Search code examples
androidandroid-tablelayouttablerow

Problems with the click event in a TableLayout


Good Morning everyone,

I'm facing yet another problem in my path of learning Android. I made a dynamic TableLayout with the content of an CSV file. I need that when I click/touch a row in the table, the color should change, and later with a click of a button get the content of the same line. Now I'm stucked with the first part and of course I have no clue about how to get the data of the row.

I declared the table inside a LinearLayout that is also inside of a ScrollView in my layout with the following properties:

    <ScrollView
    android:id="@+id/scrollMotors"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentLeft="true"
    android:layout_alignParentRight="true"
    android:layout_alignParentTop="true"
    android:layout_alignParentBottom="true"
    android:layout_marginLeft="50dp"
    android:layout_marginRight="50dp"
    android:layout_marginTop="90dp"
    android:layout_marginBottom="50dp" >
    <LinearLayout
        android:id="@+id/layoutMotors"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
        <TableLayout
            android:id="@+id/tableMotors"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:clickable="true"
            android:focusable="true"
            android:focusableInTouchMode="true"
            android:gravity="center_vertical"
            android:stretchColumns="*" >

        </TableLayout>
    </LinearLayout>
</ScrollView>

After in my java code, I declared the creation of the line:

        //Initialization of my table
    my_tableMotors = (TableLayout) findViewById(R.id.tableMotors);
    //This is an ArrayList<ArrayList<String>> that contains the lines of the CSV file,
    //I use this variable as a dynamic Matrix because my CSV file can change its dimensions.
    m = valuesFile.size(); 
    for (n = 0 ; n < m ; n++)
    {
        //Declaration and initialization of my rows
        final TableRow line = new TableRow(MotorActivity.this);
        //Setting the parameters of my row
        line.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.WRAP_CONTENT));
        line.setFocusable(true);
        line.setFocusableInTouchMode(true);
        line.setClickable(true);
        //Initialization of my TextViews that are gonna be the content of each one of the rows in the dynamic TableLayout
        myCol1 = new TextView(MotorActivity.this);
        myCol2 = new TextView(MotorActivity.this);
        myCol3 = new TextView(MotorActivity.this);
        myCol4 = new TextView(MotorActivity.this);
        j = valuesFile.get(n).size();
        for (i = 0 ; i < j ; i++)
        {
            switch(i)
            {
            case 0: 
                if (n == 0)
                {
                    myCol1.setText("Line");
                }
                else
                {
                    myCol1.setText(valuesFile.get(n).get(i)); //Sets value for the column
                }
                line.addView(myCol1);
                break;
            case 1:
                myCol2.setText(valuesFile.get(n).get(i)); //Sets value for the column
                line.addView(myCol2);
                break;
            case 2:
                myCol3.setText(valuesFile.get(n).get(i)); //Sets value for the column
                line.addView(myCol3);
                break;
            case 3:
                myCol4.setText(valuesFile.get(n).get(i)); //I use this variable for some other purpose
                break;
            }
        }
        my_tableMotors.addView(line);
    }
    my_tableMotors.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {onClickedRow(); }});
}

From what I've seen and read here, the best is to use a setOnClickListener and that's what I did using a bit of two different answers that I found here:

    public void onClickedRow()
{
    m = my_tableMotors.getChildCount();
    for (n = 0 ; n < m ; n++)
    {
        if (my_tableMotors.getChildAt(n).hasFocus())
        {
            my_tableMotors.setBackgroundColor(myColor);
        }
    }
}

Now I can't get any focus at the tableLayout at all, so please if you see something wrong in my code or if you know how to help me with this I would appreciate it a lot!!!!

Many thanks in advance :).

EDIT 1

I found the way to get the focus. I changed the method not to the whole TableLayout but only to the TableRow, so ended up as this:

*Before*

        my_tableMotors = (TableLayout) findViewById(R.id.tableMotors);
    m = valuesFile.size(); 
    for (n = 0 ; n < m ; n++)
    {
        //Declaration and initialization of my rows
        final TableRow line = new TableRow(MotorActivity.this);
        /*Other declarations*/
        j = valuesFile.get(n).size();
        for (i = 0 ; i < j ; i++)
        {
            /*Code*/
        }
        my_tableMotors.addView(line);
    }
    my_tableMotors.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {onClickedRow(); }});
}

*After*

    my_tableMotors = (TableLayout) findViewById(R.id.tableMotors);
m = valuesFile.size();
for (n = 0 ; n < m ; n++)
{
    //Declaration and initialization of my rows
        final TableRow line = new TableRow(MotorActivity.this);
    /*Other declarations*/
    j = valuesFile.get(n).size();
    for (i = 0 ; i < j ; i++)
    {
        /*Code*/
    }
    line.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {onClickedRow(); }});
    my_tableMotors.addView(line);
}

I also made the change on how to set the color of the line:

*Before*

my_tableMotors.setBackgroundColor(myColor);

*After*

my_tableMotors.getChildAt(n).setBackgroundResource(R.drawable.myColor);

Now I'm busy finding out how to get the data from the TableRow. As soon as I get that solve or an answer from you I think I have my problem solved!!!

EDIT 2

With the help of @Luksprog I could find an answer to my problem of retrieving the content!!! I did used the next code using his solution:

    public void onClickedRow()
{
    TableRow clickedRow = new TableRow(MotorActivity.this);
    m = my_tableMotors.getChildCount();
    for (n = 1 ; n < m ; n++)
    {
        if (my_tableMotors.getChildAt(n).isFocused())
        {
            my_tableMotors.getChildAt(n).setBackgroundResource(R.drawable.highlightTableRow);
            clickedRow = (TableRow) my_tableMotors.getChildAt(n);
            j = clickedRow.getChildCount();
            for (i = 0; i < j ; i++)
            {
                switch(i)
                {
                case 0:
                    myField1 = (TextView) clickedRow.getChildAt(i);
                    break;
                case 1:
                    myField2 = (TextView) clickedRow.getChildAt(i);
                    break;
                case 2:
                    myField3 = (TextView) clickedRow.getChildAt(i);
                    break;
                }
            }
        }
    }
}

Solution

  • Don't set the OnClickListener on the TableLayout instead set it to each TableRow that you create in that for loop:

    for (n = 0 ; n < m ; n++) {
        //Declaration and initialization of my rows
        final TableRow line = new TableRow(MotorActivity.this);
        line.setOnClickListener(mListener);
        line.setId(1000 + n);
        // ...
    

    where mListener is:

    OnClickListener mListener = new OnClickListener() {
    
         public void onClick(View v) {
             // v is the TableRow that was clicked
             v.setBackgroundColor(Color.RED);
             // mClickedPosition is a int field representing the clicked row(to know the position later)
             // if you allow more than one row to be clicked at one time, use a list of ints
             // or something like this
             mClickedPosition = v.getId() - 1000; 
         }
    }
    

    To later retrieve the content of the row you would use the mClickedPosition variable:

    TableRow clickedRow = (TableRow) my_tableMotors.getChildAt(mClickedPosition);
    // having the child TableRow that was clicked you could extract any data you want from it
    // of course you could simply use the mClickedPosition to extract the data from whatever data structure you have(I'm looking at valuesFile)