Android 仿IOS的PopupWindow和通用BasePopupWindow搭建

截图

Android 仿IOS的PopupWindow和通用BasePopupWindow搭建_第1张图片
pw.png

实现

1、BasePopupWindow.java

1.1、实现动态加载不同layout
1.2、动态配置是否弹出后背景半透明,关闭时候恢复(监听ondismiss,靠window类来变色)
1.3、一些基础性的方法抽象方法
1.4、为了更加复杂的样式和动效,可以继续扩展此类

/**
 * Created by wujn on 2018/10/29.
 * Version : v1.0
 * Function: base popuwindow
 */
public abstract class BasePopupWindow extends PopupWindow implements View.OnClickListener{

    /**
     * 上下文
     */
    protected Context context;
    /**
     * 最上边的背景视图
     */
    private View vBgBasePicker;
    /**
     * 内容viewgroup
     */
    private LinearLayout llBaseContentPicker;

    public BasePopupWindow(Context context) {
        super(context);
        this.context = context;
        View parentView = View.inflate(context, R.layout.base_popup_window_picker, null);
        vBgBasePicker = parentView.findViewById(R.id.v_bg_base_picker);
        llBaseContentPicker = (LinearLayout) parentView.findViewById(R.id.ll_base_content_picker);
        /***
         * 添加布局到界面中
         */
        llBaseContentPicker.addView(View.inflate(context, bindLayout(), null));
        setContentView(parentView);
        //设置PopupWindow弹出窗体的宽
        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        //设置PopupWindow弹出窗体的高
        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        //在PopupWindow里面就加上下面代码,让键盘弹出时,不会挡住pop窗口。
        this.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        setFocusable(true);//设置获取焦点
        setTouchable(true);//设置可以触摸
        setOutsideTouchable(true);//设置外边可以点击
        ColorDrawable dw = new ColorDrawable(0xffffff);
        setBackgroundDrawable(dw);
        //设置SelectPicPopupWindow弹出窗体动画效果
        this.setAnimationStyle(R.style.BottomDialogWindowAnim);
        initView(parentView);
        initData();
        initListener();
        vBgBasePicker.setOnClickListener(this);
        //是否需要屏幕半透明
        setBackgroundHalfTransition(isNeedBackgroundHalfTransition());
    }

    /**
     * 初始化布局
     *
     * @return
     */
    protected abstract int bindLayout();

    /**
     * 初始化view
     *
     * @param parentView
     */
    protected abstract void initView(View parentView);

    /**
     * 初始化数据
     */
    protected abstract void initData();

    /**
     * 初始化监听
     */
    protected abstract void initListener();





    /**
     * 为了适配7.0系统以上显示问题(显示在控件的底部)
     *
     * @param anchor
     */
    @Override
    public void showAsDropDown(View anchor) {
        if (Build.VERSION.SDK_INT >= 24) {
            Rect rect = new Rect();
            anchor.getGlobalVisibleRect(rect);
            int h = anchor.getResources().getDisplayMetrics().heightPixels - rect.bottom;
            setHeight(h);
        }
        super.showAsDropDown(anchor);
        if(isNeedBgHalfTrans){
            backgroundAlpha(0.5f);
        }
    }

    /**
     * 展示在屏幕的底部
     *
     * @param layoutid rootview
     */
    public void showAtLocation(@LayoutRes int layoutid) {
        showAtLocation(LayoutInflater.from(context).inflate(layoutid, null),
                Gravity.TOP | Gravity.CENTER_HORIZONTAL, 0, 0);
        if(isNeedBgHalfTrans){
            backgroundAlpha(0.5f);
        }
    }


    /**
     * 最上边视图的点击事件的监听
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.v_bg_base_picker:
                dismiss();
                break;
        }
    }

    /**
     * 是否设置背景半透明
     * */
    public boolean isNeedBackgroundHalfTransition(){
        return false;
    }

    private boolean isNeedBgHalfTrans = false;
    private void setBackgroundHalfTransition(boolean isNeed){
        isNeedBgHalfTrans = isNeed;
        if(isNeedBgHalfTrans){
            this.setOnDismissListener(new OnDismissListener() {
                @Override
                public void onDismiss() {
                    backgroundAlpha(1f);
                }
            });
        }
    }

    /**
     * 设置添加屏幕的背景透明度
     * @param bgAlpha
     */
    private void backgroundAlpha(float bgAlpha) {
        WindowManager.LayoutParams lp = ((Activity)context).getWindow().getAttributes();
        lp.alpha = bgAlpha; //0.0-1.0
        ((Activity)context).getWindow().setAttributes(lp);
    }


}
2、base_popup_window_picker.xml



    

    

3、进入和退出时候的动画style

    
    

进入动画:popup_bottom_enter_anim.xml



    
    

退出动画:popup_bottom_exit_anim.xml



    
    


4、仿IOS的layout:popup_window_album_or_camera.xml



    

        

item的背景style



    
    
    

5、仿IOS的popuwindow类:AlbumOrCameraPopupWindow
public class AlbumOrCameraPopupWindow extends BasePopupWindow {

    private Button btnCamera;
    private Button btnAlbum;
    private Button btnCancel;

    private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener;
    public AlbumOrCameraPopupWindow(Context context,OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener) {
        super(context);
        this.onCameraOrAlbumSelectListener = onCameraOrAlbumSelectListener;
    }

    @Override
    public boolean isNeedBackgroundHalfTransition(){
        return true;
    }

    @Override
    protected int bindLayout() {
        return R.layout.popup_window_album_or_camera;
    }

    @Override
    protected void initView(View parentView) {
        btnCamera = (Button) parentView.findViewById(R.id.btnCamera);
        btnAlbum = (Button) parentView.findViewById(R.id.btnAlbum);
        btnCancel = (Button) parentView.findViewById(R.id.btnCancel);
    }

    @Override
    protected void initData() {

    }

    @Override
    protected void initListener() {
        btnCamera.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                if(onCameraOrAlbumSelectListener != null){
                    onCameraOrAlbumSelectListener.OnSelectCamera();
                }
            }
        });

        btnAlbum.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
                if(onCameraOrAlbumSelectListener != null){
                    onCameraOrAlbumSelectListener.OnSelectAlbum();
                }
            }
        });

        btnCancel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dismiss();
            }
        });
    }

}

选择相机或者相册的监听接口

public interface OnCameraOrAlbumSelectListener {
    public void OnSelectCamera();
    public void OnSelectAlbum();
}
6、具体使用
private AlbumOrCameraPopupWindow ACWindow;
    private void initListener(){
        ACWindow = new AlbumOrCameraPopupWindow(this, onCameraOrAlbumSelectListener);
        btnIosPopupWindow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(ACWindow != null && !ACWindow.isShowing()){
                    ACWindow.showAtLocation(R.layout.activity_view_popup_window);
                }
            }
        });
    }

    /**选择相机或者相册*/
    private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener = new OnCameraOrAlbumSelectListener() {
        @Override
        public void OnSelectCamera() {
            LogUtil.i("OnSelectCamera...");
            ToastUtil.showShort(instance, "相机");
        }

        @Override
        public void OnSelectAlbum() {
            LogUtil.i("OnSelectAlbum...");
            ToastUtil.showShort(instance, "从相册中选择");
        }
    };

朝CV工程师又进一步~~~


2018/11/05 更新: BasePopupWindow.java 优化:
  • 1、先initData在initListener ,比较好一点
  • 2、protected context,子类有可能也需要用到,有时候需要加recyleview

你可能感兴趣的:(Android 仿IOS的PopupWindow和通用BasePopupWindow搭建)