Skip to content

Instantly share code, notes, and snippets.

@VladSumtsov
Created July 20, 2016 19:06
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save VladSumtsov/2128e0cc0f7c2131c0f971ee26d36ce5 to your computer and use it in GitHub Desktop.
Save VladSumtsov/2128e0cc0f7c2131c0f971ee26d36ce5 to your computer and use it in GitHub Desktop.
Flow mortar ViewPager Adapter with save state. Logic of saving state took from FragmentStatePagerAdapter.
package com.ghm.ui.adapter;
import android.content.Context;
import android.os.Bundle;
import android.os.Parcelable;
import android.support.v4.view.PagerAdapter;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.ghm.ui.util.ScreenHelper;
import java.util.ArrayList;
import java.util.List;
import flow.path.Path;
import io.techery.presenta.mortarscreen.ScreenScoper;
import mortar.MortarScope;
public class ScreenPagerStateAdapter<S extends Path> extends PagerAdapter {
protected final Context context;
private final List<S> screens;
private final ScreenScoper screenScoper;
private ArrayList<View> views = new ArrayList<>();
private ArrayList<SparseArray<Parcelable>> states = new ArrayList<>();
public ScreenPagerStateAdapter(Context context) {
this.context = context;
this.screens = new ArrayList<>();
screenScoper = new ScreenScoper();
}
public void addScreen(S... newScreens) {
for (S newScreen : newScreens) {
screens.add(newScreen);
}
notifyDataSetChanged();
}
@Override
public int getCount() {
return screens.size();
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
Path screen = screens.get(position);
String scopeName = getName(position);
MortarScope screenScope = screenScoper.getScreenScope(context, scopeName, screen);
Context screenContext = screenScope.createContext(context);
int layout = ScreenHelper.getLayout(screen);
View newChild = LayoutInflater.from(screenContext).inflate(layout, container, false);
container.addView(newChild);
fillIfNeed(position);
SparseArray<Parcelable> state = states.get(position);
if (state != null) {
newChild.restoreHierarchyState(state);
}
views.set(position, newChild);
return newChild;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
View view = ((View) object);
MortarScope screenScope = MortarScope.getScope(view.getContext());
container.removeView(view);
screenScope.destroy();
fillIfNeed(position);
SparseArray<Parcelable> array = new SparseArray<>();
view.saveHierarchyState(array);
states.set(position, array);
views.set(position, null);
}
public final S getItem(int position) {
return screens.get(position);
}
@Override public Parcelable saveState() {
Bundle bundle = new Bundle();
for (int i = 0; i < states.size(); i++) {
fillIfNeed(i);
SparseArray<Parcelable> state = states.get(i);
if (state == null) continue;
bundle.putSparseParcelableArray(getName(i), state);
}
for (int i = 0; i < views.size(); i++) {
fillIfNeed(i);
View view = views.get(i);
if (view == null) continue;
SparseArray<Parcelable> state = new SparseArray<>();
view.saveHierarchyState(state);
bundle.putSparseParcelableArray(getName(i), state);
}
return bundle;
}
@Override public void restoreState(Parcelable state, ClassLoader loader) {
Bundle bundle = (Bundle) state;
states.clear();
views.clear();
for (int i = 0; i < getCount(); i++) {
SparseArray<Parcelable> array = null;
try {
array = bundle.getSparseParcelableArray(getName(i));
} catch (Exception e) {
e.printStackTrace();
}
if (array == null) array = new SparseArray<>();
states.add(i, array);
}
}
private void fillIfNeed(int position) {
while (views.size() <= position) {
views.add(null);
}
while (states.size() <= position) {
states.add(null);
}
}
private String getName(int position) {
Path screen = getItem(position);
return String.format("%s_%d", screen.getClass().getName(), position);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view.equals(object);
}
}
@Zhuinden
Copy link

You should set the class loader on the bundle, otherwise you risk getting BadParcelException

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment