ListFragment
is a subclass of the Fragment
class. List fragments are fragments that extend the ListFragment
class. Fragments like this have special methods for working with lists and adapters, they do not need a layout file because they automatically have their own layout, and they have just one root view - a ListView
. Modern list fragments can have a GridView
though.
Creating a ListFragment
When you create a ListFragment
subclass, you won't need to override onCreateView()
unless you want to add some custom behavior to it.
If you want to override it however, you'll have to call super()
in the method body.
Let's create a list fragment named DemoListFragment and override onCreateView()
public class DemoListFragment extends ListFragment {
@Override
public View onCreateview(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return super.onCreateView(inflate, container, savedInstanceState);
}
}
Code breakdown
In the onCreateView
method, we did not inflate an xml layout file. This is because list fragments have their own layout automatically and so we don't need to inflate our own xml file.
Binding Data to ListFragments
In list fragments, you bind data to their ListViews
with adapters just like in activities, but there are two major differences. They are:
- The constructor of an
Adapter
usually takes aContext
argument. If you were constructing theAdapter
in an activity, you would have passed itthis
as theContext
argument because activities implementContext
. But since the adapter is getting constructed in a fragment(an object that doesn't implement Context), you have to get the context from somewhere else. You have to pass it the result of callinggetContext()
on theLayoutInflater
object.
Assuming you want to create an ArrayAdapter
named adapter, for an array named demoArray and the layout for one list item is defined in the file list_item.xml, you can do the job with the code snippet below.
ArrayAdapter<String> adapter = new ArrayAdapter(inflater.getContext(), android.R.layout.list_item, demoArray);
setListAdapter(adapter);
- We use
setListAdapter()
to set the adapter, and not .setAdapter(). That is because ListFragments already have a built-in reference to the list that you want to bind the adapter to. So you don't need to call it explicitly.
Responding to Clicks in the List Fragment
ListFragment
implements a listener automatically so you just have to implement the method onListItemClick()
to respond to clicks.
You can implement onListItemClick()
the default way - just by adding custom code to it - but it will make your Fragment
tightly coupled to your activity. To achieve loose coupling, you'll have to go extra steps. These steps are:
- Create an interface named
Listener
that has a handler method nameditemClicked()
. Any activity that we want to respond to clicks will implement the interface and override its method.
static interface Listener {
void itemClicked(long id);
}
- Create a private field inside the
ListFragment
to keep a reference to the activity that is listening.
private Listener listener;
- Register the activity that the fragment is being attached to as an implementer of that interface.
@Override void onAttach(Context context) {
super.onAttach(context);
this.listener = (Listener) context;
}
- In the list fragment's
onListItemClick()
method, respond to clicks by calling the listener's handler method nameditemClicked()
.
public void onListItemClick(ListView listView, View itemView, int position, long id) {
if (listener != null) {
listener.itemClicked(id);
}
}
With these done, we can implement the Listener
interface in any Activity
our ListFragment
will be attached to, override its itemClicked()
method and write some custom logic in it to handle the click.
class DemoActivity extends AppCompatAtivity implements Listener {
@Override
void itemClicked(long id) {
// You can add custom logic here
}
}
Previous article: Getting an Activity and a Fragment to Interact
Top comments (0)