package com.likebamboo.osa.android.ui.view.fab; import android.content.Context; import android.content.res.TypedArray; import android.support.annotation.NonNull; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.AccelerateDecelerateInterpolator; import android.widget.LinearLayout; import com.likebamboo.osa.android.R; import com.likebamboo.osa.android.ui.view.ObservedWebView; import butterknife.ButterKnife; import butterknife.InjectView; import io.codetail.animation.SupportAnimator; import io.codetail.animation.ViewAnimationUtils; import io.codetail.widget.RevealFrameLayout; /** * fab 对应的工具栏 */ public class FabToolbar extends RevealFrameLayout { /** * 内容区 */ @InjectView(R.id.container) LinearLayout mContainer = null; @InjectView(R.id.fabbutton) FloatingActionButton mFAB = null; /** * 屏幕宽度 */ private float mScreenWidth = 0; /** * 动画执行时间 */ private int mDuration = 500; /** * 是否处于动画执行状态 */ private boolean isAniming = false; public FabToolbar(Context context) { this(context, null); } public FabToolbar(Context context, AttributeSet attrs) { this(context, attrs, 0); } public FabToolbar(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); if (attrs != null) { loadAttributes(attrs); } } /** * 初始化 */ private void init() { mScreenWidth = getResources().getDisplayMetrics().widthPixels; View v = inflate(getContext(), R.layout.fab_tool_bar, this); ButterKnife.inject(this, v); mContainer.setVisibility(View.GONE); mFAB.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { // 正执行动画 if (isAniming) { return; } // 如果是在展示状态 if (mContainer.getVisibility() == View.VISIBLE) { hideMenu(); return; } showMenu(); } }); } /** * 加载布局属性 * * @param attrs */ private void loadAttributes(AttributeSet attrs) { TypedArray a = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.FabToolbar, 0, 0); try { mContainer.setBackgroundColor(a.getColor(R.styleable.FabToolbar_tb_color, getResources().getColor(R.color.bg_drawer))); mDuration = a.getInteger(R.styleable.FabToolbar_tb_anim_duration, 500); } finally { a.recycle(); } } /** * @param startRadius * @param endRadius * @param listener */ private void animateCircle(float startRadius, float endRadius, SupportAnimator.AnimatorListener listener) { int cX = (mFAB.getLeft() + mFAB.getRight()) / 2; int cY = (mFAB.getTop() + mFAB.getBottom()) / 2; SupportAnimator animator = ViewAnimationUtils.createCircularReveal(mContainer, cX, cY, startRadius, endRadius); animator.setInterpolator(new AccelerateDecelerateInterpolator()); animator.setDuration(mDuration); if (listener != null) { animator.addListener(listener); } animator.start(); } @Override public void addView(@NonNull View child) { if (canAddViewToContainer(child)) { mContainer.addView(child); } else { super.addView(child); } } @Override public void addView(@NonNull View child, int width, int height) { if (canAddViewToContainer(child)) { mContainer.addView(child, width, height); } else { super.addView(child, width, height); } } @Override public void addView(@NonNull View child, ViewGroup.LayoutParams params) { if (canAddViewToContainer(child)) { mContainer.addView(child, params); } else { super.addView(child, params); } } @Override public void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) { if (canAddViewToContainer(child)) { mContainer.addView(child, index, params); } else { super.addView(child, index, params); } } /** * 判断View是否可以添加 * * @param child * @return */ private boolean canAddViewToContainer(View child) { return mContainer != null && !(child instanceof FloatingActionButton); } private class ToolbarCollapseListener implements SupportAnimator.AnimatorListener { private boolean show = false; public ToolbarCollapseListener(boolean show) { this.show = show; } @Override public void onAnimationEnd() { if (show) { mContainer.setVisibility(VISIBLE); } else { mContainer.setVisibility(GONE); } isAniming = false; } @Override public void onAnimationStart() { isAniming = true; } @Override public void onAnimationCancel() { } @Override public void onAnimationRepeat() { } } //==========api method================== /** * 显示toolbar */ public void showMenu() { mContainer.setVisibility(VISIBLE); animateCircle(0, mScreenWidth, new ToolbarCollapseListener(true)); } /** * 隐藏toolbar */ public void hideMenu() { animateCircle(mScreenWidth, 0, new ToolbarCollapseListener(false)); } /** * 设置动画执行事件 * * @param duration */ public void setAnimationDuration(int duration) { mDuration = duration; } /** * 将fabtoolbar attach到webView上 * * @param webView */ public void attachTo(ObservedWebView webView) { webView.setOnScrollChangedCallback(new DirectionWebViweScrollListener()); } /** * 滚动监听 */ public class DirectionWebViweScrollListener implements ObservedWebView.OnScrollChangedCallback { private static final int DIRECTION_CHANGE_THRESHOLD = 8; private int mPrevTop; private boolean mUpdated; @Override public void onScroll(int l, int t) { if (isAniming) { return; } if (mContainer.getVisibility() == View.VISIBLE) { hideMenu(); return; } if (mFAB == null) { return; } boolean goingDown = t > mPrevTop; boolean changed = Math.abs(t - mPrevTop) > DIRECTION_CHANGE_THRESHOLD; if (changed && mUpdated) { if (goingDown) { mFAB.hide(); } else { mFAB.show(); } } mPrevTop = t; mUpdated = true; } } }