All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.simonvt.threepanelayout.ThreePaneLayout Maven / Gradle / Ivy

There is a newer version: 1.0.1
Show newest version
package net.simonvt.threepanelayout;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.animation.AccelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.FrameLayout;

public class ThreePaneLayout extends ViewGroup {

    static final boolean USE_TRANSLATIONS = Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;

    private static final boolean DEBUG = false;

    private static final int DURATION_MAX = DEBUG ? 10000 : 800;

    private static final int INDICATOR_ANIM_DURATION = 600;

    public static final int PANE_LEFT = 1;

    public static final int PANE_MIDDLE = 2;

    public static final int PANE_RIGHT = 4;

    private static final int DEFAULT_DROP_SHADOW_WIDTH_DP = 6;

    /**
     * State when the layout is not animating and the left pane is visible.
     */
    public static final int STATE_LEFT_VISIBLE = 0;

    /**
     * State when the layout is animating to the right pane.
     */
    public static final int STATE_ANIMATE_RIGHT = 1;

    /**
     * State when the layout is animating to the left pane.
     */
    public static final int STATE_ANIMATE_LEFT = 2;

    /**
     * State when the layout is not animating and the right pane is visible.
     */
    public static final int STATE_RIGHT_VISIBLE = 4;

    private static final Interpolator SMOOTH_INTERPOLATOR = new SmoothInterpolator();

    private static final Interpolator INDICATOR_INTERPOLATOR = new AccelerateInterpolator();

    private FrameLayout mLeftPane;

    private FrameLayout mMiddlePane;

    private FrameLayout mRightPane;

    private float mOffset;

    private boolean mLayerTypeHardware;

    private FloatScroller mScroller;

    private final Runnable mDragRunnable = new Runnable() {
        @Override
        public void run() {
            postAnimationInvalidate();
        }
    };

    private Drawable mShadow;

    private int mDropShadowWidth;

    private boolean mMiddlePaneCollapsible;

    private int mLeftPaneWidth;

    private int mMiddlePaneCollapsedWidth;

    private int mMiddlePaneExpandedWidth;

    private int mVisiblePanes = PANE_LEFT | PANE_MIDDLE;

    private OnPaneStateChangeListener mPaneStateChangeListener;

    private int mPageState = STATE_LEFT_VISIBLE;

    private View mLeftActiveView;

    private Bitmap mLeftActiveIndicator;

    private final Rect mLeftActiveRect = new Rect();

    private int mLeftActivePosition;

    private int mLeftIndicatorStartPos;

    private int mLeftIndicatorTop;

    private float mLeftIndicatorOffset;

    private final FloatScroller mLeftIndicatorScroller = new FloatScroller(SMOOTH_INTERPOLATOR);

    private final Runnable mLeftIndicatorRunnable = new Runnable() {
        @Override
        public void run() {
            animateLeftIndicatorInvalidate();
        }
    };

    private boolean mLeftIndicatorAnimating;

    private View mMiddleActiveView;

    private Bitmap mMiddleActiveIndicator;

    private final Rect mMiddleActiveRect = new Rect();

    private int mMiddleActivePosition;

    private int mMiddleIndicatorStartPos;

    private int mMiddleIndicatorTop;

    private float mMiddleIndicatorOffset;

    private final FloatScroller mMiddleIndicatorScroller = new FloatScroller(SMOOTH_INTERPOLATOR);

    private final Runnable mMiddleIndicatorRunnable = new Runnable() {
        @Override
        public void run() {
            animateMiddleIndicatorInvalidate();
        }
    };

    private boolean mMiddleIndicatorAnimating;

    private ViewTreeObserver.OnScrollChangedListener mScrollChangedListener
            = new ViewTreeObserver.OnScrollChangedListener() {
        @Override
        public void onScrollChanged() {
            if (mLeftActiveView != null || mMiddleActiveView != null) {
                invalidate();
            }
        }
    };

    public interface OnPaneStateChangeListener {

        void onPaneStateChange(int oldState, int newState);
    }

    public ThreePaneLayout(Context context) {
        this(context, null);
    }

    public ThreePaneLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ThreePaneLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);

        mScroller = new FloatScroller(SMOOTH_INTERPOLATOR);

        mLeftPane = new BuildLayerFrameLayout(context);
        addView(mLeftPane, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        mMiddlePane = new BuildLayerFrameLayout(context);
        addView(mMiddlePane, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        mRightPane = new BuildLayerFrameLayout(context);
        addView(mRightPane, LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ThreePaneLayout, R.attr.threePaneLayoutStyle,
                defStyle);

        final int leftPaneLayout = a.getResourceId(R.styleable.ThreePaneLayout_leftPaneLayout, -1);
        if (leftPaneLayout != -1) {
            setLeftPaneLayout(leftPaneLayout);
        }
        final int middlePaneLayout = a.getResourceId(R.styleable.ThreePaneLayout_middlePaneLayout, -1);
        if (middlePaneLayout != -1) {
            setMiddlePaneLayout(middlePaneLayout);
        }
        final int rightPaneLayout = a.getResourceId(R.styleable.ThreePaneLayout_rightPaneLayout, -1);
        if (rightPaneLayout != -1) {
            setRightPaneLayout(rightPaneLayout);
        }

        mLeftPaneWidth = a.getDimensionPixelSize(R.styleable.ThreePaneLayout_leftPaneWidth, dpToPx(250));

        mMiddlePaneCollapsible = a.getBoolean(R.styleable.ThreePaneLayout_middlePaneCollapsible, true);

        mMiddlePaneCollapsedWidth = a.getDimensionPixelSize(R.styleable.ThreePaneLayout_middlePaneCollapsedWidth,
                dpToPx(450));

        final int leftIndicatorResId = a.getResourceId(R.styleable.ThreePaneLayout_leftActiveIndicator, 0);
        if (leftIndicatorResId != 0) {
            mLeftActiveIndicator = BitmapFactory.decodeResource(getResources(), leftIndicatorResId);
        }

        final int middleIndicatorResId = a.getResourceId(R.styleable.ThreePaneLayout_middleActiveIndicator, 0);
        if (middleIndicatorResId != 0) {
            mMiddleActiveIndicator = BitmapFactory.decodeResource(getResources(), middleIndicatorResId);
        }

        a.recycle();

        mShadow = new GradientDrawable(GradientDrawable.Orientation.RIGHT_LEFT, new int[] {
                0xFF000000,
                0x00000000,
        });
        mDropShadowWidth = (int) (getResources().getDisplayMetrics().density * DEFAULT_DROP_SHADOW_WIDTH_DP + 0.5f);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        getViewTreeObserver().addOnScrollChangedListener(mScrollChangedListener);
    }

    @Override
    protected void onDetachedFromWindow() {
        getViewTreeObserver().removeOnScrollChangedListener(mScrollChangedListener);
        super.onDetachedFromWindow();
    }

    private int dpToPx(int dp) {
        return (int) (getResources().getDisplayMetrics().density * dp + 0.5f);
    }

    public void setLeftPaneLayout(int layoutId) {
        mLeftPane.removeAllViews();
        LayoutInflater.from(getContext()).inflate(layoutId, mLeftPane);
    }

    public void setMiddlePaneLayout(int layoutId) {
        mMiddlePane.removeAllViews();
        LayoutInflater.from(getContext()).inflate(layoutId, mMiddlePane);
    }

    public void setRightPaneLayout(int layoutId) {
        mRightPane.removeAllViews();
        LayoutInflater.from(getContext()).inflate(layoutId, mRightPane);
    }

    public void showLeftPane() {
        showLeftPane(true);
    }

    public void showLeftPane(boolean animate) {
        mVisiblePanes = PANE_LEFT | PANE_MIDDLE;
        requestLayout();
        animateOffsetTo(0.0f, animate);
        if (animate) setPageState(STATE_ANIMATE_LEFT);
    }

    public void showRightPane() {
        showRightPane(true);
    }

    public void showRightPane(boolean animate) {
        mVisiblePanes = PANE_RIGHT;
        if (mMiddlePaneCollapsible) mVisiblePanes |= PANE_MIDDLE;
        requestLayout();
        animateOffsetTo(1.0f, animate);
        if (animate) setPageState(STATE_ANIMATE_RIGHT);
    }

    public boolean isLeftPaneVisible() {
        return (mVisiblePanes & PANE_LEFT) != 0;
    }

    public boolean isMiddlePaneShowing() {
        return (mVisiblePanes & PANE_MIDDLE) != 0;
    }

    public boolean isRightPaneVisible() {
        return (mVisiblePanes & PANE_RIGHT) != 0;
    }

    public boolean isMiddlePaneCollapsible() {
        return mMiddlePaneCollapsible;
    }

    public void setLeftActiveView(View v) {
        setLeftActiveView(v, 0);
    }

    public void setLeftActiveView(View v, int position) {
        setLeftActiveView(v, position, true);
    }

    public void setLeftActiveView(View v, int position, boolean animate) {
        final View oldView = mLeftActiveView;
        mLeftActiveView = v;
        mLeftActivePosition = position;

        if (oldView != null && animate) {
            startAnimatingLeftIndicator();
        } else {
            mLeftIndicatorOffset = 1.0f;
        }

        invalidate();
    }

    private void startAnimatingLeftIndicator() {
        mLeftIndicatorStartPos = mLeftIndicatorTop;
        mLeftIndicatorAnimating = true;
        mLeftIndicatorScroller.startScroll(0.0f, 1.0f, INDICATOR_ANIM_DURATION);

        animateLeftIndicatorInvalidate();
    }

    /**
     * Callback when each frame in the indicator animation should be drawn.
     */
    private void animateLeftIndicatorInvalidate() {
        if (mLeftIndicatorScroller.computeScrollOffset()) {
            mLeftIndicatorOffset = mLeftIndicatorScroller.getCurr();
            invalidate();

            if (!mLeftIndicatorScroller.isFinished()) {
                postOnAnimation(mLeftIndicatorRunnable);
                return;
            }
        }

        completeAnimatingLeftIndicator();
    }

    /**
     * Called when the indicator animation has completed.
     */
    private void completeAnimatingLeftIndicator() {
        mLeftIndicatorOffset = 1.0f;
        mLeftIndicatorAnimating = false;
        invalidate();
    }

    public void setMiddleActiveView(View v) {
        setMiddleActiveView(v, 0);
    }

    public void setMiddleActiveView(View v, int position) {
        setMiddleActiveView(v, position, true);
    }

    public void setMiddleActiveView(View v, int position, boolean animate) {
        final View oldView = mMiddleActiveView;
        mMiddleActiveView = v;
        mMiddleActivePosition = position;

        if (oldView != null && animate) {
            startAnimatingMiddleIndicator();
        } else {
            mMiddleIndicatorOffset = 1.0f;
        }

        invalidate();
    }

    private void startAnimatingMiddleIndicator() {
        mMiddleIndicatorStartPos = mMiddleIndicatorTop;
        mMiddleIndicatorAnimating = true;
        mMiddleIndicatorScroller.startScroll(0.0f, 1.0f, INDICATOR_ANIM_DURATION);

        animateMiddleIndicatorInvalidate();
    }

    /**
     * Callback when each frame in the indicator animation should be drawn.
     */
    private void animateMiddleIndicatorInvalidate() {
        if (mMiddleIndicatorScroller.computeScrollOffset()) {
            mMiddleIndicatorOffset = mMiddleIndicatorScroller.getCurr();
            invalidate();

            if (!mMiddleIndicatorScroller.isFinished()) {
                postOnAnimation(mMiddleIndicatorRunnable);
                return;
            }
        }

        completeAnimatingMiddleIndicator();
    }

    /**
     * Called when the indicator animation has completed.
     */
    private void completeAnimatingMiddleIndicator() {
        mMiddleIndicatorOffset = 1.0f;
        mMiddleIndicatorAnimating = false;
        invalidate();
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        final int height = getHeight();
        final int dropShadowWidth = mDropShadowWidth;

        final int middlePaneLeft = (int) (mMiddlePane.getLeft() + Math.floor(mMiddlePane.getTranslationX()));
        mShadow.setBounds(middlePaneLeft - dropShadowWidth, 0, middlePaneLeft, height);
        mShadow.draw(canvas);

        final int rightPaneLeft = (int) (mRightPane.getLeft() + Math.floor(mRightPane.getTranslationX()));
        final int scaledDropShadowWidth = (int) (dropShadowWidth * SMOOTH_INTERPOLATOR.getInterpolation(mOffset));
        mShadow.setBounds(rightPaneLeft - scaledDropShadowWidth, 0, rightPaneLeft, height);
        mShadow.draw(canvas);

        drawLeftIndicator(canvas);
        drawMiddleIndicator(canvas);
    }

    private void drawLeftIndicator(Canvas canvas) {
        if (mLeftActiveView != null && isViewDescendant(mLeftActiveView)) {
            Integer position = (Integer) mLeftActiveView.getTag(R.id.tplActiveViewPosition);
            final int pos = position == null ? 0 : position;

            if (pos == mLeftActivePosition) {

                mLeftActiveView.getDrawingRect(mLeftActiveRect);
                offsetDescendantRectToMyCoords(mLeftActiveView, mLeftActiveRect);

                if (mLeftIndicatorAnimating) {
                    final int indicatorFinalTop = mLeftActiveRect.top + ((mLeftActiveRect.height()
                            - mLeftActiveIndicator.getHeight()) / 2);
                    final int indicatorStartTop = mLeftIndicatorStartPos;
                    final int diff = indicatorFinalTop - indicatorStartTop;
                    final int startOffset = (int) (diff * mLeftIndicatorOffset);
                    mLeftIndicatorTop = indicatorStartTop + startOffset;
                } else {
                    mLeftIndicatorTop = mLeftActiveRect.top + ((mLeftActiveRect.height()
                            - mLeftActiveIndicator.getHeight()) / 2);
                }
                final int right = (int) (mMiddlePane.getLeft() + Math.floor(mMiddlePane.getTranslationX()));
                final int left = right - mLeftActiveIndicator.getWidth();

                canvas.save();
                canvas.clipRect(left, 0, right, getHeight());
                canvas.drawBitmap(mLeftActiveIndicator, left, mLeftIndicatorTop, null);
                canvas.restore();
            }
        }
    }

    private void drawMiddleIndicator(Canvas canvas) {
        if (mMiddleActiveView != null && isViewDescendant(mMiddleActiveView)) {
            Integer position = (Integer) mMiddleActiveView.getTag(R.id.tplActiveViewPosition);
            final int pos = position == null ? 0 : position;

            if (pos == mMiddleActivePosition) {

                mMiddleActiveView.getDrawingRect(mMiddleActiveRect);
                offsetDescendantRectToMyCoords(mMiddleActiveView, mMiddleActiveRect);

                final float interpolatedRatio = 1.f - INDICATOR_INTERPOLATOR.getInterpolation(1.0f - mOffset);
                final int interpolatedWidth = (int) (mMiddleActiveIndicator.getWidth() * interpolatedRatio);

                if (mMiddleIndicatorAnimating) {
                    final int indicatorFinalTop = mMiddleActiveRect.top + ((mMiddleActiveRect.height()
                            - mMiddleActiveIndicator.getHeight()) / 2);
                    final int indicatorStartTop = mMiddleIndicatorStartPos;
                    final int diff = indicatorFinalTop - indicatorStartTop;
                    final int startOffset = (int) (diff * mMiddleIndicatorOffset);
                    mMiddleIndicatorTop = indicatorStartTop + startOffset;
                } else {
                    mMiddleIndicatorTop = mMiddleActiveRect.top + ((mMiddleActiveRect.height()
                            - mMiddleActiveIndicator.getHeight()) / 2);
                }
                final int right = (int) (mRightPane.getLeft() + mRightPane.getTranslationX());
                final int left = right - interpolatedWidth;

                canvas.save();
                canvas.clipRect(left, 0, right, getHeight());
                canvas.drawBitmap(mMiddleActiveIndicator, left, mMiddleIndicatorTop, null);
                canvas.restore();
            }
        }
    }

    protected boolean isViewDescendant(View v) {
        ViewParent parent = v.getParent();
        while (parent != null) {
            if (parent == this) {
                return true;
            }

            parent = parent.getParent();
        }

        return false;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int width = r - l;
        final int height = b - t;
        final float offset = mOffset;

        // This is easy. Only support 3.2+, so all moving or views are done with translations
        final int leftPaneWidth = mLeftPaneWidth;
        mLeftPane.layout(0, 0, leftPaneWidth, height);

        final int middlePaneWidth = mMiddlePane.getMeasuredWidth();
        mMiddlePane.layout(leftPaneWidth, 0, leftPaneWidth + middlePaneWidth, height);

        final int rightPaneWidth = mRightPane.getMeasuredWidth();
        mRightPane.layout(width, 0, width + rightPaneWidth, height);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        final int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthMode != MeasureSpec.EXACTLY || heightMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("Must measure with an exact size");
        }

        final int width = MeasureSpec.getSize(widthMeasureSpec);
        final int height = MeasureSpec.getSize(heightMeasureSpec);

        setMeasuredDimension(width, height);

        // Measure left pane
        final int leftPaneWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, mLeftPaneWidth);
        final int leftPaneHeightMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, height);
        mLeftPane.measure(leftPaneWidthMeasureSpec, leftPaneHeightMeasureSpec);

        // Measure middle pane
        final int middlePaneHeightMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, height);
        int middlePaneWidthMeasureSpec;

        mMiddlePaneExpandedWidth = width - mLeftPaneWidth;

        if (isRightPaneVisible() && mMiddlePaneCollapsible) {
            middlePaneWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, mMiddlePaneCollapsedWidth);
        } else {
            middlePaneWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, mMiddlePaneExpandedWidth);
        }

        mMiddlePane.measure(middlePaneWidthMeasureSpec, middlePaneHeightMeasureSpec);

        // Measure right pane
        int rightWidthMeasureSpec;
        final int rightHeightMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, height);

        if (mMiddlePaneCollapsible) {
            rightWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, width - mMiddlePaneCollapsedWidth);
        } else {
            rightWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, width);
        }

        final int rightWidth = MeasureSpec.getSize(rightWidthMeasureSpec);

        mRightPane.measure(rightWidthMeasureSpec, rightHeightMeasureSpec);

        // Just making sure it updates the translations
        setOffset(mOffset);
    }

    private void setOffset(float offset) {
        mOffset = offset;

        invalidate();

        final int width = getWidth();
        if (mMiddlePaneCollapsible) {
            final int middlePaneOffset = (int) (-mLeftPaneWidth * offset);
            mLeftPane.setTranslationX(middlePaneOffset);
            mMiddlePane.setTranslationX(middlePaneOffset);
            final int rightPaneTranslation = (int) (-(width - mMiddlePaneCollapsedWidth) * offset);
            mRightPane.setTranslationX(rightPaneTranslation);
        } else {
            final int viewOffset = (int) (-width * offset);
            mLeftPane.setTranslationX(viewOffset);
            mMiddlePane.setTranslationX(viewOffset);
            mRightPane.setTranslationX(viewOffset);
        }
    }

    public void setPaneStateChangeListener(OnPaneStateChangeListener paneStateChangeListener) {
        mPaneStateChangeListener = paneStateChangeListener;
    }

    private void setPageState(int state) {
        if (state != mPageState) {
            if (mPaneStateChangeListener != null) mPaneStateChangeListener.onPaneStateChange(mPageState, state);
            mPageState = state;
        }
    }

    /**
     * If possible, set the layer type to {@link View#LAYER_TYPE_HARDWARE}.
     */
    protected void startLayerTranslation() {
        if (USE_TRANSLATIONS && !mLayerTypeHardware) {
            mLayerTypeHardware = true;
            mLeftPane.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mMiddlePane.setLayerType(View.LAYER_TYPE_HARDWARE, null);
            mRightPane.setLayerType(View.LAYER_TYPE_HARDWARE, null);
        }
    }

    /**
     * If the current layer type is {@link View#LAYER_TYPE_HARDWARE}, this will set it to @link View#LAYER_TYPE_NONE}.
     */
    private void stopLayerTranslation() {
        if (mLayerTypeHardware) {
            mLayerTypeHardware = false;
            mLeftPane.setLayerType(View.LAYER_TYPE_NONE, null);
            mMiddlePane.setLayerType(View.LAYER_TYPE_NONE, null);
            mRightPane.setLayerType(View.LAYER_TYPE_NONE, null);
        }
    }

    protected void stopAnimation() {
        removeCallbacks(mDragRunnable);
        mScroller.abortAnimation();
        stopLayerTranslation();
    }

    private void completeAnimation() {
        mScroller.abortAnimation();
        final float finalVal = mScroller.getFinal();
        setOffset(finalVal);
        setPageState(isLeftPaneVisible() ? STATE_LEFT_VISIBLE : STATE_RIGHT_VISIBLE);
        stopLayerTranslation();
    }

    protected void animateOffsetTo(float finalOffset, boolean animate) {
        if (!animate) {
            setOffset(finalOffset);
            return;
        }

        final float start = mOffset;
        final float dx = finalOffset - start;

        int duration = (int) (DURATION_MAX * Math.abs(dx));
        mScroller.startScroll(start, dx, duration);

        startLayerTranslation();
        postAnimationInvalidate();
    }

    /**
     * Callback when each frame in the drawer animation should be drawn.
     */
    private void postAnimationInvalidate() {
        if (mScroller.computeScrollOffset()) {
            final float curr = mScroller.getCurr();

            setOffset(curr);
            if (!mScroller.isFinished()) {
                postOnAnimation(mDragRunnable);
                return;
            }
        }

        completeAnimation();
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState) state;
        super.onRestoreInstanceState(savedState.getSuperState());

        if (savedState.mRightPaneVisible) showRightPane(false);
    }

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

        state.mRightPaneVisible = isRightPaneVisible();

        return state;
    }

    static class SavedState extends BaseSavedState {

        boolean mRightPaneVisible;

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

        public SavedState(Parcel in) {
            super(in);
            mRightPaneVisible = in.readInt() == 1;
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeInt(mRightPaneVisible ? 1 : 0);
        }

        @SuppressWarnings("UnusedDeclaration")
        public static final Creator CREATOR = new Creator() {
            @Override
            public SavedState createFromParcel(Parcel in) {
                return new SavedState(in);
            }

            @Override
            public SavedState[] newArray(int size) {
                return new SavedState[size];
            }
        };
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy