android - NestedScrollView 没有在 AlertDialog 内扩展高度
问题描述
我目前在警报对话框中使用滚动视图,并且需要滚动视图增加高度,直到对话框达到其最大默认高度。我解释起来有点困难,所以我附上了一个插图来帮助。希望确实如此。
我遇到的问题是滚动视图的高度没有增长,即使我删除它app:layout_constraintBottom_toTopOf="@id/linearLayout4"
,它也会增长,但是底部部分将被按钮布局部分隐藏。
这是我当前的代码:
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/filter_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/dialog_box"
android:minHeight="300dp"
android:elevation="12dp">
<TextView
android:id="@+id/filter_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/filter"
style="@style/element_header"
android:textColor="@color/textColorDark"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/filter_reset_btn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:text="@string/reset"
style="@style/text_info_nBold"
android:textSize="14sp"
android:textColor="@color/textColorDark"
app:layout_constraintBottom_toBottomOf="@+id/filter_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/filter_header" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@id/linearLayout4"
app:layout_constraintTop_toBottomOf="@id/filter_header"
app:layout_constraintVertical_bias="0.0">
<androidx.core.widget.NestedScrollView
android:id="@+id/filter_scroll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fillViewport="true"
android:layout_marginTop="16dp"
android:scrollbarFadeDuration="1000">
<!-- VIEWS INSIDE HERE -->
</androidx.core.widget.NestedScrollView>
</LinearLayout>
<LinearLayout
android:id="@+id/linearLayout4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/dialog_bottombar_layout"
android:orientation="horizontal"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/dialog_secondary_button"
style="@style/low_emphasis_btn"
android:layout_width="0dp"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:backgroundTint="@color/textColorDark"
android:text="@string/dialog_cancel"
android:textColor="@color/textColorDark"
android:visibility="visible" />
<Button
android:id="@+id/dialog_primary_button"
style="@style/high_emphasis_btn"
android:layout_width="0dp"
android:layout_weight="1"
android:text="@string/apply" />
</LinearLayout>
任何帮助,将不胜感激 :)
解决方案
警报对话框倾向于包装其内容,或者可以强制全屏显示。优化屏幕空间之间的大小需要一些工作,但这并非不可能。
一种方法是让系统布置警报对话框,但在显示之前,使用ViewTreeObserver.OnGlobalLayoutListener检查对话框的结果大小。在布局监听器中,可以调整对话框的大小以适应滚动视图的内容,或者如果滚动视图内容对于屏幕来说太大,则可以调整为全屏。
这是一个演示应用程序,展示了如何做到这一点。代码中的注释解释更多。
MainActivity.kt
class MainActivity : AppCompatActivity(), View.OnClickListener {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun onClick(v: View) {
val text = when (v.id) {
R.id.customDialogShort -> getString(R.string.short_string)
R.id.customDialogMedium -> getString(R.string.lorem_medium)
else -> getString(R.string.lorem_long)
}
// Specifying the viewGroup as a parent to the inflater makes no difference.
val dialogView = LayoutInflater.from(v.context).inflate(R.layout.con_custom_view, null, false) as ConstraintLayout
(dialogView.findViewById(R.id.textView) as TextView).text = text
val alertDialog = AlertDialog.Builder(this).setView(dialogView).create()
val decorView = alertDialog.window!!.decorView
decorView.setBackgroundResource(R.drawable.alert_dialog_background)
// We need a layout pass to determine how big everything is and needs to be. Place a hook
// at the end of the layout process to examine the layout before display.
decorView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
override fun onGlobalLayout() {
decorView.viewTreeObserver.removeOnGlobalLayoutListener(this)
// Find out how much of the scrolling view is usable by its child.
val scrollingView: NestedScrollView = decorView.findViewById(R.id.filter_scroll)
val scrollingViewPadding = scrollingView.paddingTop + scrollingView.paddingBottom
val scrollingUsableHeight = scrollingView.height - scrollingViewPadding
// If the child view fits in the scrolling view, then we are done.
val childView = scrollingView.getChildAt(0)
if (childView.height <= scrollingUsableHeight) {
return
}
// Child doesn't currently fit in the scrolling view. Resize the top-level
// view so the child either fits or is forced to scroll because the maximum
// height is reached. First, find out how much space is allowed by the decor view.
val displayRectangle = Rect()
decorView.getWindowVisibleDisplayFrame(displayRectangle)
val decorViewPadding = decorView.paddingTop + decorView.paddingBottom
val decorUsableHeight = displayRectangle.height() - decorViewPadding - scrollingViewPadding
// Compute the height of the dialog that will 100% fit the scrolling content and
// reduce it if it won't fit in the maximum allowed space.
val heightToFit = dialogView.height + childView.height - scrollingUsableHeight
dialogView.minHeight = min(decorUsableHeight, heightToFit)
}
})
var buttonOk: Button = dialogView.findViewById(R.id.dialog_primary_button)
buttonOk.setOnClickListener { alertDialog.dismiss() }
buttonOk = dialogView.findViewById(R.id.dialog_secondary_button)
buttonOk.setOnClickListener { alertDialog.dismiss() }
alertDialog.show()
}
}
activity_main.xml
<LinearLayout
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/customDialogShort"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Short text" />
<Button
android:id="@+id/customDialogMedium"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Medium text" />
<Button
android:id="@+id/customDialogLong"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="onClick"
android:text="Long text" />
</LinearLayout>
con_custom_view 警报对话框
的自定义布局。
<TextView
android:id="@+id/filter_header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="@string/filter"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/filter_reset_btn"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:background="?attr/selectableItemBackgroundBorderless"
android:text="@string/reset"
android:textSize="14sp"
app:layout_constraintBottom_toBottomOf="@+id/filter_header"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/filter_header" />
<androidx.core.widget.NestedScrollView
android:id="@+id/filter_scroll"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:padding="16dp"
android:scrollbarFadeDuration="1000"
app:layout_constraintBottom_toTopOf="@id/linearLayout4"
app:layout_constraintTop_toBottomOf="@id/filter_header">
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:text="@string/lorem_long" />
</androidx.core.widget.NestedScrollView>
<LinearLayout
android:id="@+id/linearLayout4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/dialog_secondary_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_weight="1"
android:text="@string/dialog_cancel"
android:visibility="visible" />
<Button
android:id="@+id/dialog_primary_button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/apply" />
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
推荐阅读
- c - 显示我自己的系统调用错误消息
- spring-boot - 从源“http://...”访问“https://...”处的 XMLHttpRequest 已被 CORS 策略(Spring Boot 和 Angular 7)阻止
- blockchain - 在非货币区块链上进行挖矿是否需要区块奖励?
- javascript - 材质 UI 选择器 - 日期-fns 问题
- javascript - 密码在请求有效负载 devtools 中可见
- javascript - JavaScript 输入聚合函数不包括默认输入值
- python-pptx - python-pptx - 尝试将数字作为整数类型而不是字符串插入表中
- r - 在列表上迭代函数
- python - 为什么我的 lambda 函数在使用 filter() 和 map() 之类的函数时不返回任何值?
- angular - 通过传入数据的角度 TS 循环