3

I had custom components extended ImageView. Methods onSaveInstanceState and onRestoreInstanceState works correctly, but unfortunately when I click to the view mIsSelectedState = false

How can I solve this problem?

public class CustomImageView extends ImageView {

private boolean mIsSelectedState;
...

public CustomImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr);
}

private void init(Context context, AttributeSet attrs, int defStyleAttr) {
    setSaveEnabled(true);

    TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.CustomImageView, defStyleAttr, 0);
    ...
    attributes.recycle();

    mPaintImage = new Paint(Paint.ANTI_ALIAS_FLAG);
    ...
}

@Override
public boolean dispatchTouchEvent(MotionEvent event) {
    if (!isClickable()) {
        mIsSelectedState = false;
        return super.onTouchEvent(event);
    }

    ...

    invalidate();
    return super.dispatchTouchEvent(event);
}

...

@Override
protected Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();
    SavedState savedState = new SavedState(superState);

    savedState.mSelected = mIsSelectedState;
    return savedState;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if(!(state instanceof SavedState)) {
        super.onRestoreInstanceState(state);
        return;
    }

    SavedState savedState = (SavedState)state;
    super.onRestoreInstanceState(savedState.getSuperState());
    setSelectedState(savedState.mSelected);
    setBorderColor(mBorderSelectedColor);
}

private void setSelectedState(boolean isSelected) {
    mIsSelectedState = isSelected;
}

...

private static class SavedState extends BaseSavedState {
    boolean mSelected;

    SavedState(Parcelable superState) {
        super(superState);
    }

    private SavedState(Parcel in) {
        super(in);
        mSelected = in.readByte() != 0;
    }

    @Override
    public void writeToParcel(Parcel out, int flags) {
        super.writeToParcel(out, flags);
        out.writeByte((byte) (mSelected ? 1 : 0));
    }

    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];
                }
            };
}
  • 1
    May be it gets inside if (!isClickable()) { mIsSelectedState = false; and that's why you get it false. Did you debugged it ? – Shadab Ansari Mar 17 '16 at 23:07
  • FYI: In my opinion, there's no need to create your own parcelable. it adds a mess load of cruft to your code in most cases. Just use the built in Bundle class, and set attributes on it. – Matt Mar 18 '16 at 05:36
  • @ShadabAnsari yes, I checked it. I also debig it more detail. Before onDraw() called onRestoreInstantState and set **mIsSelectedState** to correct value, but unfortunately during onDraw() I have incorrect data – ALex Zhukovich Mar 18 '16 at 10:43
  • @Matt Why do you think that **Bundle** is better? As example in View **super.onSaveInstanceState()** return Parcelabble object. When we are talking about as example Activity, I agree with you. – ALex Zhukovich Mar 18 '16 at 10:45
  • Mostly because you can't screw up the parcelling on a bundle. Custom parcelling always has that chance of being coded incorrectly. – Matt Mar 18 '16 at 20:07
  • in order to save the state of a custom view have a look at this [thread](http://stackoverflow.com/questions/3542333/how-to-prevent-custom-views-from-losing-state-across-screen-orientation-changes) – b00n12 Dec 20 '16 at 20:05

1 Answers1

-3

The correct way to do saveStates is the following:

First override onSaveInstanceState()

 @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.puBoolean("myconstantKey", mIsSelectedState);
    }

Then whenever it is restored you should be overriding:

 @Override
    public void onRestoreInstanceState(Bundle savedInstanceState) {
    // Always call the superclass so it can restore the view hierarchy
    super.onRestoreInstanceState(savedInstanceState);

    // Restore state members from saved instance
    mIsSelectedState = savedInstanceState.getInt("myconstantKey");
}

You can do it also on onCreate in case you are switching between Activities

@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
           mIsSelectedState = savedInstanceState.getBoolean("myconstantKey");
        }

        ...
    }

Remember Android Activity lifecycle is tricky but once you get the hang of it everything will be better :)

Hope it helps.

Joel
  • 838
  • 5
  • 12