Spanish [SOLUCIONADO]¿GridView de botones en B4A?

ferpahud

Active Member
Licensed User
Hola, buenos dias

Queria saber si es posible hacer un tipo GridView en B4A, la idea sera poder asignale una imagen y un texto. Dejo una imagen de ejemplo:

2db9iqa.jpg


¿Alguien sabe como implementarlo, y donde conseguir informacion sobre su funcionamiento (clicks, carga, etc? Desde ya muchas gracias
 

Seneca

Active Member
Licensed User
Hola.

Yo tengo hecho algo similar. He usado un Scrollview en el que he ido colocando los distintos botones. A estos les he colocado la imágen y el texto a través de las propiedades .SetBackgroundImage y .text La imagen la he tratado previamente con la librería RSImageProcessing (RoundCorner) para redondear las esquinas y en vez de colocarla directamente en el botón, lo he hecho a través de un canvas, que me permite que la imagen solo ocupe la parte que yo decida del botón.

Espero te pueda servir de orientación.

Saludos.
 

ferpahud

Active Member
Licensed User
Hola.

Yo tengo hecho algo similar. He usado un Scrollview en el que he ido colocando los distintos botones. A estos les he colocado la imágen y el texto a través de las propiedades .SetBackgroundImage y .text La imagen la he tratado previamente con la librería RSImageProcessing (RoundCorner) para redondear las esquinas y en vez de colocarla directamente en el botón, lo he hecho a través de un canvas, que me permite que la imagen solo ocupe la parte que yo decida del botón.

Espero te pueda servir de orientación.

Saludos.
Seneca, gracias por responder. El inconveniente que tengo, es que yo necesito descargar la información de una base de datos MySQL, por lo que no se cuantos elementos voy a tener a la hora de realizar la carga.Por ejemplo si necesito decargar "categorias", con su imagen y texto, y coloco 10 botones porque la base de datos acutalmente tiene 10, si alguien carga nuevas categorías, o eliminan alguna ya el numero de categoría cambia, y la cantidad de botones no alcanza (o sobran).

Necesitaría que se creen a la hora de abrir la pantalla segun la cantidad de registros que tenga la base de datos, por eso pensaba en un gridview, pero en el buscador del foro no encuentro nada al respecto...
 

Seneca

Active Member
Licensed User
Lo que indicas de la base de datos no es un problema, de hecho yo tengo esas mismas condiciones.

Lo que hago es leer de la BD todos los botones, con su imagen y texto. Después voy añadiendo los botones a un Scrollview, calculando las coordenadas para cada botón, dependiendo del número de columnas que quiera tener, del tamaño de los botones y de la separaciónn entre cada uno de ellos. Una vez los tengo todos añadidos, lo único que resta es dimensinar el alto (height) del panel del ScrollView para que tenga un tamaño suficiente para que se vean todas las filas de botones. Este alto lo calculo multiplicando: número de filas de botones * (alto del botón + separación entre botones)

De esta forma siempre se visualizará bien, aunque el número de botones cambien en la BD. Si no has usado nunca un ScrollView, échale primero un vistazo a su funcionamiento.

Saludos.
 

ferpahud

Active Member
Licensed User
Lo que indicas de la base de datos no es un problema, de hecho yo tengo esas mismas condiciones.

Lo que hago es leer de la BD todos los botones, con su imagen y texto. Después voy añadiendo los botones a un Scrollview, calculando las coordenadas para cada botón, dependiendo del número de columnas que quiera tener, del tamaño de los botones y de la separaciónn entre cada uno de ellos. Una vez los tengo todos añadidos, lo único que resta es dimensinar el alto (height) del panel del ScrollView para que tenga un tamaño suficiente para que se vean todas las filas de botones. Este alto lo calculo multiplicando: número de filas de botones * (alto del botón + separación entre botones)

De esta forma siempre se visualizará bien, aunque el número de botones cambien en la BD. Si no has usado nunca un ScrollView, échale primero un vistazo a su funcionamiento.

Saludos.

Entiendo, no sabia que se podia hacer de esa forma, voy a echarle un vistazo a ScrollView que no lo eh utilizado nunca. Gracias nuevamente Seneca
 

desof

Well-Known Member
Licensed User
Hola puedes utilizar CustomListView y generar tu propio listado de forma dinámica.
 

ferpahud

Active Member
Licensed User
Hola puedes utilizar CustomListView y generar tu propio listado de forma dinámica.
Muchas gracias por tu respuesta, la tendre en cuenta. Todavia sigo investigando como resolverlo... lo que no encuentro es como hacerlo con forma de boton utilizando CustomListView... creo que lo terminare haciendo con un simple listview....
 

Seneca

Active Member
Licensed User
Muchas gracias por tu respuesta, la tendre en cuenta. Todavia sigo investigando como resolverlo... lo que no encuentro es como hacerlo con forma de boton utilizando CustomListView... creo que lo terminare haciendo con un simple listview....

Hola.

Sigo pensando que usar un Scrollview es la manera más versátil. El Scrollview es un elemento que te permite albergar dentro otros controles, como por ejemplo los botones. Lees de la BD los datos de cada botón, los colocas dentro del ScrollView, con el tamaño y diseño y en la posición que quieras. Al ser botones ya tienes resuelto los eventos Clic.

A mí por lo menos me ha ido perfecto.

Saludos.
 

Seneca

Active Member
Licensed User
Hola.

Sigo pensando que usar un Scrollview es la manera más versátil.

Cuando decía que el SV es más versátil me refiero a que, entre otras cosas, puedes colocar los botones en una columna, en dos (como la imagen del primer mensaje) o en las columnas que quieras. Esto creo que no se puede hacer con el CustomListView.

Saludos.
 
Last edited:

ferpahud

Active Member
Licensed User
Hola.

Sigo pensando que usar un Scrollview es la manera más versátil. El Scrollview es un elemento que te permite albergar dentro otros controles, como por ejemplo los botones. Lees de la BD los datos de cada botón, los colocas dentro del ScrollView, con el tamaño y diseño y en la posición que quieras. Al ser botones ya tienes resuelto los eventos Clic.

A mí por lo menos me ha ido perfecto.

Saludos.
El problema es que soy relativamente nuevo en B4A, no solo que nunca use ScrollView, sino que tampoco se como se pueden ir creando los botones de manera dinamica, e ir asignandole todos los atributos. Se puede en el momento de crearlos también agregarle el tamaño en %? Para que no quede mal en pantallas de distintas resoluciones.

Graicas nuevamente por la respuesta
 

ferpahud

Active Member
Licensed User
casualmente el estoy trabajando en un Proyecto y he logrado utilizar con mucho éxito el customlistview y es extremadamente potente.
Te preparare un ejemplo sencillo para ver si te sirve.
en este enlace puedes ver en la imagen inferior 5 botones creados en un CL y cada uno contiene 2 label y una imagen.
https://www.b4x.com/android/forum/threads/problemas-con-tablayout-al-iniciar-app.78512/
saludos!

Es buena opcion, pero no es del tipo boton como muestra la imagen que deje de ejemplo. Estaba pensando en terminar haciendo algo de ese estilo si se me sigue complicando hacer una grilla de botones, se ve bastante bien en tu ejemplo. Lo que puedo ver tambien es que ya estan cargados los botones, se podra hacer que la cantidad de botones sea dinamica segun los datos en la BD MySQL?
 

desof

Well-Known Member
Licensed User
Es buena opcion, pero no es del tipo boton como muestra la imagen que deje de ejemplo. Estaba pensando en terminar haciendo algo de ese estilo si se me sigue complicando hacer una grilla de botones, se ve bastante bien en tu ejemplo. Lo que puedo ver tambien es que ya estan cargados los botones, se podra hacer que la cantidad de botones sea dinamica segun los datos en la BD MySQL?

Amigo esa es solo una muestra y lle das la forma que quieres! e incluso los cargas desde un BD como tu quieres.
 

Seneca

Active Member
Licensed User
El problema es que soy relativamente nuevo en B4A, no solo que nunca use ScrollView, sino que tampoco se como se pueden ir creando los botones de manera dinamica, e ir asignandole todos los atributos. Se puede en el momento de crearlos también agregarle el tamaño en %? Para que no quede mal en pantallas de distintas resoluciones.

Graicas nuevamente por la respuesta

Sí, se puede todo eso. Tengo implementado un proceso que el resultado que me da es idéntico a la imagen del mensaje #1, y sacado todo de la BD. Solo he de indicar el alto de los botones, la separación entre ellos y el número de columnas que quiero mostrar y todo lo demás es automático. La cantidad de botones, la imagen y el texto de cada uno salen de la BD.

En cuanto tenga un ratito te hago un extracto del código y publico aquí un ejemplo.

Saludos.
 

Seneca

Active Member
Licensed User
Bueno, aquí publico un ejemplo completo de cómo creo yo un menú con botones extraidos de una BD. El resultado visual puede completarse añadiendo un ligero borde a cada botón, como aparece en el mensaje #1, o con cualquier otra necesidad estética. Las imágenes de cada botón no hay que redondearlas previamente con un editor gráfico, sino que es la propia app la que las redondea con el radio que se le indique en el código. El número de columnas y el tamaño de los botones (en %) es igualmente configurable.

Espero pueda servir a alguien.


B4X:
Sub Process_Globals
    Public sql As SQL
End Sub

Sub Globals
    Dim IE As RSImageEffects
    Dim Lista_botones As List
    Dim Color_Boton As Int = Colors.ARGB(255, 0, 0, 160)
    Dim alto_boton As Int = 45%x + 50dip 'los 50 dip es el espacio donde irá el texto del botón
    Dim ancho_boton As Int = 45%x
    Dim columnas As Int = 2
    Dim separacion As Int
    Dim intTotalBotones As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)

    preparaDB

    Dim SV As ScrollView
    SV.Initialize(100dip) '100dip - Tamaño del panel provisional
    SV.Panel.Color=Colors.White

    Activity.AddView(SV, 0, 0, 100%x, 100%y)

    Lista_botones = DBUTILS.ExecuteMemoryTable(sql, "SELECT id_boton, nombre_boton, imagen_boton FROM categorias", Null,0)

    separacion = (100%x - (columnas * ancho_boton))/(columnas + 1) 'Separación horizontal entre botones a N columnas

    intTotalBotones = Lista_botones.Size 'guarda el número total de botones a mostrar

    'Determina el alto del Panel del SV según el número, tamaño, columnas y separación de los botones
    SV.Panel.Height=(Ceil(intTotalBotones/columnas) * (alto_boton + separacion)) + separacion

    Dim DatosBoton () As String

    For Numero = 0 To intTotalBotones - 1
        Dim boton As Button
        DatosBoton = Lista_botones.Get(Numero) 'Recupera de la Lista de Botones los datos de cada uno
        'Pasa como parámetros el SV, un botón, nº del botón, texto e imagen del botón
        DibujaBoton (SV, boton, Numero, DatosBoton(0), DatosBoton(1),DatosBoton(2))
    Next

    'DoEvents

End Sub


Sub DibujaBoton (SV As ScrollView, boton As Button, Numero As Int, id As Int, texto As String, imagen As String)
    Dim x, y As Int
    boton.Initialize("btnV")
    boton.Tag = Numero 'se almacena el número de orden de cada botón

    Dim DestRect As Rect
    Dim icono As Bitmap ' mediante canvas inserto la imagen para despues redondear
    Dim iconoCanvas As Canvas

    x = separacion + (ancho_boton + separacion) * (Numero Mod columnas) 'calcula la coordenada X del botón
    y = separacion + (alto_boton + separacion) * Floor(Numero/columnas) 'calcula la coordenada Y del botón

    SV.Panel.AddView(boton, x, y, ancho_boton, alto_boton) 'añade el botón al SV

    icono.InitializeMutable(ancho_boton, alto_boton) ' inicializo el icono como bitmat modificable por el canvas
    DestRect.Initialize(0dip, 0dip, ancho_boton, alto_boton - 50dip)
    iconoCanvas.Initialize2(icono)

    'Dibuja la imagen de fondo del botón, previamente redondeada (IE.Roundcorner)
    iconoCanvas.DrawBitmap(IE.RoundCorner(LoadBitmapSample(File.DirAssets, imagen,ancho_boton, alto_boton),28), Null, DestRect)

    boton.SetBackgroundImage(icono) 'coloca en el fondo del botón

    boton.Gravity=Bit.Or(Gravity.BOTTOM, Gravity.CENTER_HORIZONTAL)
    boton.Text = texto
    boton.TextSize = 15
    boton.TextColor=Color_Boton
End Sub

Sub btnv_click
    Dim boton_pulsado As Button
    boton_pulsado = Sender
    ToastMessageShow("Botón pulsado nº: " & boton_pulsado.tag & " - " & boton_pulsado.Text, False)
End Sub

Sub preparaDB 'Borra y copia de nuev la BD
    File.Delete(DBUTILS.GetDBFolder, "botones.db")
    Dim rutaDB As String
    rutaDB=DBUTILS.CopyDBFromAssets("botones.db")
    sql.Initialize (rutaDB, "botones.db", True)
End Sub
 

Attachments

  • b4a.botonesbd.jpg
    b4a.botonesbd.jpg
    181.9 KB · Views: 470
  • menu_botones_bd.zip
    265.1 KB · Views: 329
Last edited:

ferpahud

Active Member
Licensed User
Bueno, aquí publico un ejemplo completo de cómo creo yo un menú con botones extraidos de una BD. El resultado visual puede completarse añadiendo un ligero borde a cada botón, como aparece en el mensaje #1, o con cualquier otra necesidad estética. Las imágenes de cada botón no hay que redondearlas previamente con un editor gráfico, sino que es la propia app la que las redondea con el radio que se le indique en el código. El número de columnas y el tamaño de los botones (en %) es igualmente configurable.

Espero pueda servir a alguien.


B4X:
Sub Process_Globals
    Public sql As SQL
End Sub

Sub Globals
    Dim IE As RSImageEffects
    Dim Lista_botones As List
    Dim Color_Boton As Int = Colors.ARGB(255, 0, 0, 160)
    Dim alto_boton As Int = 45%x + 50dip 'los 50 dip es el espacio donde irá el texto del botón
    Dim ancho_boton As Int = 45%x
    Dim columnas As Int = 2
    Dim separacion As Int
    Dim intTotalBotones As Int
End Sub

Sub Activity_Create(FirstTime As Boolean)

    preparaDB

    Dim SV As ScrollView
    SV.Initialize(100dip) '100dip - Tamaño del panel provisional
    SV.Panel.Color=Colors.White

    Activity.AddView(SV, 0, 0, 100%x, 100%y)

    Lista_botones = DBUTILS.ExecuteMemoryTable(sql, "SELECT id_boton, nombre_boton, imagen_boton FROM categorias", Null,0)

    separacion = (100%x - (columnas * ancho_boton))/(columnas + 1) 'Separación horizontal entre botones a N columnas

    intTotalBotones = Lista_botones.Size 'guarda el número total de botones a mostrar

    'Determina el alto del Panel del SV según el número, tamaño, columnas y separación de los botones
    SV.Panel.Height=(Ceil(intTotalBotones/columnas) * (alto_boton + separacion)) + separacion

    Dim DatosBoton () As String

    For Numero = 0 To intTotalBotones - 1
        Dim boton As Button
        DatosBoton = Lista_botones.Get(Numero) 'Recupera de la Lista de Botones los datos de cada uno
        'Pasa como parámetros el SV, un botón, nº del botón, texto e imagen del botón
        DibujaBoton (SV, boton, Numero, DatosBoton(0), DatosBoton(1),DatosBoton(2))
    Next

    'DoEvents

End Sub


Sub DibujaBoton (SV As ScrollView, boton As Button, Numero As Int, id As Int, texto As String, imagen As String)
    Dim x, y As Int
    boton.Initialize("btnV")
    boton.Tag = Numero 'se almacena el número de orden de cada botón

    Dim DestRect As Rect
    Dim icono As Bitmap ' mediante canvas inserto la imagen para despues redondear
    Dim iconoCanvas As Canvas

    x = separacion + (ancho_boton + separacion) * (Numero Mod columnas) 'calcula la coordenada X del botón
    y = separacion + (alto_boton + separacion) * Floor(Numero/columnas) 'calcula la coordenada Y del botón

    SV.Panel.AddView(boton, x, y, ancho_boton, alto_boton) 'añade el botón al SV

    icono.InitializeMutable(ancho_boton, alto_boton) ' inicializo el icono como bitmat modificable por el canvas
    DestRect.Initialize(0dip, 0dip, ancho_boton, alto_boton - 50dip)
    iconoCanvas.Initialize2(icono)

    'Dibuja la imagen de fondo del botón, previamente redondeada (IE.Roundcorner)
    iconoCanvas.DrawBitmap(IE.RoundCorner(LoadBitmapSample(File.DirAssets, imagen,ancho_boton, alto_boton),28), Null, DestRect)

    boton.SetBackgroundImage(icono) 'coloca en el fondo del botón

    boton.Gravity=Bit.Or(Gravity.BOTTOM, Gravity.CENTER_HORIZONTAL)
    boton.Text = texto
    boton.TextSize = 15
    boton.TextColor=Color_Boton
End Sub

Sub btnv_click
    Dim boton_pulsado As Button
    boton_pulsado = Sender
    ToastMessageShow("Botón pulsado nº: " & boton_pulsado.tag & " - " & boton_pulsado.Text, False)
End Sub

Sub preparaDB 'Borra y copia de nuev la BD
    File.Delete(DBUTILS.GetDBFolder, "botones.db")
    Dim rutaDB As String
    rutaDB=DBUTILS.CopyDBFromAssets("botones.db")
    sql.Initialize (rutaDB, "botones.db", True)
End Sub

Seneca, muchas gracias nuevamente por tu ayuda. Cuando intento ejecutar el codigo de ejemplo me marca un error en la siguiente linea:
B4X:
Dim IE As RSImageEffects
Are you missing a library reference?

Tengo instalada y activada la libreria de RSImageProcessing, y todas las librerias que muestra en la imagen que dejaste de ejemplo...
 
Top