5分鐘搞定PopUpWindow

1e97da0737325a6483ccfebbe0ed9c36da93a5137961c-1j0DuG_fw658.png

前言

最近在項(xiàng)目中用到了 PopUpWindow砸脊,并且在機(jī)型適配時(shí)發(fā)現(xiàn)華為等具有虛擬按鍵的手機(jī)在橫屏狀態(tài)時(shí)會(huì)造成 PopUpWindow 顯示位置偏移的情況存在畜隶,最后完美解決了這個(gè)問題敬矩,所以把經(jīng)驗(yàn)分享出來嚼黔,看能否對(duì)你有用引有。

彈窗有很多種實(shí)現(xiàn)方式瓣颅,例如:

  1. Dialog
  2. DialogFragment
  3. Fragment
  4. PopUpWindow
  5. ListPopUpWindow

在這些方式中,我們主要講 PopUpWindow 的使用方式譬正,因?yàn)樗茉谌我馕恢脧棾觯?這是其他方式很難做到的宫补。

PopUpWindow 是什么

從 Google 爸爸的開發(fā)文檔中我們不難看出,首先它是一個(gè) Window曾我,彈出時(shí)位于其他控件的上層粉怕。

image.png

怎么使用 PopUpWindow

  • 創(chuàng)建布局文件
  • 創(chuàng)建 ContentView
  • 設(shè)置 PopUpWindow
  • Show

創(chuàng)建布局文件

PopUpWindow 就是一個(gè)容器,是需要編寫對(duì)應(yīng)的布局文件抒巢,在項(xiàng)目需求中我們要做成這樣的效果

image.png
<com.tutu.app.view.TutuRegisterTitleView xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:background="@color/sdk_background"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/tutu_game_register_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:layout_marginTop="4dp"
        android:textAlignment="center"
        android:layout_marginBottom="6dp"
        android:textColor="#333333"
        android:textSize="17dp" />

    <View
        style="@style/TutuGameFullLandscapeLine"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"/>
</com.tutu.app.view.TutuRegisterTitleView>

創(chuàng)建 ContentView

ContentView 是我們將布局文件生成的View贫贝,并且將其放入 PopUpWindow 中。


        // 初始化popUpWindow
        linearLayout = new LinearLayout(getContext());
        // 生成 View 對(duì)象
        popRootView =  View.inflate(getContext(), 
        // PopUpWindow 傳入 ContentView
        popupWindow = new PopupWindow(popRootView, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);

設(shè)置 PopUpWindow

看到這里蛉谜,有人可能問:我們?cè)诓季治募幸呀?jīng)設(shè)置了背景顏色稚晚,為什么要在Java代碼中重復(fù)設(shè)置呢?

因?yàn)樵谀承?Andorid 系統(tǒng)版本中會(huì)出現(xiàn)點(diǎn)擊外部和返回鍵彈窗卻無法消失的 Bug型诚,所以你懂的互亮。

附上某大牛對(duì)該 Bug 的分析 PopupWindow 點(diǎn)擊外部和返回鍵無法消失背后的真相

        // 設(shè)置背景
        popupWindow.setBackgroundDrawable(new ColorDrawable());
        // 外部點(diǎn)擊事件
        popupWindow.setOutsideTouchable(true);

Show

這個(gè)就很簡(jiǎn)單摔笤,短短一行代碼,控制彈窗的顯示實(shí)際位置,難點(diǎn)在于 x敢茁,y 值的確定

            // 傳入 AnchorView 绷柒,錨點(diǎn)實(shí)際為 Window
            // Gravity.TOP 在該錨點(diǎn)的正上方
            // Gravity.LEFT 在屏幕左側(cè)
            // Gravity.NO_GRAVITY,在屏幕左上角
            // x 為坐標(biāo)系 x軸方向的偏移量哈街,左負(fù)右正
            // y 為坐標(biāo)系 y軸方向的偏移量蛉签,上負(fù)下正
            
            popupWindow.showAtLocation(view, Gravity.TOP, 0, y);
      
          
            popupWindow.showAtLocation(view, Gravity.NO_GRAVITY,x, y);

      
            popupWindow.showAtLocation(view, Gravity.TOP, 0, y);
           

怎樣使用 ListPopUpWindow

GS20180625140257.gif

和PopUpWindow 相比,它更適合展示多條數(shù)據(jù)摸柄,內(nèi)部包含了一個(gè) ListView 颤练,那就意味著需要 Adapter 進(jìn)行數(shù)據(jù)的綁定。

 listPopupWindow = new ListPopupWindow(getContext());
            // 適配器添加數(shù)據(jù)
            listPopupWindowAdapter.addAdapterList(list);
            // 添加適配器
            listPopupWindow.setAdapter(listPopupWindowAdapter);
            // 設(shè)置彈窗的大小和位置
            listPopupWindow.setWidth(width+horizontalOffset*2);
            listPopupWindow.setHeight(height);
            listPopupWindow.setAnchorView(view);
            listPopupWindow.setModal(true);
            listPopupWindow.setVerticalOffset(-VerticalOffset);
            listPopupWindow.setHorizontalOffset(-horizontalOffset*4);
            // 設(shè)置背景
            listPopupWindow.setBackgroundDrawable(
                    BitmapUtils.getDrawableFromResource(getContext(), RUtils.drawable(getContext(),"tutu_area_code_background")));

虛擬按鍵對(duì) PopUpWindow 的影響

虛擬按鍵的機(jī)型在橫屏狀態(tài)下塘幅,會(huì)造成一個(gè) x 軸方向的偏移(根據(jù)具體代碼確定)昔案,所以我們使用神器 getLocationInWindow尿贫,獲取錨點(diǎn) View 在當(dāng)前 Window 的坐標(biāo),然后通過計(jì)算確定彈窗出現(xiàn)位置踏揣。

具體決定方案庆亡,請(qǐng)看 Fucking Code

  // 獲取錨點(diǎn) View 在屏幕中的坐標(biāo)
  int[] location = new int[2];
                    back.getLocationInWindow(location);
                    
                    int x = location[0];//獲取當(dāng)前位置的橫坐標(biāo)
                    int y = location[1];//獲取當(dāng)前位置的縱坐標(biāo)

 // 豎屏不做處理
        if (VERTICAL_SCREEN == getContext().getResources().getConfiguration().orientation){
            popupWindow.showAtLocation(view, Gravity.TOP, 0, y);            
        }
        // 橫屏狀態(tài)
        else if (HORIZONTALL_SCREEN == getContext().getResources().getConfiguration().orientation) {
            // 檢測(cè)是否有虛擬按鍵
            if (checkDeviceHasNavigationBar(getContext())){

                  popupWindow.showAtLocation(view, Gravity.NO_GRAVITY,x, y);

            }else {
                popupWindow.showAtLocation(view, Gravity.TOP, 0, y);
            }
        }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市捞稿,隨后出現(xiàn)的幾起案子又谋,更是在濱河造成了極大的恐慌,老刑警劉巖娱局,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彰亥,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡衰齐,警方通過查閱死者的電腦和手機(jī)任斋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來耻涛,“玉大人废酷,你說我怎么就攤上這事∧疲” “怎么了澈蟆?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)卓研。 經(jīng)常有香客問我趴俘,道長(zhǎng),這世上最難降的妖魔是什么奏赘? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任寥闪,我火速辦了婚禮,結(jié)果婚禮上志珍,老公的妹妹穿的比我還像新娘橙垢。我一直安慰自己,他們只是感情好伦糯,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著嗽元,像睡著了一般敛纲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上剂癌,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天淤翔,我揣著相機(jī)與錄音,去河邊找鬼佩谷。 笑死旁壮,一個(gè)胖子當(dāng)著我的面吹牛监嗜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播抡谐,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼裁奇,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了麦撵?” 一聲冷哼從身側(cè)響起刽肠,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎免胃,沒想到半個(gè)月后音五,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡羔沙,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年躺涝,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片扼雏。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡诞挨,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呢蛤,到底是詐尸還是另有隱情惶傻,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布其障,位于F島的核電站银室,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏励翼。R本人自食惡果不足惜蜈敢,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望汽抚。 院中可真熱鬧抓狭,春花似錦、人聲如沸造烁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽惭蟋。三九已至苗桂,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間告组,已是汗流浹背煤伟。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人便锨。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓围辙,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親放案。 傳聞我的和親對(duì)象是個(gè)殘疾皇子姚建,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,510評(píng)論 25 707
  • ¥開啟¥ 【iAPP實(shí)現(xiàn)進(jìn)入界面執(zhí)行逐一顯】 〖2017-08-25 15:22:14〗 《//首先開一個(gè)線程,因...
    小菜c閱讀 6,358評(píng)論 0 17
  • 巴比城和巴比塔贩虾,坐落在士拿地的平原上。但是此城此塔控訴著人類以自我為忠心的生活方式沥阱,也見證著一個(gè)全人類的悲劇——口...
    Happy高興閱讀 113評(píng)論 0 0