使用ConstraintLayout中的组来侦听多个视图上的单击事件

End*_*eit 23 android kotlin android-constraintlayout

基本上我想将一个OnClickListener附加到ConstraintLayout中的多个视图.

在迁移到ConstraintLayout之前,我可以添加一个监听器的一个布局内的视图.现在,它们与ConstraintLayout下的其他视图位于同一层.

我尝试将视图添加到a android.support.constraint.Group并以编程方式向其添加了OnClickListener.

group.setOnClickListener {
    Log.d("OnClick", "groupClickListener triggered")
}
Run Code Online (Sandbox Code Playgroud)

但是,从ConstraintLayout版本开始,这似乎不起作用 1.1.0-beta2

我做错了什么,有没有办法实现这种行为或者我是否需要将监听器附加到每个单一视图?

Che*_*amp 45

GroupConstraintLayout是意见只是一个松散组织AFAIK.它不是a ViewGroup,因此您将无法像使用视图时那样使用单击侦听器ViewGroup.

作为替代方案,您可以获取Group代码中成员的ID列表,并明确设置单击侦听器.(我没有找到关于此功能的官方文档,但我认为它只是落后于代码版本.)请参阅getReferencedIds 此处的文档.

Java的:

    Group group = findViewById(R.id.group);
    int refIds[] = group.getReferencedIds();
    for (int id : refIds) {
        findViewById(id).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                // your code here.
            }
        });
    }
Run Code Online (Sandbox Code Playgroud)

在Kotlin中,您可以为此构建扩展功能.

科特林:

    fun Group.setAllOnClickListener(listener: View.OnClickListener?) {
        referencedIds.forEach { id ->
            rootView.findViewById<View>(id).setOnClickListener(listener)
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后调用组上的函数:

    group.setAllOnClickListener(View.OnClickListener {
        // code to perform on click event
    })
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢扩展功能! (2认同)
  • 只是为了看起来更 kotlinish 我做了一个小改动`有趣 Group.setAllOnClickListener(listener: (View) -&gt; Unit) { referencedIds.forEach { id -&gt; rootView.findViewById&lt;View&gt;(id).setOnClickListener(listener) } }` (2认同)
  • 使用这种方法的一个问题是,我们最终会在组元素之间出现不可点击的空白,这可能会导致用户体验不佳 (2认同)

Rod*_*roz 8

为了补充Kotlin用户接受的答案,请创建扩展功能并接受lambda以使其更像API group.addOnClickListener { }

创建扩展功能:

fun Group.addOnClickListener(listener: (view: View) -> Unit) {
    referencedIds.forEach { id ->
        rootView.findViewById<View>(id).setOnClickListener(listener)
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

group.addOnClickListener { v ->
    Log.d("GroupExt", v)
}
Run Code Online (Sandbox Code Playgroud)


Rez*_*adi 6

扩展方法很棒,但您可以通过将其更改为使其变得更好

fun Group.setAllOnClickListener(listener: (View) -> Unit) {
    referencedIds.forEach { id ->
        rootView.findViewById<View>(id).setOnClickListener(listener)
    }
}
Run Code Online (Sandbox Code Playgroud)

所以调用会是这样的

group.setAllOnClickListener {
    // code to perform on click event
}
Run Code Online (Sandbox Code Playgroud)

现在不再需要显式定义 View.OnClickListener 了。

您还可以像这样为 GroupOnClickLitener 定义自己的接口

interface GroupOnClickListener {
    fun onClick(group: Group)
}
Run Code Online (Sandbox Code Playgroud)

然后定义一个像这样的扩展方法

fun Group.setAllOnClickListener(listener: GroupOnClickListener) {
    referencedIds.forEach { id ->
        rootView.findViewById<View>(id).setOnClickListener { listener.onClick(this)}
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用它

groupOne.setAllOnClickListener(this)
groupTwo.setAllOnClickListener(this)
groupThree.setAllOnClickListener(this)

override fun onClick(group: Group) {
    when(group.id){
        R.id.group1 -> //code for group1
        R.id.group2 -> //code for group2
        R.id.group3 -> //code for group3
        else -> throw IllegalArgumentException("wrong group id")
    }
}
Run Code Online (Sandbox Code Playgroud)

如果视图数量很大,则第二种方法具有更好的性能,因为您只使用一个对象作为所有视图的侦听器!


Vit*_*alk 5

侦听来自多个视图的单击事件的更好方法是在所有必需视图的顶部添加一个透明视图作为容器。该视图必须位于您执行单击所需的所有视图的末尾(即顶部)。

样品容器视图:

<View
   android:id="@+id/view_container"
   android:layout_width="0dp"
   android:layout_height="0dp"
   app:layout_constraintBottom_toBottomOf="@+id/view_bottom"
   app:layout_constraintEnd_toEndOf="@+id/end_view_guideline"
   app:layout_constraintStart_toStartOf="@+id/start_view_guideline"
   app:layout_constraintTop_toTopOf="parent"/>
Run Code Online (Sandbox Code Playgroud)

上面的示例包含其中的所有四个约束边界,我们可以添加可以一起收听的视图,并且因为它是视图,所以我们可以做任何我们想做的事情,例如涟漪效应。