Created
July 20, 2016 19:06
-
-
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You should set the class loader on the bundle, otherwise you risk getting
BadParcelException