如果按钮文本行数不同,垂直线性布局中的加权按钮会切断文本

Weighted buttons in vertical linear layout cutting off text if button text line counts vary

TL;DR:这是我能想到的与我面临的问题相关的所有要点:[GIST LINK]

这是问题的图片

我正在尝试设置一些按钮,这些按钮将在垂直方向的 LinearLayout 容器中通过相等的权重增长到彼此相同的大小。

当这些按钮上的文本导致每个按钮的行数不同时,我面临的问题浮出水面。

假设 n 是按钮的最低行数,m 是最高行数;行数为 m 的按钮文本中的任何下行部分都将被截断。请参阅链接屏幕截图中的 "qshowing my clipping problem" 字样,其中所有下行部分都被切断。

我该如何解决这个问题?如果我将 android:lineSpacingExtra 引入按钮样式,剪辑会变得更糟。

如果相关,我的最小 API 设置为 21

我已经使用 RxJava 修复了这个问题,以编程方式将高度设置为正确的最大值,这样就不会发生剪裁。如果有更好的解决方案,我会很高兴看到它,但这是目前对我有用的:

class MyActivity {

    // ...

    private val compositeDisposable = CompositeDisposable()

    override fun onCreate(savedInstanceState: Bundle?) {
        setContentView(R.layout.my_activity)
        // ...

        val container: LinearLayout = findViewById(R.id.container)

        val numBtns = getNumBtnsToAdd()
        val btnList: MutableList<Button> = mutableListOf()
        val margin10 = dpToPx(10f).toInt()

        val countDown = CountDownLatch(numBtns)
        val desiredLp = LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0).apply {
            gravity = Gravity.CENTER
            setMargins(margin10, margin10, margin10, margin10)
        }

        // Completable will be run once per subscriber and emit a success or error
        val layoutCompletable = Completable.fromAction {
            countDown.await()
            for (btn in btnList) btn.layoutParams = desiredLp
        }.subscribeOn(Schedulers.newThread()).observeOn(AndroidSchedulers.mainThread())

        compositeDisposable.add(
            layoutCompletable.subscribe({
                Log.d("MyActivity", "Set LayoutParams on all buttons.")
            }, Throwable::printStackTrace)
        )

        for (i in 0 until numBtns) {
            val btn = Button(this, null, 0, R.style.button_style).apply {
                layoutParams = LinearLayout.LayoutParams(desiredLp).apply { height = LinearLayout.LayoutParams.WRAP_CONTENTS }
                text = if (i == 0) "Button${i+1} with short text"
                              else "Button${i+1} with text that will span multiple lines showing my clipping problem"
                setOnClickListener { doSomething() }
            }

            val listener = object : ViewTreeObserver.OnGlobalLayoutListener {
                override fun onGlobalLayout() {
                    countDown.countDown()
                    val height = btn.height
                    if (height > desiredLp.height) desiredLp.height = height
                    btn.viewTreeObserver.removeOnGlobalLayoutListener(this)
                }
            }
            btn.viewTreeObserver.addOnGlobalLayoutListener(listener)
            btnList.add(btn)
            container.addView(btn)
        }

        // ...
    }

    override fun finish() {
        compositeDisposable.clear()
        super.finish()
    }

    // ...

}

我猜,主要原因是按钮有固定大小。更重要的是,您使用 LinearLayout 通过 weight 属性在按钮之间共享可用空间。您可以看到单行按钮高度与两行按钮高度相同。所以 2 行按钮被迫剪裁文本。

根据您的 XML 文件,您希望在没有更多空间时启用垂直滚动。在这种情况下,您不需要使用 weight 属性。只是彼此下方有边距的按钮。