我已经采纳了来自
How to prevent custom views from losing state across screen orientation changes但即使我的 View
正确保存了它的状态,也永远不会调用 onRestoreInstanceState
。调用 Activity 的恢复方法是为了让事情变得更奇怪。
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);
}
在日志中我从未看到“正在恢复状态”。
看来,如果我没有在 android.support.v4.view.ViewPager 中使用自定义 View ,则会调用 onRestoreInstanceState。有谁知道这样做的原因,我是否必须从 Activity 中调用保存/恢复?
最佳答案
这个问题很老了,但我在谷歌搜索解决方案时偶然发现了它,然后在我弄明白之后。
问题可能是自定义 View 是在根 Activity 的 onCreate 方法中以编程方式创建的。
解决方案是从包含 ViewPager 的根 Activity 调用 onSaveInstanceState 和 onRestoreInstanceState,并以编程方式存储自定义 View 的状态。
在您的根 Activity 中执行以下操作:
保存自定义 View 的状态
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putParcelable("STATE_COLLECTION", collectionFrameLayout.onSaveInstanceState());
super.onSaveInstanceState(outState);
}
并在创建自定义 View 后在 onCreate() 中恢复它。
if (savedInstanceState != null) {
Parcelable state = savedInstanceState.getParcelable("STATE_COLLECTION");
if (state != null) {
collectionFrameLayout.onRestoreInstanceState(state);
}
}
关于android - 自定义 View 的状态已保存,但从未恢复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10656490/