Android 如何将一组视图分组并一起更改它们的可见性
我有一个活动,它包含两组视图,不能位于同一布局组中,但属于同一逻辑组,这意味着它们应该同时显示或隐藏并绑定单击事件。问题是我觉得写这样的东西真的很糟糕:Android 如何将一组视图分组并一起更改它们的可见性,android,kotlin,Android,Kotlin,我有一个活动,它包含两组视图,不能位于同一布局组中,但属于同一逻辑组,这意味着它们应该同时显示或隐藏并绑定单击事件。问题是我觉得写这样的东西真的很糟糕: fun hide() { view1.visibility = View.GONE view2.visibility = View.GONE view3.visibility = View.GONE // ... view9.visibility = View.GONE } fun show() {
fun hide() {
view1.visibility = View.GONE
view2.visibility = View.GONE
view3.visibility = View.GONE
// ...
view9.visibility = View.GONE
}
fun show() {
view1.visibility = View.VISIBLE
view2.visibility = View.VISIBLE
view3.visibility = View.VISIBLE
// ...
view9.visibility = View.VISIBLE
view1.setOnClickListener{ run() }
view2.setOnClickListener{ run() }
view3.setOnClickListener{ run() }
// ...
view9.setOnClickListener{ run() }
}
view.toggleVisibility()
我确实读过一篇文章,其中描述了一种科特林技能,通过某种方式将这些观点分组,然后只处理分组,从而简化了这一混乱局面,但不幸的是,我再也找不到这篇文章了
谢谢你的帮助
==========更新日期2019-07-31=========
我找到了解决方案,但忘了更新这个问题,我正在寻找的“分组”实际上不是Kotlin特有的功能,而是简单地使用vararg,我们可以使用Kotlin扩展(非常棒)来简化一些:
// assume we have a base activity or fragment, then put below functions in there
fun View.show() {
visibility = View.VISIBLE
}
fun show(vararg views: View) {
views.forEach { it.show() }
}
fun View.hide() {
visibility = View.GONE
}
fun hide(vararg views: View) {
views.forEach { it.hide() }
}
// then in any activity or fragment
show(v1, v2, v3, v4)
v9.hide()
================更新日期2020-03-07================
这正是androidx.constraintlayout.widget.Group设计的初衷,它可以从任何地方对一组视图进行逻辑分组,并且只通过更改组的可见性来控制它们的可见性 根据布局结构的不同,您可能希望在
视图组中对这些视图进行分组,如线性布局
,相对布局
,框架布局
或约束布局
然后,您可以仅在视图组上更改可见性
,其所有子项也将更改可见性
编辑:
如果不使用ViewGroup
,消除此样板文件的唯一解决方案是在项目中启用数据绑定,并将其设置为:
fun hide() {
view1.visibility = View.GONE
view2.visibility = View.GONE
view3.visibility = View.GONE
// ...
view9.visibility = View.GONE
}
fun show() {
view1.visibility = View.VISIBLE
view2.visibility = View.VISIBLE
view3.visibility = View.VISIBLE
// ...
view9.visibility = View.VISIBLE
view1.setOnClickListener{ run() }
view2.setOnClickListener{ run() }
view3.setOnClickListener{ run() }
// ...
view9.setOnClickListener{ run() }
}
view.toggleVisibility()
在您的活动/片段中:
val groupVisible = ObservableBoolean()
fun changeVisibility(show: Boolean) {
groupVisible.set(show)
}
在xml中:
<layout>
<data>
<variable name="groupVisible" type="Boolean"/>
</data>
<View
android:visibility="@{groupVisible ? View.VISIBLE : View.GONE}"/>
</layout>
如果您的视图不在视图组中,则可以使用。您可以创建一个来切换视图的可见性:
fun View.toggleVisibility() {
if (visibility == View.VISIBLE) {
visibility = View.GONE
} else {
visibility = View.VISIBLE
}
}
您可以这样使用它:
fun hide() {
view1.visibility = View.GONE
view2.visibility = View.GONE
view3.visibility = View.GONE
// ...
view9.visibility = View.GONE
}
fun show() {
view1.visibility = View.VISIBLE
view2.visibility = View.VISIBLE
view3.visibility = View.VISIBLE
// ...
view9.visibility = View.VISIBLE
view1.setOnClickListener{ run() }
view2.setOnClickListener{ run() }
view3.setOnClickListener{ run() }
// ...
view9.setOnClickListener{ run() }
}
view.toggleVisibility()
为什么不创建一个数组:
val views = arrayOf(view1, view2, view3, view4, view5, view6, view7, view8, view9)
然后:
fun show() {
views.forEach {
it.visibility = View.VISIBLE
it.setOnClickListener{ }
}
}
fun hide() {
views.forEach { it.visibility = View.INVISIBLE }
}
或者如果视图的名称确实类似于view1、view2等,则不使用数组
for (i in 1..9) {
val id = resources.getIdentifier("view$i", "id", context.getPackageName())
val view = findViewById<View>(id)
view.visibility = View.VISIBLE
view.setOnClickListener{ }
}
for(1..9中的i){
val id=resources.getIdentifier(“查看$i”,“id”,context.getPackageName())
val视图=findViewById(id)
view.visibility=view.visibility
view.setOnClickListener{}
}
您可以定义一个具有三个参数的函数,并使用vararg
如下代码:
fun changeVisiblityAndAddClickListeners(visibility: Int,
listener: View.OnClickListener,
vararg views: View) {
for (view: View in views) {
view.visibility = visibility
if (visibility == View.VISIBLE) {
view.setOnClickListener(listener)
}
}
}
当然,如果你有太多的观点,这不是一个有效的解决方案。我刚刚添加了这个代码片段,这是一种替代方法,特别是针对动态视图集的问题。首先,在xml布局中,按android:tag=“group_1”
属性对视图进行分组
然后在您的活动中使用for
循环来实现您需要的任何逻辑:
val root: ViewGroup = TODO("find your root layout")
for (i in 0 until root.childCount) {
val v = root.getChildAt(i)
when (v.tag) {
"group_1" -> {
TODO()
}
"group_2" -> {
TODO()
}
else -> {
TODO()
}
}
}
创建视图列表并在其上循环
val views = listOf<View>(view1, view2, ...)
views.forEach {
it.visibility = View.GONE
}
val views=listOf(视图1、视图2,…)
视图。forEach{
it.visibility=View.GONE
}
您还可以创建Iterable
,以简化列表视图上的任何操作
fun Iterable<View>.visibility(visibility: Int) = this.forEach {
it.visibility = visibility
}
//usage
views.visibility(View.GONE)
fun Iterable.visibility(visibility:Int)=this.forEach{
it.visibility=可见性
}
//用法
视图.可见性(视图.消失)
也许您想从XML中的标记定位所有视图。看一看,因为1.1您可以使用Group而不是LayoutGroup
。
您只需将此代码添加到XML布局中即可
<android.support.constraint.Group
android:id="@+id/profile"
app:constraint_referenced_ids="profile_name,profile_image" />
有关更多详细信息,请阅读本文您需要创建扩展函数 例如:
fun View.showGroupViews(vararg view: View) {
view.forEach {
it.show()
}
}
fun View.hideGroupViews(vararg view: View) {
view.forEach {
it.hide()
}
}
您可以创建包含子视图的
线性布局
或任何其他视图组
,并在XML文件中为其指定ID,然后在活动
或片段
类中定义这些函数:
fun disableViewGroup(viewGroup: ViewGroup) {
viewGroup.children.iterator().forEach {
it.isEnabled = false
}
}
fun enableViewGroup(viewGroup: ViewGroup) {
viewGroup.children.iterator().forEach {
it.isEnabled = true
}
}
然后在onCreate()
或onStart()
中按如下方式调用它:
disableViewGroup(idOfViewGroup)
children
方法返回ViewGroup
中的子视图
s的序列
,您可以对其进行迭代forEach
并应用任何适用于视图
s的操作
希望有帮助 将它们添加到一个单独的布局中,就像线性布局一样…@AmitJangid我希望这样简单,但是那些属于同一逻辑组的视图不能简单地添加到一个布局组中..它们都混在一起..感谢那些视图确实不在同一布局组下,但是根据你的建议,我仍然需要写xxxx.toggleVisibility()的十几行,这正是我想要避免的..对不起,伙计,我没有说清楚,问题现在更新了,那些属于同一逻辑组的视图不能放在同一布局组中。这肯定可以做到,谢谢!然而,这并不是我在那篇文章中看到的,这很重要。。犯错误让我们说kotlin有点神奇..当你可以通过GroupsHanks来创建不必要的循环时,你为什么要创建它呢!这是一个最接近我正在寻找和目前使用的,我已经更新了我在我的问题帖子中使用的解决方案。干杯。如果您正在使用androidx,请改用
androidx.constraintlayout.widget.Group