我在垂直 LinearLayout 中有两个垂直 ScrollView。 如果我将两者的layout_weight设置为1,它们都使用全高度的一半。 然而,如果其中一个只需要例如,情况也是如此。由于其内容而高度的四分之一。 在这种情况下,我想缩小第一个 ScrollView 并为第二个 ScrollView 使用多余的空间(反之亦然)。
知道如何实现这一目标吗?周围布局不一定是 LinearLayout。 (我看过this,但它没有回答我的问题)
好吧,由于似乎没有办法直接使用LinearLayout,所以我创建了一个自定义布局。 它必须有两个 ScrollView 作为子项,但如果内部需要其他视图,则可以轻松进行调整。
/**
* A vertical LinearLayout containing 2 ScrollViews.
* The height of each ScrollView is growing with its content, as long as both
* ScrollViews fit into the parent.
* If one ScrollView needs to scroll its content, and the other is still smaller than half
* of the parent, the smaller one takes only as much space as needed.
* Only if both views need more than half of the parent space,
* each of them receives exactly half of it.
*/
class DoubleScrollView : LinearLayout {
private lateinit var scrollView1: ScrollView
private lateinit var scrollView2: ScrollView
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) :
super(context, attrs, defStyle)
override fun onFinishInflate() {
super.onFinishInflate()
//In this simple example, we assume to have exactly 2 ScrollViews as children
scrollView1 = getChildAt(0) as ScrollView
scrollView2 = getChildAt(1) as ScrollView
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
//Allow the scroll views to set the full content height at first
scrollView1.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, 0f)
scrollView2.setLayout(ViewGroup.LayoutParams.WRAP_CONTENT, 0f)
val widthSpec = MeasureSpec.makeMeasureSpec(width, EXACTLY)
val heightSpec = MeasureSpec.makeMeasureSpec(height, AT_MOST)
scrollView1.measure(widthSpec, heightSpec)
scrollView2.measure(widthSpec, heightSpec)
// Based on the height the full content would need, adapt the LayoutParams
// of the ScrollViews.
val height = View.MeasureSpec.getSize(heightMeasureSpec)
val height1 = scrollView1.measuredHeight
val height2 = scrollView2.measuredHeight
if (height1 + height2 >= height) {
if (height1 < height / 2) {
//First wrap content, second fills the rest
scrollView2.setLayout(0, 1f)
} else if (height2 < height / 2) {
//Second wrap content, first fills the rest
scrollView1.setLayout(0, 1f)
} else {
//First and second both with same weight
scrollView1.setLayout(0, 1f)
scrollView2.setLayout(0, 1f)
}
} //else: both views can just wrap content
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
private fun View.setLayout(height: Int, weight: Float) {
this.layoutParams.height = height
(this.layoutParams as LinearLayout.LayoutParams).weight = weight
}
}
为了测试和演示,我创建了以下最小应用程序。
活动:
class MainActivity : AppCompatActivity() {
private val mainViewModel: MainViewModel by viewModels()
private lateinit var vb: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vb = ActivityMainBinding.inflate(layoutInflater)
setContentView(vb.root)
mainViewModel.text1.observe(this) { text -> updateText(vb.text1, text) }
mainViewModel.text2.observe(this) { text -> updateText(vb.text2, text) }
listOf(vb.plus1, vb.minus1, vb.plus2, vb.minus2).forEachIndexed() { i, button ->
button.setOnClickListener { mainViewModel.changeText(i <= 1, i % 2 == 0) }
}
}
private fun updateText(textView: TextView, text: String?) {
textView.text = text
}
}
视图模型:
class MainViewModel : ViewModel() {
val text1: LiveData<String> = MutableLiveData("")
val text2: LiveData<String> = MutableLiveData("")
fun changeText(first: Boolean, plus: Boolean) {
val liveData = if (first) text1 else text2
val text = liveData.value!!
val size = text.count { it == '#' } + if (plus) 1 else -1
val lines = Array(size.coerceAtLeast(0)) { "This is line #$it" }
(liveData as MutableLiveData).value = lines.joinToString("\n")
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<yourPackage.DoubleScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ScrollView
android:id="@+id/scrollView1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/plus1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"></Button>
<Button
android:id="@+id/minus1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"></Button>
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
<ScrollView
android:id="@+id/scrollView2"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:id="@+id/plus2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="+"></Button>
<Button
android:id="@+id/minus2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="-"></Button>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</ScrollView>
</yourPackage.DoubleScrollView>
通过按 + 和 - 按钮,您可以填充滚动视图并查看布局如何反应。