/* * Copyright (c) 2016 Zhang Hai <Dreaming.in.Code.ZH@Gmail.com> * All Rights Reserved. */ package me.zhanghai.android.douya.ui; import android.animation.Animator; import android.animation.ObjectAnimator; import android.content.Context; import android.os.Parcel; import android.os.Parcelable; import android.support.design.widget.FloatingActionButton; import android.support.v4.view.animation.FastOutLinearInInterpolator; import android.support.v4.view.animation.FastOutSlowInInterpolator; import android.util.AttributeSet; import android.view.ViewGroup; import butterknife.BindInt; import butterknife.ButterKnife; import me.zhanghai.android.douya.util.ViewUtils; public class FriendlyFloatingActionButton extends FloatingActionButton { @BindInt(android.R.integer.config_shortAnimTime) int mAnimationDuration; private boolean mShowing = true; private Animator mAnimator; public FriendlyFloatingActionButton(Context context) { super(context); init(); } public FriendlyFloatingActionButton(Context context, AttributeSet attrs) { super(context, attrs); init(); } public FriendlyFloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } private void init() { ButterKnife.bind(this); } @Override protected Parcelable onSaveInstanceState() { Parcelable superState = super.onSaveInstanceState(); SavedState savedState = new SavedState(superState); savedState.showing = mShowing; return savedState; } @Override protected void onRestoreInstanceState(Parcelable state) { SavedState savedState = (SavedState) state; super.onRestoreInstanceState(savedState.getSuperState()); if (!savedState.showing) { hideImmediately(); } } public void hide() { if (!mShowing) { return; } mShowing = false; cancelAnimator(); mAnimator = ObjectAnimator.ofFloat(this, TRANSLATION_Y, getTranslationY(), getHideTranslationY()) .setDuration(mAnimationDuration); mAnimator.setInterpolator(new FastOutLinearInInterpolator()); mAnimator.start(); } public void hideImmediately() { if (!mShowing) { return; } float hideTranslationY = getHideTranslationY(); if (hideTranslationY != 0) { mShowing = false; setTranslationY(hideTranslationY); } else { ViewUtils.postOnPreDraw(this, new Runnable() { @Override public void run() { hideImmediately(); } }); } } private int getHideTranslationY() { return ((ViewGroup) getParent()).getHeight() - getTop(); } public void show() { if (mShowing) { return; } mShowing = true; cancelAnimator(); mAnimator = ObjectAnimator.ofFloat(this, TRANSLATION_Y, getTranslationY(), 0) .setDuration(mAnimationDuration); mAnimator.setInterpolator(new FastOutSlowInInterpolator()); mAnimator.start(); } public void showImmediately() { if (mShowing) { return; } mShowing = true; setTranslationY(0); } private void cancelAnimator() { if (mAnimator != null) { mAnimator.cancel(); mAnimator = null; } } private static class SavedState extends BaseSavedState { public static final Parcelable.Creator<SavedState> CREATOR = new Parcelable.Creator<SavedState>() { @Override public SavedState createFromParcel(Parcel source) { return new SavedState(source); } @Override public SavedState[] newArray(int size) { return new SavedState[size]; } }; public boolean showing; public SavedState(Parcel in) { super(in); showing = in.readByte() != 0; } public SavedState(Parcelable superState) { super(superState); } @Override public void writeToParcel(Parcel dest, int flags) { super.writeToParcel(dest, flags); dest.writeByte(showing ? (byte) 1 : (byte) 0); } } }