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,这个看起来肯定很难,毕竟看起来好像很难的样子,但是实际使用时,沉下心,一切问题就有不太大了.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值