diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java index 385c027a7..42b6f8e64 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/GalleryListScene.java @@ -29,7 +29,6 @@ import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.animation.Interpolator; -import android.widget.FrameLayout; import com.hippo.animation.SimpleAnimatorListener; import com.hippo.drawable.AddDeleteDrawable; @@ -42,15 +41,16 @@ import com.hippo.ehviewer.widget.SearchBar; import com.hippo.ehviewer.widget.SearchDatabase; import com.hippo.ehviewer.widget.SearchLayout; import com.hippo.scene.Scene; +import com.hippo.util.AssertUtils; import com.hippo.util.Log; import com.hippo.util.MathUtils; import com.hippo.util.ViewUtils; +import com.hippo.widget.FabLayout; import com.hippo.widget.FloatingActionButton; -import com.hippo.widget.FloatingActionButtonLayout; // TODO disable click action when animating public class GalleryListScene extends Scene implements SearchBar.Helper, - View.OnClickListener { + View.OnClickListener, FabLayout.OnCancelListener { private static final long ANIMATE_TIME = 300l; @@ -73,8 +73,10 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, private RecyclerView mContentRecyclerView; private SearchLayout mSearchLayout; private RecyclerView mSearchRecyclerView; - private FloatingActionButtonLayout mFabLayout; + private FabLayout mFabLayout; private FloatingActionButton mCornerFab; + private FloatingActionButton mRefreshFab; + private FloatingActionButton mGoToFab; private ViewTransition mViewTransition; @@ -104,8 +106,12 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, mContentRecyclerView = mContentLayout.getRecyclerView(); mSearchLayout = (SearchLayout) findViewById(R.id.search_layout); mSearchRecyclerView = mSearchLayout.getRecyclerView(); - mFabLayout = (FloatingActionButtonLayout) findViewById(R.id.fab_layout); + mFabLayout = (FabLayout) findViewById(R.id.fab_layout); mCornerFab = mFabLayout.getPrimaryFab(); + AssertUtils.assertEquals("FabLayout in GalleryListScene should contain " + + "two secondary fab.", mFabLayout.getSecondaryFabCount(), 2); + mRefreshFab = mFabLayout.getSecondaryFabAt(0); + mGoToFab = mFabLayout.getSecondaryFabAt(1); mViewTransition = new ViewTransition(mContentLayout, mSearchLayout); @@ -125,9 +131,14 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, } }); + mFabLayout.setOnCancelListener(this); + + mRefreshFab.setOnClickListener(this); + mGoToFab.setOnClickListener(this); + // Corner Fab mCornerFab.setOnClickListener(this); - mCornerFabOriginalBottom = mResources.getDimensionPixelOffset(R.dimen.corner_fab_padding_bottom); + mCornerFabOriginalBottom = mFabLayout.getPaddingBottom(); mAddDeleteDrawable = new AddDeleteDrawable(getStageActivity()); mAddDeleteDrawable.setColor(mResources.getColor(R.color.primary_drawable_dark)); mSearchDrawable = mResources.getDrawable(R.drawable.ic_search_dark); @@ -142,9 +153,9 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, // Search Layout mSearchLayout.setFitPaddingBottom(b); // Corner Fab - FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mFabLayout.getLayoutParams(); - lp.bottomMargin = b + mCornerFabOriginalBottom; - mFabLayout.setLayoutParams(lp); + mFabLayout.setPadding(mFabLayout.getPaddingLeft(), + mFabLayout.getPaddingTop(), mFabLayout.getPaddingRight(), + mCornerFabOriginalBottom + b); } private void setFabState(int fabState) { @@ -208,18 +219,33 @@ public class GalleryListScene extends Scene implements SearchBar.Helper, } } + private void toggleFabLayout() { + mFabLayout.toggle(); + mAddDeleteDrawable.setShape(mFabLayout.getExpanded(), ANIMATE_TIME); + } + @Override public void onClick(View v) { if (v == mCornerFab) { if (mFabState == FAB_STATE_NORMAL) { - mFabLayout.toggle(); - mAddDeleteDrawable.setShape(mFabLayout.getExpanded(), ANIMATE_TIME); + toggleFabLayout(); } else if (mFabState == FAB_STATE_SEARCH) { onApplySearch(mSearchBar.getText()); } + } else if (v == mRefreshFab) { + toggleFabLayout(); + // TODO do go to top and refresh + } else if (v == mGoToFab) { + toggleFabLayout(); + // TODO do go to } } + @Override + public void onCancel(FabLayout fabLayout) { + mAddDeleteDrawable.setAdd(ANIMATE_TIME); + } + @Override public void onClickTitle() { if (mState == STATE_NORMAL) { diff --git a/app/src/main/java/com/hippo/widget/FloatingActionButtonLayout.java b/app/src/main/java/com/hippo/widget/FabLayout.java similarity index 80% rename from app/src/main/java/com/hippo/widget/FloatingActionButtonLayout.java rename to app/src/main/java/com/hippo/widget/FabLayout.java index 8f69a33a8..cf0333794 100644 --- a/app/src/main/java/com/hippo/widget/FloatingActionButtonLayout.java +++ b/app/src/main/java/com/hippo/widget/FabLayout.java @@ -28,7 +28,7 @@ import android.view.ViewGroup; import com.hippo.animation.SimpleAnimatorListener; import com.hippo.ehviewer.R; -public class FloatingActionButtonLayout extends ViewGroup { +public class FabLayout extends ViewGroup implements View.OnClickListener { private static long ANIMATE_TIME = 300l; @@ -39,24 +39,28 @@ public class FloatingActionButtonLayout extends ViewGroup { private boolean mFirst = true; private boolean mExpanded = false; + private boolean mAutoCancel = true; private float mMainFabCenterY = -1f; - public FloatingActionButtonLayout(Context context) { + private OnCancelListener mOnCancelListener; + + public FabLayout(Context context) { super(context); init(context); } - public FloatingActionButtonLayout(Context context, AttributeSet attrs) { + public FabLayout(Context context, AttributeSet attrs) { super(context, attrs); init(context); } - public FloatingActionButtonLayout(Context context, AttributeSet attrs, int defStyleAttr) { + public FabLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { + setSoundEffectsEnabled(false); mInterval = context.getResources().getDimensionPixelOffset(R.dimen.floating_action_bar_layout_interval); } @@ -157,11 +161,11 @@ public class FloatingActionButtonLayout extends ViewGroup { @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int interval = mInterval; - int top = getPaddingTop(); - int paddingLeft = getPaddingLeft(); - int vaildWidth = getMeasuredWidth() - paddingLeft - getPaddingRight(); + int centerX = 0; + int bottom = getMeasuredHeight() - getPaddingBottom(); int count = getChildCount(); - for (int i = 0; i < count; i++) { + int i = count; + while(--i >= 0) { View child = getChildAt(i); if (child.getVisibility() == View.GONE) { continue; @@ -169,14 +173,38 @@ public class FloatingActionButtonLayout extends ViewGroup { int childWidth = child.getMeasuredWidth(); int childHeight = child.getMeasuredHeight(); - int left = paddingLeft + ((vaildWidth - childWidth) / 2); - child.layout(left, top, left + childWidth, top + childHeight); + int right; + if (i == count - 1) { + right = getMeasuredWidth() - getPaddingRight(); + } else { + right = centerX + (childWidth / 2); + } + child.layout(right - childWidth, bottom - childHeight, right, bottom); if (i == count - 1) { - mMainFabCenterY = top + (childHeight / 2f); + centerX = right - (childWidth / 2); + mMainFabCenterY = bottom - (childHeight / 2f); } - top += (childHeight + interval); + bottom -= (childHeight + interval); + } + } + + public void setOnCancelListener(OnCancelListener listener) { + mOnCancelListener = listener; + } + + public void setAutoCancel(boolean autoCancel) { + if (mAutoCancel != autoCancel) { + mAutoCancel = autoCancel; + + if (mExpanded) { + if (autoCancel) { + setOnClickListener(this); + } else { + setClickable(false); + } + } } } @@ -196,6 +224,14 @@ public class FloatingActionButtonLayout extends ViewGroup { if (mExpanded != expanded) { mExpanded = expanded; + if (mAutoCancel) { + if (expanded) { + setOnClickListener(this); + } else { + setClickable(false); + } + } + if (mMainFabCenterY == -1f) { // It is before first onLayout int count = getChildCount() - 1; @@ -264,4 +300,21 @@ public class FloatingActionButtonLayout extends ViewGroup { }); oa.start(); } + + @Override + public void onClick(View v) { + setExpanded(false); + if (mOnCancelListener != null) { + mOnCancelListener.onCancel(this); + } + } + + @Override + protected void dispatchSetPressed(boolean pressed) { + // Don't dispatch it to children + } + + public interface OnCancelListener { + void onCancel(FabLayout fabLayout); + } } diff --git a/app/src/main/res/layout/scene_gallery_list.xml b/app/src/main/res/layout/scene_gallery_list.xml index b55d7631d..dd135c3c7 100644 --- a/app/src/main/res/layout/scene_gallery_list.xml +++ b/app/src/main/res/layout/scene_gallery_list.xml @@ -41,14 +41,15 @@ android:layout_marginTop="@dimen/search_bar_padding_vertical" auto:forceNoElevation="true"/> - + android:gravity="right|bottom" + android:paddingRight="@dimen/corner_fab_padding_right" + android:paddingBottom="@dimen/corner_fab_padding_bottom" + tools:ignore="RtlHardcoded,RtlSymmetry"> - +