Nad*_*bal 8 android visibility android-recyclerview
我有一个包含 2 个或更多查看者的 recyclerview,
CalendarView——全部在一个 viewhodler 中。问题是 CalendarView 的高度相当大,当 CalendarView 稍微离开屏幕并且我折叠/消失日历时,它会折叠但仍然占用空间,就像下面的屏幕截图一样。但奇怪的是,它只发生在Android 8 & 9.
初始屏幕截图:
问题截图(折叠简历后):
Viewholder 项目的 ClickListener:
val clickListener = View.OnClickListener {
// irrelevant code //
for (type in AllOptionsEnum.values()) {
// Expand Selected and Collapse Others
val detailView = this.root.findViewById<ViewGroup>(type.detailViewGroupId)
val labelView = this.root.findViewById<TextView>(type.labelViewId)
val checkBox = this.root.findViewById<CheckBox>(type.checkBoxId)
if (detailView.visibility == View.VISIBLE) {
// hide detailed view
detailView.setVisible(show = false)
checkBox.isChecked = false
} else {
// show
detailView.setVisible(show = (type.labelViewGroupId == it.id))
checkBox.isChecked = show = (type.labelViewGroupId == it.id)
}
// irrelevant code //
}
}
Run Code Online (Sandbox Code Playgroud)
编辑1: 扩展功能:
fun View.setVisible(show: Boolean = true, invisible: Boolean = false) {
if (show) this.visibility = View.VISIBLE
else this.visibility = if (invisible) View.INVISIBLE else View.GONE
}
Run Code Online (Sandbox Code Playgroud)
编辑2:
我尝试了另一种解决方案,即完全删除recyclerview并使用nestedscrollview重新构造整个屏幕,但它也具有相同的效果。
编辑3:
我也尝试过下面的代码,但结果相同
// show detailView
if(type==Enums.StayWithUsWidgetType.TYPE_CALENDAR){
// show detailview and children
this.calendarDetailView.children.forEach {
it.visible()
}
}
// Hide detailView and children
if(type==Enums.StayWithUsWidgetType.TYPE_CALENDAR){
// hide all
this.calendarDetailView.children.forEach {
it.gone()
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定Android Pie (2018)如何处理布局中的可见性更改,特别是具有复杂布局层次结构的 CalendarView。
但请注意,“ Android Pvisibilityawareimagebutton.setVisibility 只能从同一个库组调用”很明确:
最佳实践:
android:visibility="Gone"使用可见性消失意味着您的视图不会占用布局上的任何空间,而“不可见”将占用布局上不必要的空间
因此,请仔细检查您的detailView.setVisible()功能。理想情况下,它应该看起来像:
fun View.setVisible(show: Boolean) {
this.visibility = if (show) View.VISIBLE else View.GONE
}
Run Code Online (Sandbox Code Playgroud)
所以,当你看到 时setVisible(show = false),就相当于visibility = View.GONE在该视图上进行了设置。然而,这是一个假设,因为您的问题中没有提供此方法的实现。
测试的一个可能的替代解决方案是将 包装CalendarView在另一个布局中,例如LinearLayout或FrameLayout,然后设置此包装器布局而不是其CalendarView本身的可见性。
这可能有助于确保在可见性发生变化时正确地重新绘制布局。
例如:
<LinearLayout
android:id="@+id/calendarViewContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<CalendarView
android:id="@+id/calendarView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
在您的点击侦听器中,您现在可以切换可见性calendarViewContainer而不是calendarView:
val detailView = this.root.findViewById<ViewGroup>(if (type == AllOptionsEnum.CALENDAR) R.id.calendarViewContainer else type.detailViewGroupId)
Run Code Online (Sandbox Code Playgroud)
如果问题仍然存在,另一个解决方法是requestLayout()在将可见性更改为 后使用方法GONE。这将告诉 Android 系统再次测量和布局视图层次结构,这可能会解决您的问题。
detailView.setVisible(show = false)
detailView.requestLayout()
Run Code Online (Sandbox Code Playgroud)
这不是最有效的方法,因为它可能会导致不必要的布局传递,但可能有必要解决 Android Pie (9) 上的这个特定问题。
关于编辑3:
Run Code Online (Sandbox Code Playgroud)// hide detailView if(type==Enums.StayWithUsWidgetType.TYPE_CALENDAR){ // hide detailview and children this.calendarDetailView.children.forEach { it.visible() } } // Hide detailView and children if(type==Enums.StayWithUsWidgetType.TYPE_CALENDAR){ // hide all this.calendarDetailView.children.forEach { it.gone() } }
我看到您试图单独隐藏calendarDetailView( 我假设是ViewGroup包含您的CalendarView) 的每个孩子。但是,目前还不清楚您是否将其calendarDetailView本身的可见性设置为GONE。
我更愿意看到这段代码,其中它calendarDetailView本身也设置为GONE:
if(type == Enums.StayWithUsWidgetType.TYPE_CALENDAR){
// hide all children
this.calendarDetailView.children.forEach {
it.visibility = View.GONE
}
// then hide the parent itself
this.calendarDetailView.visibility = View.GONE
}
Run Code Online (Sandbox Code Playgroud)