Reputation: 31
I have used the advices from
How to prevent custom views from losing state across screen orientation changes but even when my View
saves it's state properly, onRestoreInstanceState
is never called. Activity's restoring method is called to make things stranger.
import java.text.DecimalFormat;
import java.text.NumberFormat;
import com.szyk.myheart.R;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Scroller;
public class NumberScroller extends View implements OnTouchListener{
private final float VIEW_FILL_PERCENTAGE = 80;
private final int MIN_VELOCITY_Y = 100;
private final int VELOCITY_UNIT = 1000;
private final String TAG = "NumberScroller";
private final int ALIGNING_DURATION = 1000;
private boolean isCustomizing = true;
private boolean isDragged = false;
private boolean isNewVelocityTracker = false;
private Scroller scroller;
private VelocityTracker velocityTracker;
private float lastY;
private int absoleteY;
private float velocityY;
private float ascent;
private Integer maxScrollerNumber;
private Integer minScrollerNumber;
private Paint paintNumber;
private Paint paintNumberActivated;
private Paint paintBorder;
private float textOffsetX;
private Drawable foregroundBorder;
private Drawable foregroundAlpha;
private NumberFormat numberFormatter;
/**
* Initializes attributes and variables.
* @param attrs - AttributeSet for Number Scroller
* @param context in which scroller exists.
*/
public NumberScroller(Context context, AttributeSet attrs) {
super(context, attrs);
Log.i(TAG, "Creating NumberScroller.");
initAttrs(attrs, context);
scroller = new Scroller(getContext());
setOnTouchListener(this);
foregroundAlpha = getResources().getDrawable(R.drawable.foreground_alpha);
numberFormatter = new DecimalFormat();
numberFormatter.setMinimumIntegerDigits(maxScrollerNumber.toString()
.length());
numberFormatter.setMinimumFractionDigits(0);
setSaveEnabled(true);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
/**
* (non-Javadoc)
* @see android.view.View#onMeasure(int, int)
*/
/**
* Initializes attributes from xml description.
* @param attrs - AttributeSet for Number Scroller
* @param context in which scroller exists.
*/
private void initAttrs(AttributeSet attrs, Context context) {
TypedArray typedArray = context.obtainStyledAttributes(attrs,
R.styleable.NumberScroller);
maxScrollerNumber = typedArray.getInteger(
R.styleable.NumberScroller_maximum, 99);
minScrollerNumber = typedArray.getInteger(
R.styleable.NumberScroller_minimum, 0);
if (maxScrollerNumber < minScrollerNumber) {
int tmp = minScrollerNumber;
minScrollerNumber = maxScrollerNumber;
maxScrollerNumber = tmp;
}
typedArray.recycle();
}
V1:
@Override
public Parcelable onSaveInstanceState() {
Log.i(TAG,"SAve");
//begin boilerplate code that allows parent classes to save state
Parcelable superState = super.onSaveInstanceState();
SavedState ss = new SavedState(superState);
//end
ss.stateToSave = absoleteY;
return ss;
}
@Override
public void onRestoreInstanceState(Parcelable state) {
Log.i(TAG,"REstore");
//begin boilerplate code so parent classes can restore state
if(!(state instanceof SavedState)) {
super.onRestoreInstanceState(state);
return;
}
SavedState ss = (SavedState)state;
super.onRestoreInstanceState(ss.getSuperState());
//end
absoleteY = ss.stateToSave;
}
public static class SavedState extends BaseSavedState {
int stateToSave;
SavedState(Parcelable superState) {
super(superState);
}
private SavedState(Parcel in) {
super(in);
this.stateToSave = in.readInt();
}
@Override
public void writeToParcel(Parcel out, int flags) {
super.writeToParcel(out, flags);
out.writeInt(this.stateToSave);
}
//required field that makes Parcelables from a Parcel
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
V2:
@Override
protected Parcelable onSaveInstanceState() {
Log.i(TAG, "Saving state.");
Bundle bundle = new Bundle();
bundle.putParcelable("state", super.onSaveInstanceState());
bundle.putInt("absoleteY", absoleteY);
return bundle;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
Log.i(TAG, "Restoring state");
if(state instanceof Bundle){
Bundle bundle = (Bundle) state;
absoleteY = bundle.getInt("absoleteY");
super.onRestoreInstanceState(bundle.getParcelable("state"));
return;
}
super.onRestoreInstanceState(state);
}
In logs I never see "Restoring state".
It appears that if I am not using my custom view inside android.support.v4.view.ViewPager, then onRestoreInstanceState is called. Does anyone know the reason for that and do I have to call save/restore from within the activity?
Upvotes: 3
Views: 1820
Reputation: 2202
This question is very old but I stumbled upon it while Googling a solution, then after I figured it out.
The problem may be that the custom views are created programatically inside the root Activity's onCreate method.
The solution is to call to onSaveInstanceState and onRestoreInstanceState from the root Activity containing the ViewPager and store the custom view's state programatically as well.
Inside your root Activity implement the following:
Save the state of your custom view
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelable("STATE_COLLECTION", collectionFrameLayout.onSaveInstanceState());
super.onSaveInstanceState(outState);
}
And inside the onCreate() restore it after you create your custom views.
if (savedInstanceState != null) {
Parcelable state = savedInstanceState.getParcelable("STATE_COLLECTION");
if (state != null) {
collectionFrameLayout.onRestoreInstanceState(state);
}
}
Upvotes: 1