es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Intentando espaciar de manera programática una disposición de cuadrícula de forma uniforme.

Tengo un GridLayout que debería mostrar 25 botones espaciados uniformemente. Para poder establecer un onClickListener sin llamar a cada uno de ellos, quiero hacerlo programáticamente. Hice un archivo de recursos de diseño con el propio grid para vincularlo y poder inflarlo.

activity.xml

xml
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:grid="http://schemas.android.com/apk/res-auto"
android:id="@+id/bingo_grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:columnCount="5"
android:rowCount="5"
tools:context=".BingoActivity" />

Ahora estoy creando los campos:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

<pre><code>    val bingoField = (1).rangeTo(25).toSet().toIntArray()
    binding = BingoActivityBinding.inflate(layoutInflater)

    setContentView(binding.root)
    binding.bingoGrid.alignmentMode = GridLayout.ALIGN_BOUNDS

    val bingoFieldGrid = binding.bingoGrid
    bingoFieldGrid.alignmentMode = GridLayout.ALIGN_BOUNDS
    bingoField.forEach {
        val button = createButton(it.toString())
        val gridLayoutParams = GridLayout.LayoutParams().apply {
            rowSpec = spec(GridLayout.UNDEFINED, GridLayout.CENTER, 1f)
            columnSpec = spec(GridLayout.UNDEFINED, GridLayout.CENTER, 1f)
            height = GridLayout.LayoutParams.WRAP_CONTENT
            width = GridLayout.LayoutParams.WRAP_CONTENT
        }

        bingoFieldGrid.addView(button, gridLayoutParams)
    }
@RequiresApi(Build.VERSION_CODES.M)
private fun createButton(buttonText: String): Button {
    var isCompleted = false
    return Button(baseContext).apply {
        setBackgroundColor(getColor(R.color.red))
        gravity = Gravity.CENTER
        text = buttonText
        setOnClickListener {
            isCompleted = if (!isCompleted) {
                setBackgroundColor(getColor(R.color.green))
                true
            } else {
                setBackgroundColor(getColor(R.color.red))
                false
            }
        }
    }
}

Los campos se generan automáticamente sin problemas, pero el espaciado no es correcto:

enter image description here

Soy bastante nuevo en el diseño antiguo, ¿hay una forma fácil de lograr eso?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para distribuir uniformemente los botones en el GridLayout, puedes establecer los atributos columnCount y rowCount en el archivo XML del diseño con el mismo valor, en este caso 5, lo que creará una cuadrícula de tamaño igual. Luego, en la función createButton(), puedes establecer el relleno o el margen del botón utilizando los métodos setPadding() o setMargins(), respectivamente, para crear espacio alrededor de cada botón.

    Aquí hay una versión actualizada del código con estos cambios:

    <gridlayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" xmlns:grid="http://schemas.android.com/apk/res-auto" android:id="@+id/bingo_grid" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerhorizontal="true" android:columncount="5" android:rowcount="5" tools:context=".BingoActivity"></gridlayout>
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    
        val bingoField = (1).rangeTo(25).toSet().toIntArray()
        binding = BingoActivityBinding.inflate(layoutInflater)
    
        setContentView(binding.root)
    
        val bingoFieldGrid = binding.bingoGrid
        bingoFieldGrid.alignmentMode = GridLayout.ALIGN_BOUNDS
        bingoFieldGrid.columnCount = 5
        bingoFieldGrid.rowCount = 5
    
        bingoField.forEach {
            val button = createButton(it.toString())
            val gridLayoutParams = GridLayout.LayoutParams().apply {
                rowSpec = spec(GridLayout.UNDEFINED, GridLayout.CENTER, 1f)
                columnSpec = spec(GridLayout.UNDEFINED, GridLayout.CENTER, 1f)
                height = GridLayout.LayoutParams.WRAP_CONTENT
                width = GridLayout.LayoutParams.WRAP_CONTENT
            }
            button.setPadding(16, 16, 16, 16) // or button.setMargins(16, 16, 16, 16)
            bingoFieldGrid.addView(button, gridLayoutParams)
        }
    }
    
    @RequiresApi(Build.VERSION_CODES.M)
    private fun createButton(buttonText: String): Button {
        var isCompleted = false
        return Button(baseContext).apply {
            setBackgroundColor(getColor(R.color.red))
            gravity = Gravity.CENTER
            text = buttonText
            setOnClickListener {
                isCompleted = if (!isCompleted) {
                    setBackgroundColor(getColor(R.color.green))
                    true
                } else {
                    setBackgroundColor(getColor(R.color.red))
                    false
                }
            }
        }
    }
    

    En este código revisado, las propiedades columnCount y rowCount se establecen en 5 en el archivo XML del diseño, y el relleno de cada botón se establece en 16dp en la función createButton(). Puedes ajustar los valores de relleno/margen para lograr el espaciado deseado entre los botones.

Comments are closed.