首页 > 解决方案 > 将动态添加的按钮放在彼此下方

问题描述

我正在构建一个计算器应用程序,其中有一个 ScrollView,用于在用户在模式之间切换时显示和切换运算符和单位的按钮。

问题是我不想为每种模式创建一个 XML 布局,所以我想以编程方式添加这些按钮(现在,对我来说,这似乎很难实现)。这是应该添加它们的代码:

// For each text in texts (which represents the modes), a Button is created and, if its id (represented by the index of its respective text in the list) is greater than 0, it is positioned below the previous one.
fun ScrollView.add(context: Context, input: EditText, texts: List<String>) {
    removeAllViews()

    val container = ConstraintLayout(context).apply {
        layoutParams = ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT).apply {
            topToTop = this@add.top
            startToStart = this@add.left
            endToEnd = this@add.right
        }
    }

    val buttons: MutableList<Button> = mutableListOf()

    texts.forEach { text ->
        val button = Button(context)

        val originalWidth = 60
        val width = originalWidth.toDimension(context, COMPLEX_UNIT_DIP)

        val originalHeight = 60
        val height = originalHeight.toDimension(context, COMPLEX_UNIT_DIP)

        with(button) {
            layoutParams = ConstraintLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)

            id = texts.indexOf(text)
            val previous = try { buttons[id - 1] } catch (exception: Exception) { this }

            setWidth(width)
            setHeight(height)

            with(layoutParams as ConstraintLayout.LayoutParams) {
                if (id == 0)
                    topToTop = this@add.top
                else if (id > 0) {
                    layoutParams = RelativeLayout.LayoutParams(WRAP_CONTENT, WRAP_CONTENT)
                    (layoutParams as RelativeLayout.LayoutParams).addRule(BELOW, previous.id)
                }
            }

            left = this@add.left
            right = this@add.right

            button.text = text
            isAllCaps = false

            textSize = 25f
            while (text().contains(System.getProperty("line.separator").toString())) textSize -= 5

            setOnClickListener { input.input((it as Button).text()) }
            setBackgroundResource(0)

            container.addView(this)
            buttons.add(this)

            val buttonAdded = "[Dynamic List] Button $id added as \"$text\""
            println(if (id == 0) "$buttonAdded." else "$buttonAdded. The button was positioned below \"${previous.text}\" (${previous.id}).")
        }
    }

    addView(container)
}

这是我使用上述方法实现的代码:

// Each calculator mode is represented by an Int within the list.
val modes = listOf("calculator" to 1, "length" to 2, "temperature" to 3, "time" to 4)

fun mode(context: Context, button: Button, input: EditText, view: ScrollView) {
    var counter = 0

    val operators = listOf("+", "-", times.toString(), division.toString())
    val length = with(context) { listOf(getString(R.string.light_year), context.getString(R.string.kilometer), context.getString(R.string.hectometer), context.getString(R.string.decameter), context.getString(R.string.mile), context.getString(R.string.meter), context.getString(R.string.centimeter), context.getString(R.string.millimeter), context.getString(R.string.micrometer)) }
    val temperature = with(context) { listOf(getString(R.string.celsius), context.getString(R.string.fahrenheit), context.getString(R.string.kevin), context.getString(R.string.rankine), context.getString(R.string.reaumur)) }
    val time = with(context) { listOf(getString(R.string.year), context.getString(R.string.month), context.getString(R.string.day), context.getString(R.string.hour), context.getString(R.string.minute), context.getString(R.string.second), context.getString(R.string.millisecond)) }

    with(button) {
        setOnClickListener {
            if (counter < modes.size - 1) counter++ else counter = 0

            with(view) {
                val mode: Pair<String, Int>? = modes[counter]

                when (mode?.first) {
                    "calculator" -> add(context, input, operators)
                    "length" -> add(context, input, length)
                    "temperature" -> add(context, input, temperature)
                    "time" -> add(context, input, time)
                }

                text = with(context) {
                    with(resources) { getString(identify(context, mode?.first, "string")) }
                }
            }
        }
    }
}

好吧,问题是当我运行它时,UI 最终看起来像这样,所有按钮都位于同一个位置:

计算器模式按钮定位错误。

标签: androidkotlinandroid-button

解决方案


推荐阅读