我們仍未知道的popWindow 7.0 8.0位置顯示錯誤
阿新 • • 發佈:2018-12-30
popWindow一個神奇的控制元件,為了記錄自己曾解決過的問題,也避免其他小哥遇到一樣的問題,故留下部落格進行記錄。
最近在寫一個下拉框的時候,測試小哥找到我說7.0,7.1,8.0的顯示效果不一致……
我當時的心情是……&¥%#&&(&
好吧,當遇這樣的問題,第一反應是不要慌……不要慌……甩鍋……不對,是分析並解決問題。由於各種原因我這裡就不上產品的效果,取而代之用一個抽取了特徵的demo來代替說明問題。(其實在驗證問題時,抽取出相關因素用demo進行還原除錯,不失為一個很好的辦法,畢竟有些工程光編譯就要7、8分鐘,你會感受到被編譯支配的恐懼。)
1、問題展示
正常效果是這樣的:
8.0手機上的效果是這樣的:
2、問題的嘗試與分析
好了,上程式碼吧。
public void popWindow(View view) { // 將佈局檔案轉換成View物件,popupview 內容檢視 View mPopView = getLayoutInflater().inflate(R.layout.pop_window_item, null); // 將轉換的View放置到 新建一個popuwindow物件中 PopupWindow mPopupWindow = new PopupWindow(mPopView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT); mPopupWindow.showAsDropDown(view); }
從程式碼上看貌似沒什麼問題,那麼我們就要考慮是否是不同api之間的問題了。
這裡經過嘗試當高度使用WRAP_CONTENT而不是MATCH_PARENT則不會出現問題,那麼我們可以猜想出showAsDropDown的anchor定位view並沒有錯,使用WRAP_CONTENT計算的起始下標為指定view的左下座標點。
public void showAsDropDown(View anchor) {
throw new RuntimeException("Stub!");
}
而MATCH_PARENT的座標起始點恐怕已經被設定成狀態列下的左上頂部座標點了吧。
3、解決方案
自定義一個繼承PopWindow的類,並複寫showAsDropDown()方法,你可以複寫showAsDropDown(View anchor),public void showAsDropDown(View anchor, int xoff, int yoff) 等方法,具體看各自呼叫的需求。
public class CompatiblePopWindow extends PopupWindow {
public CompatiblePopWindow(View contentView, int width, int height) {
super(contentView, width, height);
}
@Override
public void showAsDropDown(View anchor) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Rect compatibleFix = new Rect();
anchor.getGlobalVisibleRect(compatibleFix);
int height = anchor.getResources().getDisplayMetrics().heightPixels - compatibleFix.bottom;
this.setHeight(height);
}
super.showAsDropDown(anchor);
}
}
/**Button彈出popupWindow的點選事件
*/
public void popWindow(View view) {
// 將佈局檔案轉換成View物件,popupview 內容檢視
View mPopView = getLayoutInflater().inflate(R.layout.pop_window_item, null);
// 將轉換的View放置到 新建一個popuwindow物件中
CompatiblePopWindow popupWindow = new CompatiblePopWindow(mPopView,
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
popupWindow.showAsDropDown(view);
}
附贈一個簡單PopWindow類的封裝呼叫,該封裝類和使用demo可以下載附件獲取。
/**Button彈出popupWindow的點選事件
*/
public void popWindow(View view) {
// 將佈局檔案轉換成View物件,popupview 內容檢視
View mPopView = getLayoutInflater().inflate(R.layout.pop_window_item, null);
//附帶庫的使用方法
TomesPopWindow mPopWindow = new TomesPopWindow.PopupWindowBuilder(this)
.setView(mPopView)
.size(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)
.create()
.showAsDropDown(view,0,0);
}