TableLayout with SQLite

193 views Asked by At

I need to display data in tabletLayout from SQLite. The SQLite response is correct, the data is correct, I add them correct but it does not list them. It shows me only one :

TableLAyout.xml :

  <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".Views.MarcadoXLoteActivity">

<Spinner
    android:id="@+id/spinner3"
    android:layout_width="105dp"
    android:background="@drawable/green_border"
    android:layout_height="36dp"
    android:layout_marginTop="8dp"
    app:layout_constraintStart_toStartOf="@+id/textView73"
    app:layout_constraintTop_toBottomOf="@+id/textView73" />

<ImageView
    android:id="@+id/imageView26x"
    android:layout_width="33dp"
    android:layout_height="46dp"
    android:layout_marginStart="-34dp"
    app:layout_constraintBottom_toBottomOf="@+id/spinner3"
    app:layout_constraintStart_toEndOf="@+id/spinner3"
    app:layout_constraintTop_toTopOf="@+id/spinner3"
    app:srcCompat="@drawable/baseline_arrow_drop_down_24" />

<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbarM"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:minHeight="?attr/actionBarSize"
    android:theme="?attr/actionBarTheme"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:subtitleTextColor="@color/white"
    app:title="  Marcado de Avances Por Lote"
    app:titleTextAppearance="@style/TextAppearance.AppCompat.Display1"
    app:titleTextColor="@color/black">


</androidx.appcompat.widget.Toolbar>

<androidx.cardview.widget.CardView
    android:id="@+id/cardView2"
    android:layout_width="798dp"
    android:layout_height="wrap_content"
    android:layout_marginStart="1dp"
    android:layout_marginTop="32dp"
    android:layout_marginEnd="1dp"
    app:cardBackgroundColor="#DEF1DE"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/toolbarM">

    <TextView
        android:id="@+id/tvNomMarcado"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:text="     CIMENTACION"
        android:textColor="#11B818"
        android:textSize="24sp"
        android:textStyle="bold|italic" />

</androidx.cardview.widget.CardView>

<TextView
    android:id="@+id/textView72"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="80dp"
    android:layout_marginTop="24dp"
    android:text="Manzana"
    android:textColor="#000000"
    android:textSize="16sp"
    app:layout_constraintStart_toStartOf="@+id/cardView2"
    app:layout_constraintTop_toBottomOf="@+id/cardView2" />

<TextView
    android:id="@+id/textView73"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="24dp"
    android:layout_marginEnd="220dp"
    android:text="Rango de Lotes"
    android:textColor="#000000"
    android:textSize="16sp"
    app:layout_constraintEnd_toEndOf="@+id/cardView2"
    app:layout_constraintTop_toBottomOf="@+id/cardView2" />

<Spinner
    android:id="@+id/spinnerMan"
    android:layout_width="206dp"
    android:layout_height="36dp"
    android:layout_marginTop="8dp"
    android:background="@drawable/green_border"
    app:layout_constraintStart_toStartOf="@+id/textView72"
    app:layout_constraintTop_toBottomOf="@+id/textView72" />

<ImageView
    android:id="@+id/imageView26"
    android:layout_width="33dp"
    android:layout_height="46dp"
    android:layout_marginStart="-34dp"
    app:layout_constraintBottom_toBottomOf="@+id/spinnerMan"
    app:layout_constraintStart_toEndOf="@+id/spinnerMan"
    app:layout_constraintTop_toTopOf="@+id/spinnerMan"
    app:srcCompat="@drawable/baseline_arrow_drop_down_24" />

<TableLayout
    android:id="@+id/tlMarcado"
    android:layout_width="700dp"
    android:layout_height="789dp"
    android:layout_marginStart="16dp"
    android:layout_marginTop="8dp"
    android:layout_marginEnd="16dp"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/spinner3">

    <TableRow
        android:background="#51B435"
        android:padding="10dp">

        <TextView
            android:layout_width="120dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="DESCRIPCIÓN"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="78dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:singleLine="false"
            android:text="PRECIO


            CONTRATISTA"
            android:textColor="@color/white" />

        <TextView
            android:id="@+id/tvTarjetaML"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />
    </TableRow>

    <TableRow
        android:background="#F0F7F7"
        android:padding="5dp">

        <TextView
            android:id="@+id/tvDescML"
            android:layout_width="120dp"
            android:layout_height="55dp"
            android:layout_gravity="center"
            android:background="@drawable/tableborder"
            android:gravity="center"
            android:text="FAB. DE REGISTRO PLUBIAL" />

        <TextView
            android:id="@+id/tvPrecioML"
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_gravity="center"
            android:layout_weight="1"
            android:background="@drawable/tableborder"
            android:gravity="center"
            android:text=" $129.00" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="@color/blueM"
            android:padding="6dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="@color/blueM"
            android:padding="6dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="@color/blueM"
            android:padding="6dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="@color/blueM"
            android:padding="6dp" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:layout_weight="1"
            android:background="#2A42C6"
            android:padding="6dp" />

    </TableRow>

    <TableRow
        android:background="#F0F7F7"
        android:padding="5dp"/>

    <TableRow
        android:background="#F0F7F7"
        android:padding="6dp"/>

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TableRow
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
</TableLayout>

<Button
    android:id="@+id/btnguardarmercado"
    android:layout_width="562dp"
    android:layout_height="72dp"
    android:layout_marginStart="352dp"
    android:layout_marginTop="30dp"
    android:layout_marginEnd="352dp"
    android:background="@drawable/btn_gray"
    android:text="GUARDAR AVANCE"
    android:textSize="30sp"
    app:backgroundTint="@null"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/tlMarcado" />

<Spinner
    android:id="@+id/spinner4"
    android:layout_width="105dp"
    android:layout_height="36dp"
    android:layout_marginStart="16dp"
    android:background="@drawable/green_border"
    app:layout_constraintStart_toEndOf="@+id/textView71"
    app:layout_constraintTop_toTopOf="@+id/spinner3" />

<ImageView
    android:id="@+id/imageView88"
    android:layout_width="33dp"
    android:layout_height="46dp"
    android:layout_marginStart="-34dp"
    app:layout_constraintBottom_toBottomOf="@+id/spinner4"
    app:layout_constraintStart_toEndOf="@+id/spinner4"
    app:layout_constraintTop_toTopOf="@+id/spinner4"
    app:srcCompat="@drawable/baseline_arrow_drop_down_24" />

<TextView
    android:id="@+id/textView71"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="7dp"
    android:text="Al"
    android:textColor="#040404"
    android:textSize="20sp"
    app:layout_constraintBottom_toBottomOf="@+id/spinner3"
    app:layout_constraintStart_toEndOf="@+id/spinner3"
    app:layout_constraintTop_toBottomOf="@+id/textView73" />

</androidx.constraintlayout.widget.ConstraintLayout>

Kotlin code:

 private fun llenartabla() {
        val tableLayout = findViewById<TableLayout>(R.id.tlMarcado)
        val obraS = SharedApp.prefs.obra
        val obraSt = obraS.toString()

        val dbHelper = DBHandler(this)
        val db = dbHelper.readableDatabase

        val cursor: Cursor = db.rawQuery("select distinct dstarjeta, insumo, cantidad, precio_insumo, lote, manzana, id_detalle_kontrol from ActividadesM where obra = '" + obraSt + "'", null)

cursor.moveToFirst()
    do{
        val a = TableRow(this)
        a.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)

        val tvCodigo = tableLayout.findViewById<View>(R.id.tvDescML) as TextView
        tvCodigo.text = cursor.getString(0)
        if (tvCodigo.getParent() != null) {
            (tvCodigo.getParent() as ViewGroup).removeView(tvCodigo) // <- fix
        }
        a.addView(tvCodigo)

        val tvDescripcion = tableLayout.findViewById<View>(R.id.tvTarjetaML) as TextView
        tvDescripcion.text = cursor.getString(6)
        if (tvDescripcion.getParent() != null) {
            (tvDescripcion.getParent() as ViewGroup).removeView(tvDescripcion) // <- fix
        }
        a.addView(tvDescripcion)

        val tvPrecio = tableLayout.findViewById<View>(R.id.tvPrecioML) as TextView
        tvPrecio.text = cursor.getString(2)
        if (tvPrecio.getParent() != null) {
            (tvPrecio.getParent() as ViewGroup).removeView(tvPrecio) // <- fix
        }
        a.addView(tvPrecio)

        tableLayout.addView(a)
    }while (cursor.moveToNext())    }

I can't get it to work:

enter image description here

2

There are 2 answers

2
avinash On BEST ANSWER

I would also recommend to use "RecyclerView". But in case if you need to use the tablelayout, please consider following

I created a sample app based on your issue.

a) Update the table TableLayout as follows

<?xml version="1.0" encoding="utf-8"?>

<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".sobounty.SoBountctivity">
<TableLayout
    android:id="@+id/test_table"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
    <TableRow
        android:background="#51B435"
        android:padding="10dp">

        <TextView
            android:layout_width="120dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:gravity="center"
            android:text="DESCRIPCIÓN"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="78dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:singleLine="false"
            android:text="PRECIO


        CONTRATISTA"
            android:textColor="@color/white" />

        <TextView
            android:id="@+id/tvTarjetaML"
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="36dp"
            android:layout_gravity="center"
            android:layout_weight="0.5"
            android:gravity="center"
            android:text="015004001"
            android:textColor="@color/white" />
    </TableRow>


</TableLayout>

I am using it as layout so, I used ScrollView as root container.

b) Create a second layout file (table_row_layout)as follows (add your styles etc in it, I have removed few of them to make things simple). This contains the row views.

<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
    android:id="@+id/tvDescML"
    android:layout_width="120dp"
    android:layout_height="55dp"
    android:layout_gravity="center"
    android:gravity="center"
    android:text="FAB. DE REGISTRO PLUBIAL" />

<TextView
    android:id="@+id/tvPrecioML"
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:layout_gravity="center"
    android:layout_weight="1"
    android:gravity="center"
    android:text=" $129.00" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:layout_weight="1"
    android:padding="6dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:layout_weight="1"
    android:padding="6dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:layout_weight="1"
    android:padding="6dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:layout_weight="1"
    android:padding="6dp" />

<TextView
    android:layout_width="wrap_content"
    android:layout_height="60dp"
    android:layout_weight="1"
    android:background="#2A42C6"
    android:padding="6dp" />
 </TableRow>

c) Activity code (Adjust the logic as per your need) Here, we will inflate the table_row_layout and then add it to the viewgroup

class SoBountctivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_so_bountctivity)
    // tableLayout i which we want to insert view
    val tableLayout = findViewById<TableLayout>(R.id.test_table)
    // Fake data
    val fruitList = returnFruitList()
    // layoutInflater
    val layoutInflater = layoutInflater

    // Your cursor can replace the forEach. Looping over the data
    fruitList.forEach {

        // Get the new row_layout
        val view = layoutInflater.inflate(R.layout.table_row_layout, tableLayout, false)
        // Get the views in which you want to add the data
        val textView = view.findViewById<TextView>(R.id.tvDescML)
        // Set the data
        textView.text = it
        // Add the row view in tableLayout
        tableLayout.addView(view)
    }


    for (rowIndex in 0 until tableLayout.childCount) {
        val rowView: TableRow = tableLayout.getChildAt(rowIndex) as TableRow
        for (colIndex in 0 until rowView.childCount) {
            val view = rowView.getChildAt(colIndex)
            view.setOnClickListener {
                // For listeners.
                onTableCellClicked(rowIndex, colIndex)

            }
        }
    }
}

private fun returnFruitList() = listOf("Apple", "Banana", "Pineapple", "Guava", "Berries", "JackFruit", "Tomato", "Papaya")

private fun onTableCellClicked(rowIndex: Int, colIndex: Int) {
    Toast.makeText(this, "I AM CLICKED row $rowIndex col $colIndex", Toast.LENGTH_SHORT).show()
}
}

However I too would take note of the comment left by @marcpetitvecino on the question. Using RecyclerView is a better approach, as it is very flexible, memory efficient, has smooth scrolling as it recycles / reuses views and is very modular / customisable.

Result : Sample

enter image description here

3
djmonki On

1. The problem with the code lies in how it is accessing the TextViews within the TableLayout.

This is a simplified look at the TableLayout.xml which shows the following structure:

<TableLayout
  android:id="@+id/tlMarcado"
  .....>
  <TableRow
     .....>
     <TextView
       android:id="@+id/tvTarjetaML"
       ...../>
  </TableRow>
</TableLayout>

The TextViews with IDs (tvDescML, tvTarjetaML, tvPrecioML) are not direct children of TableLayout. They are in fact children of TableRow within TableLayout

2. The code is attempting to source the TextViews by their IDs within the TableLayout view:

val tvCodigo = tableLayout.findViewById<View>(R.id.tvDescML) as TextView
tvCodigo.text = cursor.getString(0)
if (tvCodigo.getParent() != null) {
  (tvCodigo.getParent() as ViewGroup).removeView(tvCodigo) // <- fix
}
a.addView(tvCodigo)

To resolve this issue, the code needs to find the TableRow first, then find the TextView within that TableRow:

val a = TableRow(this)
a.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)

val tvCodigo = a.findViewById<TextView>(R.id.tvDescML)
tvCodigo.text = cursor.getString(0)
if (tvCodigo.getParent() != null) {
  (tvCodigo.getParent() as ViewGroup).removeView(tvCodigo) // <- fix
}
a.addView(tvCodigo)

3. Remove the 'if' condition and the subsequent removeView() call

This code checks if the tvCodigo TextView has a parent view and removes it:

if (tvCodigo.getParent() != null) {
  (tvCodigo.getParent() as ViewGroup).removeView(tvCodigo) // <- fix
}

The context provided above is to add the tvCodigo TextView to a new TableRow and add that TableRow to the TableLayout. The removeView() method is used to remove a view from its parent view hierarchy.

However, since the code is creating a new TableRow (a) and the tvCodigo TextView is set as the child, there is no possibility for the TextView to have an existing parent. This code is unnecessary and should be removed, this will not affect the functionality of the code and will make it cleaner:

val a = TableRow(this)
a.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)

val tvCodigo = a.findViewById<TextView>(R.id.tvDescML)
tvCodigo.text = cursor.getString(0)
a.addView(tvCodigo)

4. Make the Code more Performant

The addView() method is called multiple times, modifying the view hierarchy frequently can have a performance impact. So only apply the method to the TableLayout at the end of the do block :

cursor.moveToFirst()
  do{
    val a = TableRow(this)
    a.layoutParams = TableRow.LayoutParams(TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT)

    val tvCodigo = a.findViewById<TextView>(R.id.tvDescML)
    tvCodigo.text = cursor.getString(0)

    val tvDescripcion = a.findViewById<TextView>(R.id.tvTarjetaML)
    tvDescripcion.text = cursor.getString(6)

    val tvPrecio = a.findViewById<TextView>(R.id.tvPrecioML)
    tvPrecio.text = cursor.getString(2)

    tableLayout.addView(a)
  } while (cursor.moveToNext())

This answers the question, however I would take note of the comment left by @marcpetitvecino on the question.
Using RecyclerView is a better approach, as it is very flexible, memory efficient, has smooth scrolling as it recycles / reuses views and is very modular / customisable.