首页 热点专区 小学知识 中学知识 出国留学 考研考公
您的当前位置:首页正文

自定义View监听同级View状态

来源:要发发知识网

需求是这样的:

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

难点

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

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

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

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

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

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

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

此时,需求就变得简单了,在尝试了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。

显示全文