package org.edx.mobile.view.adapters;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.view.ViewGroup;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Implementation of {@link FragmentPagerAdapter} that takes a static list
* of Fragments as the items.
*/
public class StaticFragmentPagerAdapter extends FragmentPagerAdapter {
@NonNull
private List<Item> items = Collections.emptyList();
@NonNull
private final Map<Integer, Fragment> positionToFragment = new HashMap<>();
public StaticFragmentPagerAdapter(@NonNull FragmentManager manager, @NonNull Item... items) {
super(manager);
setItems(Arrays.asList(items));
}
public void setItems(@NonNull List<Item> items) {
this.items = new LinkedList<>(items);
notifyDataSetChanged();
}
@Override
public int getCount() {
return items.size();
}
// Despite the name, this method is actually used for *instantiating* each fragment
@Override
public Fragment getItem(int position) {
return items.get(position).generateFragment();
}
public Fragment getFragment(int position) {
return positionToFragment.get(position);
}
@Override
public CharSequence getPageTitle(int position) {
return items.get(position).title;
}
@Override
public Fragment instantiateItem(ViewGroup container, int position) {
final Fragment fragment = (Fragment)super.instantiateItem(container, position);
positionToFragment.put(position, fragment);
return fragment;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
super.destroyItem(container, position, object);
positionToFragment.remove(position);
}
/**
* Data class representing a page.
*/
public static final class Item {
private static String ERROR_MSG_INSTANTIATION = "Unable to instantiate fragment %s: make " +
"sure class name exists, is public, and has an empty constructor that is public.";
private final Class<? extends Fragment> fragmentClass;
private final Bundle args;
private final CharSequence title;
public Item(Class<? extends Fragment> fragmentClass) {
this(fragmentClass, null, null);
}
public Item(Class<? extends Fragment> fragmentClass, Bundle args) {
this(fragmentClass, args, null);
}
public Item(Class<? extends Fragment> fragmentClass, CharSequence title) {
this(fragmentClass, null, title);
}
public Item(Class<? extends Fragment> fragmentClass, Bundle args, CharSequence title) {
if (args != null) {
args.setClassLoader(fragmentClass.getClassLoader());
}
this.fragmentClass = fragmentClass;
this.args = args;
this.title = title;
}
private Fragment generateFragment() {
final Fragment fragment;
try {
fragment = fragmentClass.newInstance();
} catch (InstantiationException e) {
throw new Fragment.InstantiationException(
String.format(ERROR_MSG_INSTANTIATION, fragmentClass), e);
} catch (IllegalAccessException e) {
throw new Fragment.InstantiationException(
String.format(ERROR_MSG_INSTANTIATION, fragmentClass), e);
}
fragment.setArguments(args);
return fragment;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Item item = (Item) o;
if (fragmentClass != null ? !fragmentClass.equals(item.fragmentClass) : item.fragmentClass != null)
return false;
if (args != null ? !args.equals(item.args) : item.args != null) return false;
return title != null ? title.equals(item.title) : item.title == null;
}
@Override
public int hashCode() {
int result = fragmentClass != null ? fragmentClass.hashCode() : 0;
result = 31 * result + (args != null ? args.hashCode() : 0);
result = 31 * result + (title != null ? title.hashCode() : 0);
return result;
}
}
}