Android 仿IOS的PopupWindow和通用BasePopupWindow搭建

截圖

pw.png

實(shí)現(xiàn)

1、BasePopupWindow.java

1.1井厌、實(shí)現(xiàn)動(dòng)態(tài)加載不同layout
1.2秒赤、動(dòng)態(tài)配置是否彈出后背景半透明,關(guān)閉時(shí)候恢復(fù)(監(jiān)聽ondismiss痹愚,靠window類來變色)
1.3富岳、一些基礎(chǔ)性的方法抽象方法
1.4蛔糯、為了更加復(fù)雜的樣式和動(dòng)效,可以繼續(xù)擴(kuò)展此類

/**
 * 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;
    /**
     * 內(nèi)容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);
        //設(shè)置PopupWindow彈出窗體的寬
        this.setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        //設(shè)置PopupWindow彈出窗體的高
        this.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        //在PopupWindow里面就加上下面代碼窖式,讓鍵盤彈出時(shí)蚁飒,不會(huì)擋住pop窗口。
        this.setInputMethodMode(PopupWindow.INPUT_METHOD_NEEDED);
        this.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
        setFocusable(true);//設(shè)置獲取焦點(diǎn)
        setTouchable(true);//設(shè)置可以觸摸
        setOutsideTouchable(true);//設(shè)置外邊可以點(diǎn)擊
        ColorDrawable dw = new ColorDrawable(0xffffff);
        setBackgroundDrawable(dw);
        //設(shè)置SelectPicPopupWindow彈出窗體動(dòng)畫效果
        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);

    /**
     * 初始化數(shù)據(jù)
     */
    protected abstract void initData();

    /**
     * 初始化監(jiān)聽
     */
    protected abstract void initListener();





    /**
     * 為了適配7.0系統(tǒng)以上顯示問題(顯示在控件的底部)
     *
     * @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);
        }
    }


    /**
     * 最上邊視圖的點(diǎn)擊事件的監(jiān)聽
     *
     * @param v
     */
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.v_bg_base_picker:
                dismiss();
                break;
        }
    }

    /**
     * 是否設(shè)置背景半透明
     * */
    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);
                }
            });
        }
    }

    /**
     * 設(shè)置添加屏幕的背景透明度
     * @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淮逻、進(jìn)入和退出時(shí)候的動(dòng)畫style
<!--animanation-->
    <!-- 底部的dialog彈出的動(dòng)畫樣式-->
    <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>

進(jìn)入動(dòng)畫: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>

退出動(dòng)畫: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();
            }
        });
    }

}

選擇相機(jī)或者相冊的監(jiān)聽接口

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);
                }
            }
        });
    }

    /**選擇相機(jī)或者相冊*/
    private OnCameraOrAlbumSelectListener onCameraOrAlbumSelectListener = new OnCameraOrAlbumSelectListener() {
        @Override
        public void OnSelectCamera() {
            LogUtil.i("OnSelectCamera...");
            ToastUtil.showShort(instance, "相機(jī)");
        }

        @Override
        public void OnSelectAlbum() {
            LogUtil.i("OnSelectAlbum...");
            ToastUtil.showShort(instance, "從相冊中選擇");
        }
    };

朝CV工程師又進(jìn)一步~~~??


2018/11/05 更新: BasePopupWindow.java 優(yōu)化:
  • 1、先initData在initListener 强窖,比較好一點(diǎn)
  • 2凸椿、protected context,子類有可能也需要用到翅溺,有時(shí)候需要加recyleview
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末脑漫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子咙崎,更是在濱河造成了極大的恐慌优幸,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件褪猛,死亡現(xiàn)場離奇詭異网杆,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)伊滋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門碳却,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人笑旺,你說我怎么就攤上這事昼浦。” “怎么了筒主?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵关噪,是天一觀的道長。 經(jīng)常有香客問我乌妙,道長使兔,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任藤韵,我火速辦了婚禮虐沥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘泽艘。我一直安慰自己置蜀,他們只是感情好奈搜,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著盯荤,像睡著了一般馋吗。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上秋秤,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天宏粤,我揣著相機(jī)與錄音,去河邊找鬼灼卢。 笑死绍哎,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的鞋真。 我是一名探鬼主播崇堰,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼涩咖!你這毒婦竟也來了海诲?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤檩互,失蹤者是張志新(化名)和其女友劉穎特幔,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體闸昨,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蚯斯,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饵较。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拍嵌。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖循诉,靈堂內(nèi)的尸體忽然破棺而出横辆,到底是詐尸還是另有隱情,我是刑警寧澤打洼,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站逆粹,受9級特大地震影響募疮,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜僻弹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一阿浓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蹋绽,春花似錦芭毙、人聲如沸筋蓖。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粘咖。三九已至,卻和暖如春侈百,著一層夾襖步出監(jiān)牢的瞬間瓮下,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工钝域, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留讽坏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓例证,卻偏偏與公主長得像路呜,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子织咧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348