Android再也不用findViewById、butterKnife(DecorView视图树揭秘)

(本文未借鉴任何资料,有不足望指教)

我比较喜欢偷懒,所以想着通过getViewAt的方法免去我们繁琐的命名工作,并且提升一波布局可重用性。


Fragment挺好的,他通过inflate出来一个View,你想要获取你布局中的控件,直接getViewAt就可以。

但是Activity不一样,他是setContentView的形式,你就得不到布局的根布局实例了。


怎么办?


开发艺术探索上在讲事件分发的时候,讲了事件是先分发给activity,再传给window,再给decorview的。所以尝试性地获取了下,成功了。

ViewGroup mDecorView =(ViewGroup)this.getWindow().getDecorView();


接下来的工作就简单了,我每获取一个孩子,就获取他的孩子数量,再一个个getChildAt,弄明白了到底有啥东西。

我的工作是这样的

protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ViewGroup mDecorView =(ViewGroup)this.getWindow().getDecorView();

        ViewGroup mOne = (ViewGroup) mDecorView.getChildAt(0);//LinearLayout

//        ViewGroup mOneOne = (ViewGroup) mOne.getChildAt(0);//ViewStub
        ViewGroup mOneTwo = (ViewGroup) mOne.getChildAt(1);//FrameLayout

        ViewGroup mOneTwoOne = (ViewGroup) mOneTwo.getChildAt(0);//ActionBarOverlayLayout

        ViewGroup mOneTwoOneOne = (ViewGroup) mOneTwoOne.getChildAt(0);//ContentFrameLayout(他的孩子就是我们的布局)
        ViewGroup mOneTwoOneTwo = (ViewGroup) mOneTwoOne.getChildAt(1);//ActionBarContainer

        View mOneTwoOneTwoOne =  mOneTwoOneTwo.getChildAt(0);//ToolBar
        View mOneTwoOneTwoTwo = mOneTwoOneTwo.getChildAt(1);//ActionBarContextView
    }


所以我根据获得的信息,画一个层级树(window不是view,所以不画进去了)



可是这样一来要get好多好多次,可能性能会有损耗,不过确实是一个免掉fvb的好办法。

另外一种方法是直接给你布局的根布局butterknife或者fvb,然后你从以这个根布局为基础开始getChildAt即可。

最后一种方法其实和碎片一样,setContentView还有接受另外参数的方法:

LayoutInflater inflater = LayoutInflater.from(this);
View v = inflater.inflate(R.layout.activity_main, null, false);
setContentView(v);


两种方式都很好。只不过问题也有,你fvb是绑定的,控件可以随便移动。而getChildAt的方法就在这种情况下会出问题。不过个人还是更喜欢getChildAt的方式,因为我的出发点是xml布局和java代码降低联系。(考虑这样一种风趣的情况,xml是别人设计的,你要的东西他都有,但是我和他吵架了,他就是不给你看,也不准你用插件,怎么办?我会采取bfs或者dfs的方式遍历视图 树,从而获取我想要的控件(哼,给我使绊子也没用!))萝卜青菜,各有所爱。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值