Add FloatingActionButtonLayout
This commit is contained in:
1 parent
5916e57bc8
commit
bab22977f2
13 files changed
+475
-33
No files matched your search
@@ -15,6 +15,7 @@
|
||||
|
||||
package com.hippo.drawable;
|
||||
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Canvas;
|
||||
@@ -24,6 +25,7 @@ import android.graphics.Path;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Build;
|
||||
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.util.MathUtils;
|
||||
@@ -127,6 +129,30 @@ public class AddDeleteDrawable extends Drawable {
|
||||
invalidateSelf();
|
||||
}
|
||||
|
||||
public void setAdd(long duration) {
|
||||
setShape(false, duration);
|
||||
}
|
||||
|
||||
public void setDelete(long duration) {
|
||||
setShape(true, duration);
|
||||
}
|
||||
|
||||
public void setShape(boolean delete, long duration) {
|
||||
if (!((!delete && mProgress == 0f) || (delete && mProgress == 1f))) {
|
||||
float endProgress = delete ? 1f : 0f;
|
||||
if (duration <= 0) {
|
||||
setProgress(endProgress);
|
||||
} else {
|
||||
ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", endProgress);
|
||||
oa.setDuration(duration);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
oa.setAutoCancel(true);
|
||||
}
|
||||
oa.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOpacity() {
|
||||
return PixelFormat.TRANSLUCENT;
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.hippo.util.Log;
|
||||
import com.hippo.util.MathUtils;
|
||||
import com.hippo.util.ViewUtils;
|
||||
import com.hippo.widget.FloatingActionButton;
|
||||
import com.hippo.widget.FloatingActionButtonLayout;
|
||||
|
||||
// TODO disable click action when animating
|
||||
public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
@@ -72,6 +73,7 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
private RecyclerView mContentRecyclerView;
|
||||
private SearchLayout mSearchLayout;
|
||||
private RecyclerView mSearchRecyclerView;
|
||||
private FloatingActionButtonLayout mFabLayout;
|
||||
private FloatingActionButton mCornerFab;
|
||||
|
||||
private ViewTransition mViewTransition;
|
||||
@@ -102,7 +104,8 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
mContentRecyclerView = mContentLayout.getRecyclerView();
|
||||
mSearchLayout = (SearchLayout) findViewById(R.id.search_layout);
|
||||
mSearchRecyclerView = mSearchLayout.getRecyclerView();
|
||||
mCornerFab = (FloatingActionButton) findViewById(R.id.fab);
|
||||
mFabLayout = (FloatingActionButtonLayout) findViewById(R.id.fab_layout);
|
||||
mCornerFab = mFabLayout.getPrimaryFab();
|
||||
|
||||
mViewTransition = new ViewTransition(mContentLayout, mSearchLayout);
|
||||
|
||||
@@ -139,9 +142,9 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
// Search Layout
|
||||
mSearchLayout.setFitPaddingBottom(b);
|
||||
// Corner Fab
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mCornerFab.getLayoutParams();
|
||||
FrameLayout.LayoutParams lp = (FrameLayout.LayoutParams) mFabLayout.getLayoutParams();
|
||||
lp.bottomMargin = b + mCornerFabOriginalBottom;
|
||||
mCornerFab.setLayoutParams(lp);
|
||||
mFabLayout.setLayoutParams(lp);
|
||||
}
|
||||
|
||||
private void setFabState(int fabState) {
|
||||
@@ -204,7 +207,8 @@ public class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
public void onClick(View v) {
|
||||
if (v == mCornerFab) {
|
||||
if (mFabState == FAB_STATE_NORMAL) {
|
||||
//
|
||||
mFabLayout.toggle();
|
||||
mAddDeleteDrawable.setShape(mFabLayout.getExpanded(), ANIMATE_TIME);
|
||||
} else if (mFabState == FAB_STATE_SEARCH) {
|
||||
onApplySearch(mSearchBar.getText());
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
TextView.OnEditorActionListener, TextWatcher,
|
||||
SearchEditText.SearchEditTextListener, Messenger.Receiver {
|
||||
|
||||
private static final long ANIMATION_TIME = 300;
|
||||
private static final long ANIMATE_TIME = 300l;
|
||||
|
||||
private Path mPath = new Path();
|
||||
private int mWidth;
|
||||
@@ -227,7 +227,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
// start animator
|
||||
if (mDrawerArrowDrawable.getProgress() != 1f) {
|
||||
ObjectAnimator oa1 = ObjectAnimator.ofFloat(mDrawerArrowDrawable, "progress", 0f, 1f);
|
||||
oa1.setDuration(ANIMATION_TIME);
|
||||
oa1.setDuration(ANIMATE_TIME);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
oa1.setAutoCancel(true);
|
||||
}
|
||||
@@ -235,7 +235,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
}
|
||||
if (mAddDeleteDrawable.getProgress() != 1f) {
|
||||
ObjectAnimator oa2 = ObjectAnimator.ofFloat(mAddDeleteDrawable, "progress", 0f, 1f);
|
||||
oa2.setDuration(ANIMATION_TIME);
|
||||
oa2.setDuration(ANIMATE_TIME);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
oa2.setAutoCancel(true);
|
||||
}
|
||||
@@ -257,7 +257,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
// start animator
|
||||
if (mDrawerArrowDrawable.getProgress() != 0f) {
|
||||
ObjectAnimator oa1 = ObjectAnimator.ofFloat(mDrawerArrowDrawable, "progress", 1f, 0f);
|
||||
oa1.setDuration(ANIMATION_TIME);
|
||||
oa1.setDuration(ANIMATE_TIME);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
oa1.setAutoCancel(true);
|
||||
}
|
||||
@@ -265,7 +265,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
}
|
||||
if (mAddDeleteDrawable.getProgress() != 0f) {
|
||||
ObjectAnimator oa2 = ObjectAnimator.ofFloat(mAddDeleteDrawable, "progress", 1f, 0f);
|
||||
oa2.setDuration(ANIMATION_TIME);
|
||||
oa2.setDuration(ANIMATE_TIME);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
oa2.setAutoCancel(true);
|
||||
}
|
||||
@@ -286,7 +286,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
// Show suggestions list
|
||||
if (mProgress != 1f) {
|
||||
ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", 0f, 1f);
|
||||
oa.setDuration(ANIMATION_TIME);
|
||||
oa.setDuration(ANIMATE_TIME);
|
||||
oa.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
@@ -313,7 +313,7 @@ public class SearchBar extends CardView implements View.OnClickListener,
|
||||
// Hide suggestions list
|
||||
if (mProgress != 0f) {
|
||||
ObjectAnimator oa = ObjectAnimator.ofFloat(this, "progress", 1f, 0f);
|
||||
oa.setDuration(ANIMATION_TIME);
|
||||
oa.setDuration(ANIMATE_TIME);
|
||||
oa.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
|
||||
@@ -37,36 +37,32 @@ public class FloatingActionButton extends View {
|
||||
|
||||
private GasketDrawer mGasketDrawer;
|
||||
private Drawable mDrawable;
|
||||
|
||||
private int mDrawableWidth;
|
||||
private Drawable.Callback mDrawableCallback;
|
||||
|
||||
public FloatingActionButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs, 0, 0);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs, defStyleAttr, 0);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
public FloatingActionButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
mDrawableWidth = UiUtils.dp2pix(context, 24);
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
mDrawableWidth = context.getResources().getDimensionPixelOffset(R.dimen.fab_drawable_size);
|
||||
mDrawableCallback = new DrawableCallback();
|
||||
|
||||
TypedArray a;
|
||||
|
||||
a = context.obtainStyledAttributes(attrs, R.styleable.FloatingActionButton, defStyleAttr, defStyleRes);
|
||||
a = context.obtainStyledAttributes(attrs, R.styleable.FloatingActionButton);
|
||||
int bgColor = a.getColor(R.styleable.FloatingActionButton_color, Color.BLACK);
|
||||
mDrawable = a.getDrawable(R.styleable.FloatingActionButton_drawable);
|
||||
setDrawable(a.getDrawable(R.styleable.FloatingActionButton_drawable));
|
||||
boolean forceNoElevation = a.getBoolean(R.styleable.FloatingActionButton_forceNoElevation, false);
|
||||
a.recycle();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !forceNoElevation) {
|
||||
mGasketDrawer = new GasketDrawerLollipop(this, bgColor);
|
||||
} else {
|
||||
mGasketDrawer = new GasketDrawerOld(this, bgColor);
|
||||
@@ -83,8 +79,7 @@ public class FloatingActionButton extends View {
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec),
|
||||
ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec));
|
||||
setMeasuredDimension(ViewUtils.getSuitableSize(getSuggestedMinimumWidth(), widthMeasureSpec), ViewUtils.getSuitableSize(getSuggestedMinimumHeight(), heightMeasureSpec));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -113,6 +108,13 @@ public class FloatingActionButton extends View {
|
||||
}
|
||||
|
||||
public void setDrawable(Drawable drawable) {
|
||||
if (mDrawable != null) {
|
||||
mDrawable.setCallback(null);
|
||||
}
|
||||
if (drawable != null) {
|
||||
drawable.setCallback(mDrawableCallback);
|
||||
}
|
||||
|
||||
mDrawable = drawable;
|
||||
invalidate();
|
||||
}
|
||||
@@ -125,6 +127,24 @@ public class FloatingActionButton extends View {
|
||||
void setColor(int color);
|
||||
}
|
||||
|
||||
private class DrawableCallback implements Drawable.Callback {
|
||||
@Override
|
||||
public void invalidateDrawable(Drawable who) {
|
||||
if (who == mDrawable) {
|
||||
invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void scheduleDrawable(Drawable who, Runnable what, long when) {
|
||||
// Empty
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unscheduleDrawable(Drawable who, Runnable what) {
|
||||
// Empty
|
||||
}
|
||||
}
|
||||
|
||||
static class GasketDrawerOld implements GasketDrawer {
|
||||
|
||||
@@ -163,6 +183,7 @@ public class FloatingActionButton extends View {
|
||||
ViewUtils.removeHardwareAccelerationSupport(mView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStateChange(int[] stateSet) {
|
||||
boolean enabled = false;
|
||||
boolean pressed = false;
|
||||
@@ -199,6 +220,7 @@ public class FloatingActionButton extends View {
|
||||
mView.invalidate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Canvas canvas) {
|
||||
mBounds.left = mGasketPadding;
|
||||
mBounds.top = mGasketPadding;
|
||||
@@ -207,6 +229,7 @@ public class FloatingActionButton extends View {
|
||||
canvas.drawOval(mBounds, mPaint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setColor(int color) {
|
||||
mColor = color;
|
||||
mDarkerColor = UiUtils.getDarkerColor(color);
|
||||
|
||||
@@ -0,0 +1,267 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.widget;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.PropertyValuesHolder;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.hippo.animation.SimpleAnimatorListener;
|
||||
import com.hippo.ehviewer.R;
|
||||
|
||||
public class FloatingActionButtonLayout extends ViewGroup {
|
||||
|
||||
private static long ANIMATE_TIME = 300l;
|
||||
|
||||
private static final String STATE_KEY_SUPER = "super";
|
||||
private static final String STATE_KEY_CHECKED = "expanded";
|
||||
|
||||
private int mInterval;
|
||||
|
||||
private boolean mFirst = true;
|
||||
private boolean mExpanded = false;
|
||||
private float mMainFabCenterY = -1f;
|
||||
|
||||
public FloatingActionButtonLayout(Context context) {
|
||||
super(context);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public FloatingActionButtonLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context);
|
||||
}
|
||||
|
||||
public FloatingActionButtonLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context);
|
||||
}
|
||||
|
||||
private void init(Context context) {
|
||||
mInterval = context.getResources().getDimensionPixelOffset(R.dimen.floating_action_bar_layout_interval);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addView(@NonNull View child, int index, ViewGroup.LayoutParams params) {
|
||||
if (!(child instanceof FloatingActionButton)) {
|
||||
throw new IllegalStateException("FloatingActionBarLayout should only " +
|
||||
"contain FloatingActionButton, but try to add "+ child.getClass().getName());
|
||||
}
|
||||
super.addView(child, index, params);
|
||||
}
|
||||
|
||||
public FloatingActionButton getPrimaryFab() {
|
||||
View v = getChildAt(getChildCount() - 1);
|
||||
if (v == null) {
|
||||
return null;
|
||||
} else {
|
||||
return (FloatingActionButton) v;
|
||||
}
|
||||
}
|
||||
|
||||
public int getSecondaryFabCount() {
|
||||
return Math.max(0, getChildCount() - 1);
|
||||
}
|
||||
|
||||
public FloatingActionButton getSecondaryFabAt(int index) {
|
||||
if (index < 0 || index >= getSecondaryFabCount()) {
|
||||
return null;
|
||||
}
|
||||
return (FloatingActionButton) getChildAt(index);
|
||||
}
|
||||
|
||||
private int getChildMeasureSpec(int parentMeasureSpec) {
|
||||
int parentMode = MeasureSpec.getMode(parentMeasureSpec);
|
||||
int parentSize = MeasureSpec.getSize(parentMeasureSpec);
|
||||
int childMode;
|
||||
int childSize;
|
||||
switch (parentMode) {
|
||||
default:
|
||||
case MeasureSpec.AT_MOST:
|
||||
case MeasureSpec.EXACTLY:
|
||||
childMode = MeasureSpec.AT_MOST;
|
||||
childSize = parentSize;
|
||||
break;
|
||||
case MeasureSpec.UNSPECIFIED:
|
||||
childMode = MeasureSpec.UNSPECIFIED;
|
||||
childSize = parentSize;
|
||||
}
|
||||
return MeasureSpec.makeMeasureSpec(childSize, childMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
if (mFirst) {
|
||||
mFirst = false;
|
||||
boolean expanded = mExpanded;
|
||||
int count = getChildCount() - 1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
getChildAt(i).setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec);
|
||||
int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec);
|
||||
measureChildren(childWidthMeasureSpec, childHeightMeasureSpec);
|
||||
|
||||
int maxWidth = 0;
|
||||
int maxHeight = 0;
|
||||
boolean firstChild = true;
|
||||
int count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child.getVisibility() == View.GONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
maxWidth = Math.max(maxWidth, child.getMeasuredWidth());
|
||||
maxHeight = maxHeight + child.getMeasuredHeight();
|
||||
if (firstChild) {
|
||||
firstChild = false;
|
||||
} else {
|
||||
maxHeight += mInterval;
|
||||
}
|
||||
}
|
||||
|
||||
// Account for padding too
|
||||
maxWidth += getPaddingLeft() + getPaddingRight();
|
||||
maxHeight += getPaddingTop() + getPaddingBottom();
|
||||
|
||||
// Check against minimum height and width
|
||||
maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight());
|
||||
maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
|
||||
|
||||
setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, 0),
|
||||
resolveSizeAndState(maxHeight, heightMeasureSpec, 0));
|
||||
}
|
||||
|
||||
@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 count = getChildCount();
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (child.getVisibility() == View.GONE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int childWidth = child.getMeasuredWidth();
|
||||
int childHeight = child.getMeasuredHeight();
|
||||
int left = paddingLeft + ((vaildWidth - childWidth) / 2);
|
||||
child.layout(left, top, left + childWidth, top + childHeight);
|
||||
|
||||
if (i == count - 1) {
|
||||
mMainFabCenterY = top + (childHeight / 2f);
|
||||
}
|
||||
|
||||
top += (childHeight + interval);
|
||||
}
|
||||
}
|
||||
|
||||
public void toggle() {
|
||||
setExpanded(!mExpanded);
|
||||
}
|
||||
|
||||
public boolean getExpanded() {
|
||||
return mExpanded;
|
||||
}
|
||||
|
||||
public void setExpanded(boolean expanded) {
|
||||
setExpanded(expanded, true);
|
||||
}
|
||||
|
||||
public void setExpanded(boolean expanded, boolean animation) {
|
||||
if (mExpanded != expanded) {
|
||||
mExpanded = expanded;
|
||||
|
||||
if (mMainFabCenterY == -1f) {
|
||||
// It is before first onLayout
|
||||
int count = getChildCount() - 1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
getChildAt(i).setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
|
||||
}
|
||||
} else {
|
||||
int count = getChildCount() - 1;
|
||||
for (int i = 0; i < count; i++) {
|
||||
View child = getChildAt(i);
|
||||
if (animation) {
|
||||
setChildAnimation(child, expanded);
|
||||
} else {
|
||||
child.setVisibility(expanded ? View.VISIBLE : View.INVISIBLE);
|
||||
if (expanded) {
|
||||
child.setAlpha(1f);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void setChildAnimation(final View child, final boolean expanded) {
|
||||
float startTranslationY;
|
||||
float endTranslationY;
|
||||
float startAlpha;
|
||||
float endAlpha;
|
||||
if (expanded) {
|
||||
startTranslationY = mMainFabCenterY -
|
||||
(child.getTop() + (child.getHeight() / 2));
|
||||
endTranslationY = 0f;
|
||||
startAlpha = 0f;
|
||||
endAlpha = 1f;
|
||||
} else {
|
||||
startTranslationY = 0f;
|
||||
endTranslationY = mMainFabCenterY -
|
||||
(child.getTop() + (child.getHeight() / 2));
|
||||
startAlpha = 1f;
|
||||
endAlpha = 0f;
|
||||
}
|
||||
|
||||
PropertyValuesHolder translationYPvh = PropertyValuesHolder.ofFloat(
|
||||
"translationY", startTranslationY, endTranslationY);
|
||||
PropertyValuesHolder alphaPvh = PropertyValuesHolder.ofFloat(
|
||||
"alpha", startAlpha, endAlpha);
|
||||
ObjectAnimator oa = ObjectAnimator.ofPropertyValuesHolder(child, translationYPvh, alphaPvh);
|
||||
oa.setDuration(ANIMATE_TIME);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
|
||||
oa.setAutoCancel(true);
|
||||
}
|
||||
oa.addListener(new SimpleAnimatorListener() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
if (expanded) {
|
||||
child.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
if (!expanded) {
|
||||
child.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
oa.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 Hippo Seven
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
tools:targetApi="21"
|
||||
|
||||
auto:width="24dp"
|
||||
auto:height="24dp"
|
||||
auto:viewportWidth="24"
|
||||
auto:viewportHeight="24"
|
||||
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
auto:pathData="@string/pd_arrow_up"
|
||||
auto:fillColor="@color/primary_drawable_dark"
|
||||
|
||||
android:pathData="@string/pd_arrow_up"
|
||||
android:fillColor="@color/primary_drawable_dark"/>
|
||||
|
||||
</vector>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
~ Copyright (C) 2015 Hippo Seven
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<vector
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
tools:targetApi="21"
|
||||
|
||||
auto:width="24dp"
|
||||
auto:height="24dp"
|
||||
auto:viewportWidth="24"
|
||||
auto:viewportHeight="24"
|
||||
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
auto:pathData="@string/pd_go_to"
|
||||
auto:fillColor="@color/primary_drawable_dark"
|
||||
|
||||
android:pathData="@string/pd_go_to"
|
||||
android:fillColor="@color/primary_drawable_dark"/>
|
||||
|
||||
</vector>
|
||||
@@ -15,6 +15,7 @@
|
||||
-->
|
||||
<com.hippo.ehviewer.widget.OffsetLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
@@ -40,17 +41,39 @@
|
||||
android:layout_marginTop="@dimen/search_bar_padding_vertical"
|
||||
auto:forceNoElevation="true"/>
|
||||
|
||||
<com.hippo.widget.FloatingActionButton
|
||||
xmlns:auto="http://schemas.android.com/apk/res-auto"
|
||||
style="@style/FloatingActionButton"
|
||||
android:id="@+id/fab"
|
||||
<com.hippo.widget.FloatingActionButtonLayout
|
||||
android:id="@+id/fab_layout"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="bottom|right"
|
||||
android:layout_marginRight="@dimen/corner_fab_padding_right"
|
||||
android:layout_marginBottom="@dimen/corner_fab_padding_bottom"
|
||||
auto:color="?attr/colorAccent"
|
||||
tools:ignore="RtlHardcoded"/>
|
||||
tools:ignore="RtlHardcoded">
|
||||
|
||||
<com.hippo.widget.FloatingActionButton
|
||||
style="@style/FloatingActionButton.ForceNoElevation.Small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
auto:color="?attr/colorPrimary"
|
||||
auto:drawable="@drawable/ic_arrow_up_dark"
|
||||
auto:forceNoElevation="true"/>
|
||||
|
||||
<com.hippo.widget.FloatingActionButton
|
||||
style="@style/FloatingActionButton.ForceNoElevation.Small"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
auto:color="?attr/colorPrimary"
|
||||
auto:drawable="@drawable/ic_go_to_dark"
|
||||
auto:forceNoElevation="true"/>
|
||||
|
||||
<com.hippo.widget.FloatingActionButton
|
||||
style="@style/FloatingActionButton.ForceNoElevation"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
auto:color="?attr/colorAccent"
|
||||
auto:forceNoElevation="true"/>
|
||||
|
||||
</com.hippo.widget.FloatingActionButtonLayout>
|
||||
|
||||
</com.hippo.ehviewer.widget.OffsetLayout>
|
||||
|
||||
@@ -19,5 +19,7 @@
|
||||
<!-- Fab -->
|
||||
<dimen name="fab_size">56dp</dimen>
|
||||
<dimen name="fab_size_small">40dp</dimen>
|
||||
<dimen name="fab_size_fne">60dp</dimen>
|
||||
<dimen name="fab_size_fne_small">44dp</dimen>
|
||||
|
||||
</resources>
|
||||
@@ -26,6 +26,7 @@
|
||||
<declare-styleable name="FloatingActionButton">
|
||||
<attr name="color"/>
|
||||
<attr name="drawable"/>
|
||||
<attr name="forceNoElevation"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="FloatLabelEditText">
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
-->
|
||||
<resources>
|
||||
|
||||
<!-- FloatingActionBarLayout -->
|
||||
<dimen name="floating_action_bar_layout_interval">16dp</dimen>
|
||||
|
||||
<!-- Simple Dialog -->
|
||||
<dimen name="simple_dialog_padding">16dp</dimen>
|
||||
<dimen name="simple_dialog_fixed_width">320dp</dimen>
|
||||
@@ -92,6 +95,9 @@
|
||||
<!-- Fab -->
|
||||
<dimen name="fab_size">60dp</dimen>
|
||||
<dimen name="fab_size_small">44dp</dimen>
|
||||
<dimen name="fab_size_fne">60dp</dimen>
|
||||
<dimen name="fab_size_fne_small">44dp</dimen>
|
||||
<dimen name="fab_drawable_size">24dp</dimen>
|
||||
|
||||
<!-- DrawerArrowDrawable -->
|
||||
<dimen name="dad_drawable_size">24dp</dimen>
|
||||
|
||||
@@ -21,5 +21,7 @@
|
||||
<string name="pd_menu" translatable="false">M3,6H21V8H3V6M3,11H21V13H3V11M3,16H21V18H3V16Z</string>
|
||||
<string name="pd_android_debug_bridge" translatable="false">M15,9A1,1 0 0,1 14,8A1,1 0 0,1 15,7A1,1 0 0,1 16,8A1,1 0 0,1 15,9M9,9A1,1 0 0,1 8,8A1,1 0 0,1 9,7A1,1 0 0,1 10,8A1,1 0 0,1 9,9M16.12,4.37L18.22,2.27L17.4,1.44L15.09,3.75C14.16,3.28 13.11,3 12,3C10.88,3 9.84,3.28 8.91,3.75L6.6,1.44L5.78,2.27L7.88,4.37C6.14,5.64 5,7.68 5,10V11H19V10C19,7.68 17.86,5.64 16.12,4.37M5,16C5,19.86 8.13,23 12,23A7,7 0 0,0 19,16V12H5V16Z</string>
|
||||
<string name="pd_help_circle" translatable="false">M15.07,11.25L14.17,12.17C13.45,12.89 13,13.5 13,15H11V14.5C11,13.39 11.45,12.39 12.17,11.67L13.41,10.41C13.78,10.05 14,9.55 14,9C14,7.89 13.1,7 12,7A2,2 0 0,0 10,9H8A4,4 0 0,1 12,5A4,4 0 0,1 16,9C16,9.88 15.64,10.67 15.07,11.25M13,19H11V17H13M12,2A10,10 0 0,0 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12C22,6.47 17.5,2 12,2Z</string>
|
||||
<string name="pd_arrow_up" translatable="false">M13,20H11V8L5.5,13.5L4.08,12.08L12,4.16L19.92,12.08L18.5,13.5L13,8V20Z</string>
|
||||
<string name="pd_go_to" translatable="false">M10.5,7A6.5,6.5 0 0,0 4,13.5A6.5,6.5 0 0,0 10.5,20H14V18H10.5C8,18 6,16 6,13.5C6,11 8,9 10.5,9H16.17L13.09,12.09L14.5,13.5L20,8L14.5,2.5L13.08,3.91L16.17,7H10.5M18,18H16V20H18V18Z</string>
|
||||
|
||||
</resources>
|
||||
@@ -35,6 +35,16 @@
|
||||
<item name="android:minHeight">@dimen/fab_size_small</item>
|
||||
</style>
|
||||
|
||||
<style name="FloatingActionButton.ForceNoElevation">
|
||||
<item name="android:minWidth">@dimen/fab_size_fne</item>
|
||||
<item name="android:minHeight">@dimen/fab_size_fne</item>
|
||||
</style>
|
||||
|
||||
<style name="FloatingActionButton.ForceNoElevation.Small">
|
||||
<item name="android:minWidth">@dimen/fab_size_fne_small</item>
|
||||
<item name="android:minHeight">@dimen/fab_size_fne_small</item>
|
||||
</style>
|
||||
|
||||
<style name="FloatingActionButton.Content">
|
||||
<item name="android:layout_gravity">right|bottom</item>
|
||||
<item name="android:layout_marginLeft">@dimen/content_fab_margin_start</item>
|
||||
|
||||
Reference in new issue
Block a user