Android :使用ViewTreeObserver進行監聽測繪頁面

前一段時間,項目中有一個頁面,如圖所示
在這裏插入圖片描述在這裏插入圖片描述
圖片中的最下方的按鈕,取消預約,這兩個按鈕,在正常的頁面中是正常顯示的,但是會出現頭部的ToolBar會被頂出頁面,也就是在彈出輸入框的時候,然後測試小夥伴就給我提了bug,沒有辦法,只好去尋找解決辦法;
1.最開始尋找的解決辦法,就是在androidMnifest,清淡文件中加入
"android:windowSoftInputMode="adjustPan|stateHidden"
,但是沒啥用啊,後來又詳細的查看了相對應的其他幾個參數,也都挨個試驗了,最後失敗;只好再次去另尋他法
2.第二個方法就是進行讓整個頁面進行滑動,NestedScrollView使用相關的,將整個頁面除了toolbar,都包裹進去,然後在彈出輸入框的時候進行頁面的整體調整,最後勉強通過測試,但是展示效果不理想,而且按鈕也跟着滑動,明顯的不符合自己的需求;
3.實在沒有辦法了,繼續百度,找方法吧;然後就找到了本片文章的主題ViewTreeObserver,
ViewTreeObserver 註冊一個觀察者來監聽視圖樹,當視圖樹的佈局、視圖樹的焦點、視圖樹將要繪製、視圖樹滾動等發生改變時,ViewTreeObserver都會收到通知,ViewTreeObserver不能被實例化,可以調用View.getViewTreeObserver()來獲得。
官方文檔的描述ViewTreeObserver是用來監聽一些全局變化的。

	在 ViewTreeObserver 中,包含了以下幾個接口:
	interface ViewTreeObserver.OnGlobalFocusChangeListener
	interface ViewTreeObserver.OnGlobalLayoutListener
	interface ViewTreeObserver.OnPreDrawListener
	interface ViewTreeObserver.OnScrollChangedListener
	interface ViewTreeObserver.OnTouchModeChangeListener

具體的使用方法

		View decorView = getWindow().getDecorView();
        View contentView = findViewById(Window.ID_ANDROID_CONTENT);
        decorView.getViewTreeObserver().addOnGlobalLayoutListener(getGlobalLayoutListener(decorView, contentView));

在這裏開始進行監聽的編寫,然後實現對應的監聽方法,對其中的對應的數據contentView.setPadding,設置好他的偏移量,這樣就可以在彈出輸入框的時候,不會讓我們的toolbar被頂上去,也不會遮擋住我們的EditText,而且按鈕也不會被遮蓋

private ViewTreeObserver.OnGlobalLayoutListener getGlobalLayoutListener(final View decorView, final View contentView) {
        return () -> {
            Rect r = new Rect();
            decorView.getWindowVisibleDisplayFrame(r);
            int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
            int diff = height - r.bottom;
            if (diff != 0) {
                if (contentView.getPaddingBottom() != diff) {
                   	contentView.setPadding(0, 0, 0, diff);
           		} else {
                  	contentView.setPadding(0, 0, 0, 0);
            }
        };
    }

然後在我以爲大功告成的時候,我們的測試小夥伴又提bug了,在小米的劉海屏手機上在這裏插入圖片描述
這兩個按鈕,只展示了頭部的一丟丟,取消 和預約按鈕的字基本都看出出來;這就很煩人,但是沒有辦法之後繼續加判斷
這裏獲取是不是小米的機型判斷

		public static boolean isMiui() {
        	String manufacturer = Build.MANUFACTURER;
        	//這個字符串可以自己定義,例如判斷華爲就填寫huawei,魅族就填寫meizu
        	return !"xiaomi".equalsIgnoreCase(manufacturer);
        }

然後在ViewTreeObserver之中加上相關的判斷,然後大功告成

private ViewTreeObserver.OnGlobalLayoutListener getGlobalLayoutListener(final View decorView, final View contentView) {
        return () -> {
            Rect r = new Rect();
            decorView.getWindowVisibleDisplayFrame(r);
            int height = decorView.getContext().getResources().getDisplayMetrics().heightPixels;
            int diff = height - r.bottom;
            if (diff != 0) {
                if (contentView.getPaddingBottom() != diff) {
                    if (isMiui()) {
                        contentView.setPadding(0, 0, 0, diff);
                    }else{
                        contentView.setPadding(0, 0, 0, 0);
                    }
                }
            } else {
                if (contentView.getPaddingBottom() != 0) {
                    contentView.setPadding(0, 0, 0, 0);
                }
            }
        };
    }

開始以爲ViewTreeObserver,這個看起來肯定很難,畢竟看起來好像很難的樣子,但是實際使用時,沉下心,一切問題就有不太大了.

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