封裝使用PopupWindow彈出窗口(一)

引用

??現(xiàn)如今很多軟件都有個人中心,而個人中心往往都用來設(shè)置個人信息奋姿,一般的個人中心包括:用戶頭像,用戶名素标,以及其他的業(yè)務(wù)邏輯需要的集合称诗。今天我們就來封裝彈出窗口PopupWindow,點擊更換頭像就是很經(jīng)典的例子头遭。


介紹

??PopupWindow用來做彈出框并不是獨一份寓免,一般系統(tǒng)使用的是另一種,我們很多軟件的消息通知其實都是用AlertDialog计维,但PopupWindow好就好在它足夠靈活袜香,可以適應(yīng)很多自定義的彈出框環(huán)境。


本期效果

popupwindow示例.gif

區(qū)別

(1)AlertDialog不能指定顯示的位置享潜,只能默認(rèn)顯示在屏幕最中間困鸥。而
PopupWindow是可以指定顯示位置的,隨便哪個位置都可以,更加靈活疾就。
(2)AlertDialog是非阻塞線程式對話框:AlertDialog彈出時澜术,后臺還可以做事情;而PopupWindow是阻塞線程式對話框:PopupWindow彈出時猬腰,程序會等待鸟废,在PopupWindow退出前,程序一直等待姑荷,只有當(dāng)我們調(diào)用了dismiss方法的后盒延,PopupWindow退出,程序才會向下執(zhí)行鼠冕。
這兩種區(qū)別的表現(xiàn)是:
??AlertDialog彈出時添寺,背景是黑色的,但是當(dāng)我們點擊背景懈费,AlertDialog會消失计露,證明程序不僅響應(yīng)AlertDialog的操作,還響應(yīng)其他操作憎乙,其他程序沒有被阻塞票罐,這說明了AlertDialog是非阻塞式對話框;PopupWindow彈出時泞边,背景沒有什么變化该押,但是當(dāng)我們點擊背景的時候,程序沒有響應(yīng)阵谚,只允許我們操作PopupWindow蚕礼,其他操作被阻塞。
(3)PopupWindow的位置按照有無偏移分椭蹄,可以分為偏移和無偏移兩種闻牡;按照參照物的不同净赴,可以分為相對于某個控件(Anchor錨)和相對于父控件绳矩。


用法

第一步:布局文件

(1)主布局:activity_case22.xml

說明:我簡單添加了一個居中的按鈕點擊事件來處理彈出popupwindow。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/case22_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".show.Case22"
    tools:ignore="MissingConstraints">

        <androidx.appcompat.widget.Toolbar
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:titleTextColor="@color/white"
            android:background="@color/green"
            app:title="PopupWindow使用" />

        <Button
            android:id="@+id/show_popupWindow"
            android:layout_width="match_parent"
            android:textAllCaps="false"
            android:layout_height="wrap_content"
            android:text="彈出PopupWindow"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintBottom_toBottomOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>

(2)子布局:popup_select_layout.xml

說明:這里是比較常用的彈出框玖翅,拍照+相冊+取消翼馆,View用作分割線。

<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:ignore="MissingConstraints">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/white"
        app:layout_constraintBottom_toBottomOf="parent">

        <Button
            android:id="@+id/take_photo"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@drawable/button_round_style"
            android:gravity="center"
            android:text="拍照"
            android:textColor="@color/black"
            android:textSize="20sp" />

        <View
            android:id="@+id/divide1"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/black"
            app:layout_constraintTop_toBottomOf="@id/take_photo" />

        <Button
            android:id="@+id/picture"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@drawable/button_round_style"
            android:gravity="center"
            android:text="相冊"
            android:textColor="@color/black"
            android:textSize="20sp"
            app:layout_constraintTop_toBottomOf="@id/divide1" />

        <View
            android:id="@+id/divide2"
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:background="@color/black"
            app:layout_constraintTop_toBottomOf="@id/picture" />

        <Button
            android:id="@+id/cancel"
            android:layout_width="match_parent"
            android:layout_height="40dp"
            android:background="@drawable/button_round_style"
            android:gravity="center"
            android:text="取消"
            android:textColor="@color/black"
            android:textSize="20sp"
            app:layout_constraintTop_toBottomOf="@id/divide2" />

    </androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

第二步:創(chuàng)建TestPopupWindow類

繼承自PopupWindow類金度。

/**
 * @data on 2020/9/14 9:18 AM
 * @auther  ArmStrong
 * @describe
 */
public class TestPopupWindow extends PopupWindow {
    TestDataListener mTestDataListener;
    int type = 0;


    public TestPopupWindow(Context context) {
        super(context);
        View contentView = LayoutInflater.from(context).inflate(R.layout.popup_select_layout, null);
        //封裝成CommonPopupWindow類
        setContentView(contentView);
        setWidth(ViewGroup.LayoutParams.MATCH_PARENT);
        setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
        setFocusable(true);
        setBackgroundDrawable(new BitmapDrawable());
        setOutsideTouchable(true);
        setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
            }
        });

        //初始化控件
        TextView takePhoto = (TextView)contentView.findViewById(R.id.take_photo);
        TextView picture = (TextView)contentView.findViewById(R.id.picture);
        TextView cancel = (TextView)contentView.findViewById(R.id.cancel);

        takePhoto.setOnClickListener((View)->{
            Log.i("TestPopupWindow: ","拍照");
            type = 0;
            if(mTestDataListener != null){
                mTestDataListener.getTestData(type);
            }
            dismiss();
        });

        picture.setOnClickListener((View)->{
            Log.i("TestPopupWindow: ","相冊");
            type = 1;
            if(mTestDataListener != null){
                mTestDataListener.getTestData(type);
            }
            dismiss();
        });
        cancel.setOnClickListener((View)->{
            Log.i("TestPopupWindow: ","取消");
            type = 2;
            if(mTestDataListener != null){
                mTestDataListener.getTestData(type);
            }
            dismiss();
        });
    }
    //回調(diào)事件接口
    public interface TestDataListener {
        void getTestData(int type);
    }

    public void setTestClickaListener(TestDataListener testDataListener) {
        mTestDataListener = testDataListener;
    }
}

第三步:在Activity中使用

public class Case22 extends AppCompatActivity {
    TestPopupWindow popupWindow;
    Button btnShowPopupWindow;

    @SuppressLint("ResourceType")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_case22);
        ConstraintLayout case22Layout = findViewById(R.id.case22_layout); //主布局設(shè)置彈出窗口定位使用
        btnShowPopupWindow = findViewById(R.id.show_popupWindow);
        showPopupWindow(case22Layout);

    }
    //展示彈出窗口
    private void showPopupWindow(View parent){
        btnShowPopupWindow.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow = new TestPopupWindow(getApplicationContext());
                popupWindow.showAtLocation(parent, Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL, 0, 0);//在activity的底部展示应媚。
//            popupWindow.showAsDropDown(binding.showPopupWindow); //在某個控件下方彈出Popupwindow
            popupWindow.setTestClickaListener(new TestPopupWindow.TestDataListener() {
                @Override
                public void getTestData(int type) {
                    Log.d("test: ", String.valueOf(type)); //測試
                    switch (type){
                        case 0:  //拍照
                            Toast.makeText(getBaseContext(),"拍照",Toast.LENGTH_SHORT).show();
                            break;
                        case 1:  //相冊
                            Toast.makeText(getBaseContext(),"相冊",Toast.LENGTH_SHORT).show();
                            break;
                        case 2:  //取消
                            Toast.makeText(getBaseContext(),"取消",Toast.LENGTH_SHORT).show();
                            break;
                    }
                }
            });
            }
        });
    }
}

大功告成!

解析

第一:封裝的思想
??我們都知道Java語言的三個特點:封裝繼承和多態(tài)猜极。但我們一直以來在定義PopupWindow時中姜,都是在new其對象的時候在activity中調(diào)用其實例化對象的set方法來設(shè)置popupWindow的屬性,從而實現(xiàn)我們的業(yè)務(wù),但這種封裝并不徹底丢胚。
??為了體現(xiàn)徹底的封裝思想翩瓜,我們在這里自定義了TestPopupWindow類并繼承自PopupWindow,在其類中構(gòu)造方法里設(shè)置携龟,每當(dāng)在activity中new一個對象兔跌,這些屬性就會被設(shè)置,一個封裝峡蟋,實現(xiàn)多處的代碼復(fù)用坟桅,同時有效地簡化了Activity的代碼。

第二:定義其彈出位置
??PopupWindow可以靈活地定義其顯示的位置蕊蝗,一種方式是絕對定位:采用showAtLocation()方法仅乓,它有四個參數(shù),分別是View蓬戚,Gravity方灾,x,y碌更,父布局+位置+偏移量裕偿。本例中我們讓其位于父布局的底部并且水平居中Gravity.BOTTOM|Gravity.CENTER_HORIZONTAL。

??另一中方式是相對定位:采用showAsDropDown()方法痛单,它用來定義顯示PopupWindow在某個控件之下彈出嘿棘。


效果圖

PopupWindow彈出框.jpeg

千夜零一:“之前總是看各種博客學(xué)習(xí)東西,現(xiàn)在我想用博客記錄下我的學(xué)習(xí)腳步旭绒,好東西也需要分享鸟妙,索取和給予是相互的。以后會盡量日更的挥吵!目標(biāo)完成1001篇博客哈哈重父。”
??如果覺得對你有所幫助忽匈,請不要吝嗇你的點贊房午,有問題也可以在下方評論區(qū)留言哦,關(guān)注我一起學(xué)習(xí)吧~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末丹允,一起剝皮案震驚了整個濱河市郭厌,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雕蔽,老刑警劉巖折柠,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異批狐,居然都是意外死亡扇售,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來承冰,“玉大人嘱根,你說我怎么就攤上這事∠镄福” “怎么了该抒?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長顶燕。 經(jīng)常有香客問我凑保,道長,這世上最難降的妖魔是什么涌攻? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任欧引,我火速辦了婚禮,結(jié)果婚禮上恳谎,老公的妹妹穿的比我還像新娘芝此。我一直安慰自己,他們只是感情好因痛,可當(dāng)我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布婚苹。 她就那樣靜靜地躺著,像睡著了一般鸵膏。 火紅的嫁衣襯著肌膚如雪膊升。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天谭企,我揣著相機與錄音廓译,去河邊找鬼。 笑死债查,一個胖子當(dāng)著我的面吹牛非区,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盹廷,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼征绸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了速和?” 一聲冷哼從身側(cè)響起歹垫,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎颠放,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體吭敢,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡碰凶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片欲低。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡辕宏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出砾莱,到底是詐尸還是另有隱情瑞筐,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布腊瑟,位于F島的核電站聚假,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏闰非。R本人自食惡果不足惜膘格,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望财松。 院中可真熱鬧瘪贱,春花似錦、人聲如沸辆毡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽舶掖。三九已至喷户,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間访锻,已是汗流浹背褪尝。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留期犬,地道東北人河哑。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像龟虎,于是被迫代替她去往敵國和親璃谨。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,066評論 2 355