How to add items dynamically in a Listview that is inside a Fragment?

Asked

Viewed 1,645 times

1

I’m developing a layout in an Android app that will be used in Tablets, basically the layout main possesses a Toolbar, one Drawerlayout, one Framelayout and a Fragment, as is below:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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">

    <include
        android:id="@+id/toolbar"
        layout="@layout/default_toolbar" />

    <android.support.v4.widget.DrawerLayout 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/drawer_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/toolbar">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:baselineAligned="false"
            android:orientation="horizontal">

            <FrameLayout
                android:id="@+id/content_frame"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.8" />

            <fragment
                android:id="@+id/history_frag"
                class="br.com.exemplo.HistoryFragment"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.2"
                tools:layout="@layout/history_fragment" />

        </LinearLayout>

        <ListView
            android:id="@+id/left_drawer"
            android:layout_width="240dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/background_light"
            android:choiceMode="singleChoice"
            android:divider="@android:color/transparent"
            android:dividerHeight="1dp" />

    </android.support.v4.widget.DrawerLayout>

</RelativeLayout>

The content_frame is responsible for accommodating the Fragments according to the option selected and the history_frag is a Fragment fixed, that Fragment owns the 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="match_parent">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="16dp"
        android:text="@string/lbl_history"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/textView1"
        android:layout_marginBottom="16dp">

        <ListView
            android:id="@android:id/list"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:choiceMode="singleChoice" />

    </ScrollView>

    <Button
        android:id="@+id/btnClear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/scrollView"
        android:text="@string/lbl_clear" />

</RelativeLayout>

I would like to know how to dynamically add new items to Listview inside the history_frag, through the Fragment current that is in the content_frame. I tried to do that:

// Fragment qualquer que está no content_frame, todos os fragments que serão chamados 
// possuem um Button chamado btnRandom.
public class ExemploFragment extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, 
                            @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.exemplo_fragment, container, false);

        Button btnRandom = (Button) v.findViewById(R.id.btnRandom);

        btnRandom.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // aqui é adicionado um novo item ao history_frag
                HistoryFragment historyFrag = (HistoryFragment) getActivity().
                        getSupportFragmentManager().findFragmentById(R.id.history_frag);
                if (historyFrag != null) {
                    historyFrag.addHistory("Um item qualquer");
                }
            }
        });

        return v;
    }

}

The class Historyframent is like this:

public class HistoryFragment extends ListFragment {

    private ArrayAdapter<String> mArrayAdapter;
    private List<String> mList;

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        mList = new ArrayList<String>();
        mList.add("a");
        mList.add("b");
        mList.add("c");
        mArrayAdapter = new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_1, mList);
        setListAdapter(mArrayAdapter);
    }

    @Override
    public View onCreateView(final LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.history_fragment, container, false);

        Button btnClear = (Button) v.findViewById(R.id.btnClear);
        btnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mArrayAdapter.clear();
                mArrayAdapter.notifyDataSetChanged();
            }
        });

        return v;
    }

    public void addHistory(String history) {
        if (mArrayAdapter != null) {
            mArrayAdapter.add(history);
            mArrayAdapter.notifyDataSetChanged();
        }
    }

}

In doing so, only the first item is added to the Listview, I tried to debug the code and the items are passed to the Historyfragment correctly, only are not updated. I also tried to call the notifyDataSetChanged(); within the runOnUiThread, but it didn’t work. Does anyone have any idea where I might be missing?

  • How is your code Adapter?

  • @Wakim, I updated the code, I tried to add some items directly through the code, but also it was not, only the first item is displayed.

1 answer

2


The problem is that you put a ListView within a ScrollView, which is unnecessary because the ListView already manages the items that are displayed in the space that is given for it to "render".

I understand you want to force TextView and the Button appear and the ListView occupy the rest of the available space. Giving a suggestion would be:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginTop="16dp"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <ListView
        android:id="@android:id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:weight="1"
        android:choiceMode="singleChoice" />

    <Button
        android:id="@+id/btnClear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/lbl_clear" />
</LinearLayout>

The trick in this case is to use the layout_height="0dp" and the layout_weight="1", with this you force the ListView take up all available space after calculating the size of the other children of the same father.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.