制作几乎扩展的浮动操作按钮

大家好

不到半年后,我的应用程序开始工作,其中“浮动操作按钮”菜单是由第三方库实现的。

在某些时候,我想使其变得更加愉快和方便。



已成为


礼物是我遇到了我成功优化的其他地方的低效率代码。

应用程序创建历史
购物车小部件历史

实作

1.按钮布局
fab_layout.xml <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:cardView="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.CardView android:id="@+id/fab_spending" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:visibility="invisible" cardView:cardBackgroundColor="@color/red" cardView:cardCornerRadius="12dp" cardView:cardElevation="8dp"> <TextView style="@style/White16" android:layout_width="120dp" android:layout_height="36dp" android:drawableRight="@drawable/remove" android:drawablePadding="6dp" android:gravity="center" android:padding="4dp" android:text="@string/spending"/> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/fab_income" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:visibility="invisible" cardView:cardBackgroundColor="@color/green" cardView:cardCornerRadius="12dp" cardView:cardElevation="8dp"> <TextView style="@style/White16" android:layout_width="120dp" android:layout_height="36dp" android:drawableRight="@drawable/add" android:drawablePadding="6dp" android:gravity="center" android:text="@string/income"/> </android.support.v7.widget.CardView> <android.support.v7.widget.CardView android:id="@+id/fab_transfer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:visibility="invisible" cardView:cardBackgroundColor="@color/gunmetal" cardView:cardCornerRadius="12dp" cardView:cardElevation="8dp"> <TextView style="@style/White16" android:layout_width="120dp" android:layout_height="36dp" android:drawableRight="@drawable/autorenew" android:drawablePadding="6dp" android:gravity="center" android:text="@string/transfer"/> </android.support.v7.widget.CardView> </FrameLayout> 


2.动画

2.1外观
   <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--Move--> <translate android:duration="300" android:fromXDelta="125%" android:fromYDelta="25%" android:interpolator="@android:anim/linear_interpolator" android:toXDelta="0%" android:toYDelta="0%"></translate> <!--Fade In--> <alpha android:duration="300" android:fromAlpha="0.0" android:interpolator="@android:anim/decelerate_interpolator" android:toAlpha="1.0"></alpha> </set>  <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--Move--> <translate android:duration="300" android:fromXDelta="75%" android:fromYDelta="210%" android:interpolator="@android:anim/linear_interpolator" android:toXDelta="0%" android:toYDelta="0%"></translate> <!--Fade In--> <alpha android:duration="300" android:fromAlpha="0.0" android:interpolator="@android:anim/decelerate_interpolator" android:toAlpha="1.0"></alpha> </set>  <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--Move--> <translate android:duration="300" android:fromXDelta="25%" android:fromYDelta="400%" android:interpolator="@android:anim/linear_interpolator" android:toXDelta="0%" android:toYDelta="0%"></translate> <!--Fade In--> <alpha android:duration="300" android:fromAlpha="0.0" android:interpolator="@android:anim/decelerate_interpolator" android:toAlpha="1.0"></alpha> </set> 


2.1失踪
底部子菜单

 <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--Move--> <translate android:duration="300" android:fromXDelta="-125%" android:fromYDelta="-25%" android:interpolator="@android:anim/linear_interpolator" android:toXDelta="0%" android:toYDelta="0%"></translate> <!--Fade Out--> <alpha android:duration="300" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.0"></alpha> </set>  <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--Move--> <translate android:duration="300" android:fromXDelta="-75%" android:fromYDelta="-210%" android:interpolator="@android:anim/linear_interpolator" android:toXDelta="0%" android:toYDelta="0%"></translate> <!--Fade Out--> <alpha android:duration="300" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.0"></alpha> </set>  <?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="true"> <!--Move--> <translate android:duration="300" android:fromXDelta="-25%" android:fromYDelta="-400%" android:interpolator="@android:anim/linear_interpolator" android:toXDelta="0%" android:toYDelta="0%"></translate> <!--Fade Out--> <alpha android:duration="300" android:fromAlpha="1.0" android:interpolator="@android:anim/accelerate_interpolator" android:toAlpha="0.0"></alpha> </set> 


3.屏幕布局
 <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:card_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content"> <ua.karelov.beans.ui.custom.MyRelativeLayout android:id="@+id/l_root" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.RecyclerView android:id="@+id/rv_transactions" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="4dp" android:clickable="true" android:fadingEdgeLength="20dp" android:focusable="true" android:requiresFadingEdge="vertical"/> </ua.karelov.beans.ui.custom.MyRelativeLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_marginRight="16dp" android:layout_marginBottom="46dp" android:rotation="45" android:src="@drawable/close" app:layout_behavior=".ui.custom.FABScroll" /> <include layout="@layout/fab_layout" android:layout_width="match_parent" android:layout_height="500dp" android:layout_gravity="bottom|end" android:layout_marginBottom="46dp"/> </android.support.design.widget.CoordinatorLayout> 


4. FAB滚动行为
 import android.content.Context; import android.support.annotation.NonNull; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.FloatingActionButton; import android.support.v4.view.ViewCompat; import android.util.AttributeSet; import android.view.View; import android.view.animation.LinearInterpolator; public class FABScroll extends FloatingActionButton.Behavior { public FABScroll(Context context, AttributeSet attrs) { super(); } @Override public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) { super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); //child -> Floating Action Button if (dyConsumed > 0) { CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) child.getLayoutParams(); int fab_bottomMargin = layoutParams.bottomMargin; child.animate().translationY(child.getHeight() + fab_bottomMargin).setInterpolator(new LinearInterpolator()).start(); } else if (dyConsumed < 0) { child.animate().translationY(0).setInterpolator(new LinearInterpolator()).start(); } } @Override public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) { return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL; } } 


5.我们将从RelativeLayout继承来处理在空座位上的点击以关闭菜单
 import android.content.Context; import android.util.AttributeSet; import android.view.MotionEvent; import android.widget.RelativeLayout; public class MyRelativeLayout extends RelativeLayout { private boolean layoutClickable = true; public void setLayoutClickable(boolean layoutClickable) { this.layoutClickable = layoutClickable; } public boolean isLayoutClickable() { return layoutClickable; } public MyRelativeLayout(Context context) { super(context); } public MyRelativeLayout(Context context, AttributeSet attrs) { super(context, attrs); } public MyRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // true if you do not want the children to be clickable. return !layoutClickable; } } 


6.连接片段中的所有内容
 private static final double transitionSmall = 0.25; private static final double transitionMediumX = 0.75; private static final double transitionMediumY = 2.1; private static final double transitionBigY = 4; @BindView(R.id.fab) FloatingActionButton fab; @BindView(R.id.fab_spending) CardView fabSpending; @BindView(R.id.fab_income) CardView fabIncome; @BindView(R.id.fab_transfer) CardView fabTransfer; //Animations Animation fadeIn; Animation fadeOut; Animation showFabSpending; Animation hideFabSpending; Animation showFabIncome; Animation hideFabIncome; Animation showFabTransfer; Animation hideFabTransfer; @Override protected void initView() { super.initView(); //Animations fadeIn = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_in); fadeOut = AnimationUtils.loadAnimation(getActivity(), R.anim.fade_out); showFabSpending = AnimationUtils.loadAnimation(getActivity(), R.anim.fab1_show); hideFabSpending = AnimationUtils.loadAnimation(getActivity(), R.anim.fab1_hide); showFabIncome = AnimationUtils.loadAnimation(getActivity(), R.anim.fab2_show); hideFabIncome = AnimationUtils.loadAnimation(getActivity(), R.anim.fab2_hide); showFabTransfer = AnimationUtils.loadAnimation(getActivity(), R.anim.fab3_show); hideFabTransfer = AnimationUtils.loadAnimation(getActivity(), R.anim.fab3_hide); } @OnTouch(R.id.l_root) public boolean clickRoot() { if(!lRoot.isLayoutClickable()) { //Close FAB menu hideFAB(); } return true; } private void expandFAB() { ViewCompat.animate(fab). rotation(-90). withLayer(). setDuration(300). start(); lRoot.setLayoutClickable(false); lRoot.startAnimation(fadeOut); //Floating Action Button 1 FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fabSpending.getLayoutParams(); layoutParams.rightMargin += (int) (fabSpending.getWidth() * (1 + transitionSmall)); layoutParams.bottomMargin += (int) (fabSpending.getHeight() * transitionSmall); fabSpending.setLayoutParams(layoutParams); fabSpending.startAnimation(showFabSpending); fabSpending.setClickable(true); //Floating Action Button 2 FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) fabIncome.getLayoutParams(); layoutParams2.rightMargin += (int) (fabIncome.getWidth() * transitionMediumX); layoutParams2.bottomMargin += (int) (fabIncome.getHeight() * transitionMediumY); fabIncome.setLayoutParams(layoutParams2); fabIncome.startAnimation(showFabIncome); fabIncome.setClickable(true); //Floating Action Button 3 FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) fabTransfer.getLayoutParams(); layoutParams3.rightMargin += (int) (fabTransfer.getWidth() * transitionSmall); layoutParams3.bottomMargin += (int) (fabTransfer.getHeight() * transitionBigY); fabTransfer.setLayoutParams(layoutParams3); fabTransfer.startAnimation(showFabTransfer); fabTransfer.setClickable(true); } private void hideFAB() { ViewCompat.animate(fab). rotation(45f). withLayer(). setDuration(300). start(); lRoot.setLayoutClickable(true); lRoot.startAnimation(fadeIn); //Floating Action Button 1 FrameLayout.LayoutParams layoutParams = (FrameLayout.LayoutParams) fabSpending.getLayoutParams(); layoutParams.rightMargin -= (int) (fabSpending.getWidth() * (1 + transitionSmall)); layoutParams.bottomMargin -= (int) (fabSpending.getHeight() * transitionSmall); fabSpending.setLayoutParams(layoutParams); fabSpending.startAnimation(hideFabSpending); fabSpending.setClickable(false); //Floating Action Button 2 FrameLayout.LayoutParams layoutParams2 = (FrameLayout.LayoutParams) fabIncome.getLayoutParams(); layoutParams2.rightMargin -= (int) (fabIncome.getWidth() * transitionMediumX); layoutParams2.bottomMargin -= (int) (fabIncome.getHeight() * transitionMediumY); fabIncome.setLayoutParams(layoutParams2); fabIncome.startAnimation(hideFabIncome); fabIncome.setClickable(false); //Floating Action Button 3 FrameLayout.LayoutParams layoutParams3 = (FrameLayout.LayoutParams) fabTransfer.getLayoutParams(); layoutParams3.rightMargin -= (int) (fabTransfer.getWidth() * transitionSmall); layoutParams3.bottomMargin -= (int) (fabTransfer.getHeight() * transitionBigY); fabTransfer.setLayoutParams(layoutParams3); fabTransfer.startAnimation(hideFabTransfer); fabTransfer.setClickable(false); } private void initMenu() { fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if(lRoot.isLayoutClickable()) { //Display FAB menu expandFAB(); } else { //Close FAB menu hideFAB(); } } }); } //     (          ) fab.animate().translationY(0).setInterpolator(new LinearInterpolator()).start(); 

Source: https://habr.com/ru/post/zh-CN455728/


All Articles