I have 3 ListFragments being handled by a viewPager (managed by a FragmentAdapter) - they work perfectly. Now when the user clicks an item in ListFragment #1, a new Fragment should open with the details. It's behaving strangely in the following manner:
Only clicking a list item twice opens the DetailFragment, yet debugging shows the first click indeed goes into the DetailFragment, but doesn't show the view (the view still shows the current ListFragment).
After clicking the 2nd time, the DetailFragment does show it's layout, but not the elements within it (like TextView, etc).
If the user 'accidently' swipes the screen when DetailFragment is showing, the viewPager sets it in place of the 2nd ListFragment! Only when pressing back on the DetailFragment view will 'reset' the viewPager to it's correct ListFragment. Of course if the user swipes when in a DetailFragment, the next ListFragment of the viewPager should appear, and the DetailFragment should be removed.
Thanks for any tips muddling through Android's odd world of fragments and views :)
public class PlanetFragment extends ListFragment{
LayoutInflater inflater;
ListView list;
ArrayList<HashMap<String, String>> planetListArray;
HashMap<String, String> planetMap;
Activity activity;
Context context;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.planets_tab_layout, container, false);
inflater=(LayoutInflater)getLayoutInflater(savedInstanceState);
activity = getActivity();
context = PlanetFragment.this.getActivity();
String dbTableName = "Table_Planets";
SQLiteHelper info = new SQLiteHelper(getActivity().getBaseContext());
info.open();
ArrayList<HashMap<String, String>> datafromSQL = info.getData(dbTableName);
if(!datafromSQL.isEmpty()){
planetListArray = new ArrayList<HashMap<String, String>>();
for (int i = 0; i<datafromSQL.size(); i++){
planetMap = new HashMap<String, String>();
planetMap.put(PLANET_ID, datafromSQL.get(i).get(KEY_PLANET_ID));
planetMap.put(ZODIAC_ID, datafromSQL.get(i).get(KEY_ZODIAC_ID));
planetMap.put(DEGREES, datafromSQL.get(i).get(KEY_DEGREES));
planetMap.put(CONTENT, datafromSQL.get(i).get(KEY_CONTENT));
planetListArray.add(planetMap);
}
info.close();
}
list = (ListView) v.findViewById(android.R.id.list);
PlanetAdapter adapter=new PlanetAdapter(getActivity(), R.layout.planets_row, planetListArray);
list.setAdapter(adapter);
return v;
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
//the dividers
getListView().setDivider(getResources().getDrawable(R.drawable.purplebartop));
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
super.onListItemClick(l, v, position, id);
HashMap<String, String> item = planetListArray.get(position);
Bundle bundle = new Bundle();
bundle.putSerializable("itemMap", item);
bundle.putInt("position", position);
Fragment frag = DetailFragment.newInstance();
frag.setArguments(bundle);
if (frag != null) {
getActivity().getSupportFragmentManager()
.beginTransaction()
.replace(R.id.pager, frag, "frag")
.addToBackStack("frag")
.commit();
}
}
}
public class DetailFragment extends Fragment{
Context context;
Activity activity;
TextView planetName;
public static android.support.v4.app.Fragment newInstance() {
DetailFragment f = new DetailFragment();
return f;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
inflater=(LayoutInflater)getLayoutInflater(savedInstanceState);
View v = inflater.inflate(R.layout.dialog_details, container, false);
activity = getActivity();
context = DetailFragment.this.getActivity();
planetName = (TextView)v.findViewById(R.id.planetNameExpanded);
planetName.setText("planetX");
return v;
}
}
EDIT:
Instead of getActivity().getSupportFragmentManager()
I have also tried getChildFragmentManager()
but it always gives the error: The method getChildFragmentManager()
is undefined for the type PlanetFragment.
When you click on a list item, you are indeed constructing a new details fragment and telling the fragment manager to replace the tag "frag" with that fragment. However, you are not telling the view pager to switch over to that fragment.
Since you already have a back-pointer to your activity, you could use findViewById to find your view pager, and then call viewPager.setCurrentItem.
I think you might be asking for trouble by constructing a new details fragment inside of the list fragment. When you use a FragmentPagerAdapter, the adapter usually constructs the fragments. I would have implemented this by letting the adapter make the fragments, and then in your onListItemClick find the existing details fragment and call a method on it to configure it with the new data. But maybe just the setCurrentItem will fix your problem.
EDIT
First, I would write your FragmentPagerAdapter so you can use getItem to fetch the existing fragment, without creating a new one each time.
Also add functions in your activity to work with your fragments:
Now when you click on an item in your list fragment, you can get the existing detail fragment, configure it, and set the ViewPager to show the detail fragment.