I have an empty TableLayout with header in activity_main.xml as follows
<TableLayout
android:id="@+id/sensorTable"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbarAlwaysDrawVerticalTrack="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/lineChart">
<TableRow>
<TextView
android:layout_width="75dp"
android:layout_column="0"
android:layout_weight="1"
android:text="Id"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="75dp"
android:layout_column="0"
android:layout_weight="1"
android:text="Sensor"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_width="75dp"
android:layout_column="1"
android:layout_weight="1"
android:text="Reading"
android:textSize="20sp"
android:textStyle="bold"></TextView>
</TableRow>
</TableLayout>
Then, I programmatically add tablerows in MainActivity.kt as follows.
val stableLayout = findViewById<TableLayout>(R.id.sensorTable)
var scout: Int = 0
while (scout<ccsen1.count()){
val tableRow = LayoutInflater.from(this).inflate(R.layout.table_item, null, false)
val idauto = tableRow.findViewById<View>(R.id.idautoint) as TextView
val Sensor = tableRow.findViewById<View>(R.id.sensor) as TextView
val Reading = tableRow.findViewById<View>(R.id.reading) as TextView
idauto.setText((ccsen1.elementAt(scout)).sidauto)
Sensor.setText((ccsen1.elementAt(scout)).sname)
Reading.setText((ccsen1.elementAt(scout)).sreading)
stableLayout.addView(tableRow)
scout++
}
Then, I try to access the tablerows as follows in another function, but the app crashes. It only displays the header of the TableLayout which is defined in the XML file as shown above (id, sensor, reading). As soon as the while loop increments to the next tablerow, app crashes as if there are NO MORE tablerows to be found. However, stableLayout.childCount
returns 3 rows. So, val t = stableLayout.getChildAt(index:1) as TableRow
fails and crashes the app.
val RowCount = stableLayout.childCount
var scout3: Int = 0
while (scout3<RowCount) {
val t = stableLayout.getChildAt(scout3) as TableRow
//TextView firstTextView = (TextView) t.getChildAt(0);
val firstTextView = t.getChildAt(0) as TextView
//TextView secondTextView = (TextView) t.getChildAt(1);
val secondTextView = t.getChildAt(1) as TextView
//TextView secondTextView = (TextView) t.getChildAt(2);
val thirdTextView = t.getChildAt(2) as TextView
//String firstText = firstTextView.getText().toString();
val firstText = firstTextView.text.toString()
//String secondText = secondTextView.getText().toString();
val secondText = secondTextView.text.toString()
//String secondText = secondTextView.getText().toString();
val thirdText = thirdTextView.text.toString()
Toast.makeText(this@MainActivity, "$firstText-$secondText-$thirdText", Toast.LENGTH_SHORT).show()
scout3++
}
Why is this and how do I fix this? Am I missing something?
2024-12-18 13:19:58.221 7183-7183/com.example.installedapps E/e.installedapp: Attempt to load writable dex file: /data/data/com.example.installedapps/code_cache/.overlay/base.apk/classes3.dex
2024-12-18 13:19:58.558 7183-7217/com.example.installedapps E/QT: [QT]file does not exist
2024-12-18 13:19:59.478 7183-7222/com.example.installedapps E/ion: ioctl c0044901 failed with code -1: Invalid argument
2024-12-18 13:20:17.902 7183-7183/com.example.installedapps E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.installedapps, PID: 7183
java.lang.ClassCastException: androidx.constraintlayout.widget.ConstraintLayout cannot be cast to android.widget.TableRow
at com.example.installedapps.MainActivity.createButtonDynamically$lambda-4(MainActivity.kt:173)
at com.example.installedapps.MainActivity.$r8$lambda$WmSUg8-J-d8vkkGFbIzKlnN5bls(Unknown Source:0)
at com.example.installedapps.MainActivity$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
at android.view.View.performClick(View.java:7792)
at android.widget.TextView.performClick(TextView.java:16112)
at android.view.View.performClickInternal(View.java:7769)
at android.view.View.access$3800(View.java:910)
at android.view.View$PerformClick.run(View.java:30218)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loopOnce(Looper.java:226)
at android.os.Looper.loop(Looper.java:313)
at android.app.ActivityThread.main(ActivityThread.java:8751)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:571)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1135)
You should not use a LinearLayout or ConstraintLayout, the Top Element in table_item.xml
should be a TableRow
. LinearLayout will sort of work as TableRow
extends LinearLayout
BUT the Table Column aligning and sizing features won't work.
But as you have hardcoded the layout_width
to a fixed value it will seem to align (until one column takes more than 75dp)
If you look at the documentation of TableRow it says
The children of a TableRow do not need to specify the layout_width and layout_height attributes in the XML file. TableRow always enforces those values to be respectively ViewGroup.LayoutParams.MATCH_PARENT and ViewGroup.LayoutParams.WRAP_CONTENT
You might as well just use a verticial and then horizontal layouts for your Table when you fix the widths of the TextView
and not have the extra cost of TableLayout.
To correctly use TableLayout activity_main.xml
should be
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TableLayout
android:id="@+id/sensorTable"
android:layout_width="0dp"
android:layout_height="0dp"
android:scrollbarAlwaysDrawVerticalTrack="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TableRow>
<TextView
android:layout_column="0"
android:layout_weight="1"
android:text="Id"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_column="0"
android:layout_weight="1"
android:text="Sensor"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:layout_column="1"
android:layout_weight="1"
android:text="Reading"
android:textSize="20sp"
android:textStyle="bold"/>
</TableRow>
</TableLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
and table_item.xml
<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="@+id/idautoint"
android:layout_column="0"
android:layout_weight="1"
android:textSize="20sp" />
<TextView
android:id="@+id/sensor"
android:layout_column="0"
android:layout_weight="1"
android:textSize="20sp" />
<TextView
android:id="@+id/reading"
android:layout_column="1"
android:layout_weight="1"
android:textSize="20sp" />
</TableRow>
This will allow the main Feature of TableLayout which is auto aligning columns based on the Max width of a column to work.
The way you have it at the moment then TableLayout
is just acting as another wasted LinearLayout