While attempting to create an activity with tabbed view I used the Tabbed Activity template from Android Studio/IntelliJ IDEA.
I managed to instantiate 3 distinct tabs containing their own fragments defined in XML resources. One of these fragments had a ListView and to populate it I found a solution by creating a custom ArrayAdapter, found here.
My problem was to set the ListView to that adapter so it would display my data.
Well, it came to be easier than I expected..
To instantiate a fragment in one of the tabs, the Tabbed template flows as follows:
public static class FragmentExample extends Fragment {
public FragmentExample() {}
public static FragmentExample newInstance() {
FragmentExample fragment = new Fragment();
return fragment;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_example, container, false);
return rootView;
}
}
The fragment is inflated by this line, where fragment_example is the XML resource for it:
View rootView = inflater.inflate(R.layout.fragment_example, container, false);
I have tried to simply use the same method to inflate the XML containing my ListView and then programmatically populate data and finally setting the adapter to it. But it always threw on my face a NullPointerException referring to the adapter object.
I admit I had no idea why, until I read this answer:
MainActivity calls setContentView with R.layout.activity_main as parameter that contains a ViewPager and not a ListView. Since you don't have a ListView declare in to that layout, findViewById(android.R.id.list) returns null, and when you try access it (calling setAdapter) the NullPointerException is thrown. Awswer source here
And I realized I would have to change that particular fragment class, of course, but not only the code within..
By doing some research I found the ListFragment class and analysed it. Pretty interesting.
In order to inflate my ListView alongside my instantiated fragment I just had to extend it to the ListFragment class instead of the Fragment one and override its onCreateView like so (I actually adapted it from the super class itself):
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
final Context context = getActivity();
FrameLayout root = new FrameLayout(context);
FrameLayout lframe = new FrameLayout(context);
ListView lv = new ListView(getActivity());
lv.setId(android.R.id.list);
lv.setDrawSelectorOnTop(false);
lframe.addView(lv, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
root.addView(lframe, new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
// ------------------------------------------------------------------
// BEFORE SETTING YOUR CUSTOM ADAPTER TO THE LISTVIEW YOU MUST FIRST CREATE AN OBJECT
// OF IT AND POPULATE YOUR DATA. THIS IS SHOWN IN THE CUSTOM ARRAYADAPTER LINK ABOVE //
setListAdapter(customAdapter);
// ------------------------------------------------------------------
root.setLayoutParams(new FrameLayout.LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
return root;
}
What happens here is that it programmatically sets the fragment and the ListView, so I don't need a XML resource file for it.
Then it sets the adapter with setListAdapter method, which is defined in the ListFragment class.
I strongly recommend you to take a good look in that particular class to better understand it.
I'm new to Android development. I hope I can help others with what I'm learning.
Please feel free to post any improvement in the comments. :]