Android 仿IOS的PopupWindow和通用BasePopupWindow搭建

截圖

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{

    /**
     * 上下文
     */
    private 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);
        initListener();
        initData();
        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
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <View
        android:id="@+id/v_bg_base_picker"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1" />

    <LinearLayout
        android:id="@+id/ll_base_content_picker"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:orientation="vertical" />
</LinearLayout>
3、進入和退出時候的動畫style
<!--animanation-->
    <!-- 底部的dialog彈出的動畫樣式-->
    <style name="BottomDialogWindowAnim" parent="android:Animation">
        <item name="android:windowEnterAnimation">@anim/popup_bottom_enter_anim</item>
        <item name="android:windowExitAnimation">@anim/popup_bottom_exit_anim</item>
    </style>

進入動畫:popup_bottom_enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >
    <translate
        android:duration="200"
        android:fromYDelta="100%p"
        android:toYDelta="0" />
    <alpha
        android:duration="200"
        android:fromAlpha="0.0"
        android:toAlpha="1.0" />
</set>

退出動畫:popup_bottom_exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate
        android:duration="200"
        android:fromYDelta="0"
        android:toYDelta="50%p" />
    <alpha
        android:duration="200"
        android:fromAlpha="1.0"
        android:toAlpha="0.0" />

</set>
4、仿IOS的layout:popup_window_album_or_camera.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_shape_corner_white"
        android:orientation="vertical">

        <Button
            android:id="@+id/btnCamera"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:text="拍照"
            android:textColor="@color/dodgerblue"
            android:textSize="@dimen/normal_text_size" />

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/gray_1" />


        <Button
            android:id="@+id/btnAlbum"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:text="從相冊中選擇"
            android:textColor="@color/dodgerblue"
            android:textSize="@dimen/normal_text_size" />
    </LinearLayout>


    <LinearLayout
        android:layout_marginTop="10dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@drawable/bg_shape_corner_white"
        android:orientation="vertical">

        <Button
            android:id="@+id/btnCancel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@null"
            android:text="@string/cancel"
            android:textColor="@color/dodgerblue"
            android:textSize="@dimen/normal_text_size" />

    </LinearLayout>

</LinearLayout>

item的背景style

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/white" />
    <corners android:radius="6dp"/>
    <stroke android:width="1dp" android:color="@color/gray_1" />
</shape>
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工程師又進一步~~~😆

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章