自定义View监听同级View状态

2017-01-14 10:04:39来源:http://www.jianshu.com/p/2dc8e23687f9作者:KiSoo人点击

第七城市
需求是这样的:


需要自定义一个控件来检测EditEext的状态
在xml中自己写属性,传入EditText的Id
尽量减少在Activity中的代码量,降低耦合度


难点


在这之前,不知道属性中可以直接传入id
拿到id后,无可以findViewById的实例
获取到的EditText和Activity中的EditText不是同一个实例


首先,我们自定义一个属性,暂且称之为bind_view



`JMU(MB%@NR0P8RV]W9L9GG.png

在xml文件中引用,并将我们所需要绑定的EditText的Id传入



`W5I[N}BQR[L%8QK2M0)]V4.png


起初,我是抱着试一试的心态来做这个的,在R文件中,我看到我们所绑定的Edittext的Id如下:



9XTNK0R8HF$6EQ0)VNV{7QP.png

在我们所写的自定义view的构造函数中,获取TypedArray


final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.TextBindView);

在debug模式下看到,我们传入的id在TypedArray中



4]V_})Q@4HMIKLVX}_X6CA4.png

此时,需求就变得简单了,在尝试了getInt,getType未果之后,我们使用了getResourceId获取到了真正的绑定的EditText的Id


int resId = ta.getResourceId(R.styleable.TextBindView_bind_view, 0);

突然发现,我们所绑定的View不是我们自定义View的子View,而View的findViewById是向下遍历,此时机智的我想到了再定义一个属性



J(PAANH1T0913OHPZB%ZNAK.png

通过这个属性,传入layout,通过layout来findViewById


app:parent_view="@layout/activity_main"

然而,此时发现,在构造函数中是无法View.inflate的,真是个悲伤的故事,通过上网查阅资料,知道这是由于生命周期的缘故,想要inflate,必须在onAttachedToWindow方法中进行,于是我将函数迁移至onAttachedToWindow方法中。


在这里,我们成功的获得了我们所绑定的EditText,并且获取到了text,此时,我想在这里给EditText设置一个textWatcher,事情就大功告成了,结果并不尽如人意。


给Edittext设置textWatcher后,发现改变Edittext的内容没有什么卵用。让我一度怀疑人生了,再使用settext同样没有什么用,仔细思考之后,认为:


通过View.inflate来获取到的ViewRoot,再进行findViewById所得到的View,和我们Activity通过setContentView绘制出的View并不是同一个View。这段话可能有点绕,总的来说就是一句话,setContentView和inflater加载出来的是两个不同的实例。


此时,事情又回到刚开始了,难道真的要在activity给我们所自定义的View添加一个要监听的EditText吗?


秉着没有代码做不到的事情,我上网查阅资料得出:



同一个activity 通过findViewById来获取到的View 永远都是同一个View



第二点也是最重要的一点,View中的context其实是Activity向上转型得到的,我们只需要将其向下转型即可得到当前界面的activity



最终,我们直接根据得到的resId,使用activity.findViewById来获取我们绑定的Edittext。



CB7_SCQ(_0DY}M(%TENE%~X.png

此时,我们终于达成了本次自定义View的最终需求。成功在xml中传入绑定的Id来监听edittext。



]JRBLCPHN0N_4EN09F)RBH7.png

我是KiSoo
我的心愿是没有bug




第七城市

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台