PopupWindow setOutsideTouchable(false)无效问题完美解决方案

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了PopupWindow setOutsideTouchable(false)无效问题完美解决方案相关的知识,希望对你有一定的参考价值。

参考技术A 最近遇到一个问题,在PopupWindow上有一个Edittext 需要设置setfocus(true) 才可以打开键盘输入,但是呢setOutsideTouchable(false) 设置点击外部不可关闭时又必须得setfocus(false) 这样就比较尴尬了,查了很多资料最后发现可以设置拦截的方式来解决如下

Android PopupWindow全屏


很多应用中经常可以看到弹出这种PopupWindow的效果,做了一个小demo分享一下。demo的思路是通过遍历文件,找到图片以及图片文件夹放置在PopupWindow上面。点击按钮可以弹出这个PopupWindow,这里为PopupWindow设置了动画。

PopupWindow全屏代码提要

受限需要自定义Popupwindow,这里不看Popupwindow里面要展示的内容,主要是设置Popupwindow的高度。

public class PopupwindowList extends PopupWindow 
    private int mWidth;
    private int mHeight;
    private View mContentView;
    private List<FileBean> mFileBeans;
    private ListView mListView;

    public PopupwindowList(Context context,List<FileBean> mFileBeans) 
        super(context);
        this.mFileBeans=mFileBeans;
        //计算宽度和高度
        calWidthAndHeight(context);
        setWidth(mWidth);
        setHeight(mHeight);
        mContentView= LayoutInflater.from(context).inflate(R.layout.popupwidow,null);
        //设置布局与相关属性
        setContentView(mContentView);
        setFocusable(true);
        setTouchable(true);
        setTouchable(true);
        setTouchInterceptor(new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
            //点击PopupWindow以外区域时PopupWindow消失
                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) 
                    dismiss();
                
                return false;
            
        );

    

    /**
     * 设置PopupWindow的大小
     * @param context
     */
    private void calWidthAndHeight(Context context) 
        WindowManager wm= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics= new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metrics);

        mWidth=metrics.widthPixels;
        //设置高度为全屏高度的70%
        mHeight= (int) (metrics.heightPixels*0.7);
    

点击按钮弹出PopupWindow

   mButtonShowPopup.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                //点击时弹出PopupWindow,屏幕变暗
                popupwindowList.setAnimationStyle(R.style.ListphotoSelect);
                popupwindowList.showAsDropDown(mButtonShowPopup, 0, 0);
                lightoff();

            
        );
 private void lightoff() 
        WindowManager.LayoutParams lp=getWindow().getAttributes();
        lp.alpha=0.3f;
        getWindow().setAttributes(lp);
    

一、FileBean类保存信息

FileBean如上图PopupWindow所示,需要保存文件的路径,文件夹的名称,文件夹中文件的数量,文件夹中第一张图片的路径。基本全部为set、get方法

/**
 * this class is used to record file information like the name  of the file 、the path of the file……
 *
 */
public class FileBean 
    private String  mFileName;
    private String mFilePath;
    private String mFistImgPath;
    private int mPhotoCount;

    public String getmFileName() 
        return mFileName;
    

    public void setmFileName(String mFileName) 
        this.mFileName = mFileName;
    

    public String getmFilePath() 
        return mFilePath;
    

    public void setmFilePath(String mFilePath) 
        this.mFilePath = mFilePath;
        int index=this.mFilePath.lastIndexOf(File.separator);
        mFileName=this.mFilePath.substring(index);
    

    public String getmFistImgPath() 
        return mFistImgPath;
    

    public void setmFistImgPath(String mFistImgPath) 
        this.mFistImgPath = mFistImgPath;
    

    public int getmPhotoCount() 
        return mPhotoCount;
    

    public void setmPhotoCount(int mPhotoCount) 
        this.mPhotoCount = mPhotoCount;
    

二、PopupWidow界面设置

自定义PopupWindow,

public class PopupwindowList extends PopupWindow 
    private int mWidth;
    private int mHeight;
    private View mContentView;
    private List<FileBean> mFileBeans;
    private ListView mListView;
    //观察者模式
    public interface  OnSeletedListener
        void onselected(FileBean bean);
    
    private OnSeletedListener listener;
    public void setOnSelecterListener(OnSeletedListener listener)
        this.listener=listener;
    
    public PopupwindowList(Context context,List<FileBean> mFileBeans) 
        super(context);
        this.mFileBeans=mFileBeans;
        calWidthAndHeight(context);
        setWidth(mWidth);
        setHeight(mHeight);
        mContentView= LayoutInflater.from(context).inflate(R.layout.popupwidow,null);
        setContentView(mContentView);
        setFocusable(true);
        setTouchable(true);
        setTouchable(true);
        setTouchInterceptor(new View.OnTouchListener() 
            @Override
            public boolean onTouch(View v, MotionEvent event) 
            //点击PopupWindow以外区域时PopupWindow消失
                if (event.getAction() == MotionEvent.ACTION_OUTSIDE) 
                    dismiss();
                
                return false;
            
        );
        initListView(context);
        initEvent();
    

    private void initEvent() 

    
   //初始化PopupWindow的listview
    private void initListView(Context context) 
        MyListViewAdapter adapter=new MyListViewAdapter(context,0,mFileBeans);
        mListView= (ListView) mContentView.findViewById(R.id.listview);
        mListView.setAdapter(adapter);
    

    /**
     * 设置PopupWindow的大小
     * @param context
     */
    private void calWidthAndHeight(Context context) 
        WindowManager wm= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics metrics= new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(metrics);

        mWidth=metrics.widthPixels;
        mHeight= (int) (metrics.heightPixels*0.7);
    

三、点击按钮弹出PopupWindow


public class PopupWindowTest extends AppCompatActivity 
    private Button mButtonShowPopup;
    private Set<String> mFilePath;
    private List<FileBean> mFileBeans;
    PopupwindowList popupwindowList;
    private Handler mHandler=new Handler()
        @Override
        public void handleMessage(Message msg) 
            super.handleMessage(msg);
            initPopupWindow();
        
    ;

    private void initPopupWindow() 
       popupwindowList=new PopupwindowList(this,mFileBeans);
        popupwindowList.setOnDismissListener(new PopupWindow.OnDismissListener() 
            @Override
            public void onDismiss() 
                lighton();
            
        );

    
       //PopupWindow消失时,使屏幕恢复正常
    private void lighton() 
        WindowManager.LayoutParams lp=getWindow().getAttributes();
        lp.alpha=1.0f;
        getWindow().setAttributes(lp);
    

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.popupwindowtestlayout);
        mButtonShowPopup= (Button) findViewById(R.id.button_showpopup);
        mFileBeans=new ArrayList<>();
        initData();
        initEvent();

    

    private void initEvent() 

        mButtonShowPopup.setOnClickListener(new View.OnClickListener() 
            @Override
            public void onClick(View v) 
                //点击时弹出PopupWindow,屏幕变暗
                popupwindowList.setAnimationStyle(R.style.ListphotoSelect);
                popupwindowList.showAsDropDown(mButtonShowPopup, 0, 0);
                lightoff();

            
        );
    

    private void lightoff() 
        WindowManager.LayoutParams lp=getWindow().getAttributes();
        lp.alpha=0.3f;
        getWindow().setAttributes(lp);
    
   //开启线程初始化数据,遍历文件找到所有图片文件,及其文件夹与路径进行保存。
    private void initData() 
        if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
            ToastUtils.showToast(this,"当前sdcard不用使用");
        
        new Thread()
            @Override
            public void run() 
                super.run();
                Uri imgsUri= MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                ContentResolver contentResolver=getContentResolver();
                Cursor cursor=contentResolver.query(imgsUri,null,MediaStore.Images.Media.MIME_TYPE + "=? or " + MediaStore.Images.Media.MIME_TYPE + "=?",new String[]"image/jpeg","image/png",MediaStore.Images.Media.DATA);
                mFilePath=new HashSet<>();
                while (cursor.moveToNext())
                    String path=cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA));
                    File parentfile=new File(path).getParentFile();
                    if(parentfile==null) continue;
                    String filePath=parentfile.getAbsolutePath();
                    FileBean fileBean=null;

                    if(mFilePath.contains(filePath))
                         continue;
                    else 
                        mFilePath.add(filePath);
                        fileBean=new FileBean();
                        fileBean.setmFilePath(filePath);
                        fileBean.setmFistImgPath(path);
                    
                    if(parentfile.list()==null) continue;
                     int count=parentfile.list(new FilenameFilter() 
                         @Override
                         public boolean accept(File dir, String filename) 
                             if(filename.endsWith(".jpg")||filename.endsWith(".png")||filename.endsWith(".jpeg"))

                                 return true;
                             
                             return false;
                         
                     ).length;
                    fileBean.setmPhotoCount(count);
                    mFileBeans.add(fileBean);

                

                cursor.close();
                //将mFilePath置空,发送消息,初始化PopupWindow。
                mFilePath=null;
                mHandler.sendEmptyMessage(0x110);

            
        .start();

    


四、PopupWindow动画设置。

(1)编写弹出与消失动画

①弹出动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="0"
    android:toXDelta="0"
    android:fromYDelta="100%"
    android:toYDelta="0"
    android:duration="1000"></translate>
</set>

②消失动画

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="0"
        android:toXDelta="0"
        android:fromYDelta="0"
        android:toYDelta="100%"
        android:duration="1000"></translate>
</set>

(2)设置style与调用style

①设置style

在style中进行添加

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light">
        <!-- Customize your theme here. -->
    </style>
    <style name="ListphotoSelect">
        <item name="android:windowEnterAnimation">@anim/animshow</item>
        <item name="android:windowExitAnimation">@anim/animdismiss</item>
    </style>
</resources>

②调用style

为PopupWindow设置动画style

    popupwindowList.setAnimationStyle(R.style.ListphotoSelect);

备注:布局很简单不再展示。

以上是关于PopupWindow setOutsideTouchable(false)无效问题完美解决方案的主要内容,如果未能解决你的问题,请参考以下文章

请教popupwindow点击外部关闭问题

android中popupwindow怎么把一个页面做个弹窗

使弹出popupwindow界面外部的控件不能点击

怎样自动弹出popupwindow

自定义控件(仿PopupWindow篇)

自定义控件(仿PopupWindow篇)