Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scrollview and OnClick handlers not working when view is cleared and re-created

Tags:

android

I'm having an odd problem and I am not sure where the issue is.

I have an XML file which contains two linear layouts, only one is visible at a time depending on what setting has been used. Both views are dynamically generated and set an on click listener and onlongclicklistener.

Below is the XML layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <LinearLayout android:id="@+id/resultTableContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:visibility="gone">
        <ScrollView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:scrollbars="horizontal"
            android:fillViewport="true">
            <HorizontalScrollView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:fillViewport="true">
                <TableLayout android:id="@+id/resultTable"
                    android:stretchColumns="1"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:shrinkColumns="false">
                </TableLayout>
            </HorizontalScrollView>
        </ScrollView>
    </LinearLayout>
    <LinearLayout android:id="@+id/formattedResultContainer"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        android:visibility="gone">
        <ScrollView android:id="@+id/formattedScrollContainer"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:scrollbars="vertical">
            <LinearLayout android:id="@+id/formattedResult"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"/>
        </ScrollView>
    </LinearLayout>
</RelativeLayout>

For simplicity I'll call the first linear layout container view 1 and the second linear layout container view 2.

Both views have their visibility set to gone by default, and when the screen first loads, view 1's visibility is set to visible and the view is dynamically generated using the following code:

@Override
    public void processResult(final View.OnClickListener editRowClickListener, final View.OnLongClickListener columnLongClickListener)
    {
        try
        {
            this.getActivity().runOnUiThread(new Runnable()
            {
                @Override
                public void run()
                {
                    if (shouldExistingResultBeCleared())
                    {
                        resultView.removeAllViews();
                    }
                    if (getSettings().getInt(Defines.SharedPreferenceSettings.APPLICATION_THEME, com.BoardiesITSolutions.Library.R.style.LibAppTheme)
                            == com.BoardiesITSolutions.Library.R.style.LibAppTheme)
                    {
                        resultView.setBackgroundColor(Color.WHITE);
                    }
                    else
                    {
                        resultView.setBackgroundColor(Color.BLACK);
                    }
                }
            });

            this.showDialog(getJSONResult().length());

            new Thread(new Runnable()
            {
                @Override
                public void run()
                {
                    try
                    {
                        for (int i = 0; i < getJSONResult().length(); i++)
                        {
                            HashMap<Integer, String> fieldIndexAndValue = new HashMap<Integer, String>();
                            final TableRow tr;
                            if (!getSettings().getBoolean("IsDarkTheme", false))
                            {
                                tr = (TableRow) getFragment().getLayoutInflater(getFragment().getArguments()).inflate(R.layout.result_table_row_light_theme, resultView, false);
                            } else
                            {
                                tr = (TableRow) getFragment().getLayoutInflater(getFragment().getArguments()).inflate(R.layout.result_table_row_dark_theme, resultView, false);
                            }
                            if (i == 0)
                            {
                                tr.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.appPrimaryColour));
                            }
                            else if (i % 2 == 0)
                            {
                                if (!getSettings().getBoolean("IsDarkTheme", false))
                                {
                                    tr.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.resultRowLightThemeAlternateRow));
                                } else
                                {
                                    tr.setBackgroundColor(ContextCompat.getColor(getActivity(), R.color.resultRowDarkThemeAlternateRow));
                                }
                            }
                            ImageButton imageButton = (ImageButton) getFragment().getLayoutInflater(getFragment().getArguments()).inflate(R.layout.row_edit_image, tr, false);
                            imageButton.setOnClickListener(editRowClickListener);
                            tr.addView(imageButton);

                            if (i == 0)
                            {
                                imageButton.setVisibility(View.INVISIBLE);
                            }

                            JSONArray array = getJSONResult().getJSONArray(i);
                            String currentField = null;
                            for (int j = 0; j < array.length(); j++)
                            {
                                final TextView textView;
                                textView = (TextView) getFragment().getLayoutInflater(getFragment().getArguments()).inflate(R.layout.result_textview, tr, false);
                                textView.setText(array.getString(j));
                                if (!getSettings().getBoolean(Defines.SharedPreferenceSettings.MULTILINE_RESULT, true))
                                {
                                    textView.setSingleLine(true);
                                }
                                if (i == 0)
                                {
                                    textView.setTypeface(null, Typeface.BOLD);
                                    //Get the fields into a index and field hash map
                                    addIndexAndField(j, array.getString(j));
                                } else
                                {
                                    textView.setOnLongClickListener(columnLongClickListener);
                                    fieldIndexAndValue.put(j, array.getString(j));
                                }
                                getActivity().runOnUiThread(new Runnable()
                                {

                                    @Override
                                    public void run()
                                    {
                                        tr.addView(textView);
                                    }
                                });
                            }
                            imageButton.setTag(fieldIndexAndValue);

                            getActivity().runOnUiThread(new Runnable()
                            {

                                @Override
                                public void run()
                                {
                                    resultView.addView(tr);
                                }
                            });
                            updateProgressDialog();
                            //handler.sendMessage(handler.obtainMessage());
                        }
                        closeDialog();
                        //((ResultProcessor)resultProcessor).closeDialog();
                    }
                    catch (JSONException ex)
                    {

                    }
                }
            }).start();
        }
        catch (Exception ex)
        {

        }
    }

This works perfectly fine. The user presses an option to switch to view 2, so view 1 is cleared, visibility set to gone ans view 2 is set to visible. This view is then dynamically generated and the on click listeners are set to the view accordingly. (I haven't included the code for this view as I don't believe it is related and this view always works without exception).

If the user then switches back to view 1, view 2 is cleared, and visibility set to gone and view 1 is back to being visible and the same method, as shown above, is used to re-create the view dynamically and assign the on click listeners.

The view itself looks fine, however, there is no user interaction possible, the scroll view no longer scrolls vertically or horizontally and neither of the click handlers works.

As view 1 work once, I don't understand why it won't when it is re-generated, but view 2 always works no matter what.

like image 666
Boardy Avatar asked Mar 30 '17 20:03

Boardy


5 Answers

I've managed to resolve the issue I was having. I tried what was suggested but unfortunately it didn't have a lot of effect.

What I had currently was one fragment, which had to linear layout containers, and when the view was switched one container was hidden and the container shown and then reload the relevant view content.

I've instead changed it so each view, is instead in a different fragment and with its own XML layout file, then when the view is switched, it uses a fragment transaction to replace one fragment view with the other and then uses the same code as I had above to dynamically populate the relevant view content.

like image 84
Boardy Avatar answered Oct 24 '22 07:10

Boardy


You could try outputting the exception details in the catch blocks in case an exception is being raised somewhere:

catch (JSONException ex)
    ex.printStackTrace();
    Log.e("Exception: ", ex.getMessage());
    throw new RuntimeException(ex);
}

and

catch (Exception ex) {
    ex.printStackTrace();
    Log.e("Exception: ", ex.getMessage());
    throw new RuntimeException(ex);
}
like image 1
robd Avatar answered Oct 24 '22 07:10

robd


Set layout visibility:

view1.setVisibility(View.VISIBLE)
view2.setVisibility(View.GONE)

instead of:

resultView.removeAllViews();
resultView.addView();
like image 1
toro Avatar answered Oct 24 '22 07:10

toro


Had same issue. I suggest you to try to use nestedScrollview instead scrollview and put scrolling off. and set two method in your activity that will help you

like image 1
parik dhakan Avatar answered Oct 24 '22 05:10

parik dhakan


Should try NestedScrollView instead ScrollView

like image 1
Cesario Avatar answered Oct 24 '22 06:10

Cesario