Implementation of scrolling hide and pop-up effects of FloatingActionButton

FloatingActionButton can be said to be one of the symbols of Material Design, but many people don't like it very much. One of the main reasons is that the existence of FAB blocks the content to be displayed, thus affecting the experience.

This article mainly introduces the optimization of FAB in two aspects, one is the special effect of clicking the FAB pop-up submenu, and the other is the automatic hiding of FAB when sliding. The final implementation effect is shown in the following figure:

【Picture 0】


Implementation of pop-up effect

A third-party FAB library is used here , and the main implementation steps are as follows.

First use Android Studio to create a new Blank Activity, we found that the Activity comes with a FAB by default, as shown in the figure:

【Picture 1】

Import dependencies in build.gradle:

compile 'com.getbase:floatingactionbutton:1.10.1'

Then click "Sync Now" AS will automatically complete the download of dependencies, we don't need to go to GitHub to download.

Next, use the FloatingActionsMenu of the third-party library to replace the FloatingActionButton in the previous layout file. FloatingActionsMenu can be said to be a FAB collection, which itself contains an add button. After clicking the button, the submenu will be expanded to realize pop-up special effects. The layout file activity_main.xml is as follows:

<?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:tools="http://schemas.android.com/tools"
    xmlns:fab="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.android.wangkang.fabdemo.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <com.getbase.floatingactionbutton.FloatingActionsMenu
        android:id="@+id/fab_menu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        fab:fab_addButtonColorNormal="@color/colorAccent"
        fab:fab_icon="@drawable/ic_add_24dp"
        fab:fab_labelStyle="@style/menu_labels_style"
        fab:fab_labelsPosition="left">

        <com.getbase.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab_1"
            fab:fab_colorNormal="@color/colorAccent"
            fab:fab_size="mini"
            fab:fab_icon="@drawable/ic_timer_24dp"
            fab:fab_title="第一个FAB"/>
        <com.getbase.floatingactionbutton.FloatingActionButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/fab_2"
            fab:fab_colorNormal="@color/colorAccent"
            fab:fab_size="mini"
            fab:fab_icon="@drawable/ic_accessibility_24dp"
            fab:fab_title="第二个FAB"/>
    </com.getbase.floatingactionbutton.FloatingActionsMenu>

</android.support.design.widget.CoordinatorLayout>


Don't forget to add the namespace here

xmlns:fab="http://schemas.android.com/apk/res-auto"


We need to set the labelStyle ourselves, first add the following two colors to colors.xml:

<color name="black_semi_transparent">#B2000000</color>
<color name="text">#FFFFFF</color>


Add the following code to styles:

<style name="menu_labels_style">
    <item name="android:background">@drawable/fab_label_background</item>
    <item name="android:textColor">@color/text</item>
</style>

The above fab_label_background can be defined in the drawable folder by itself. The reference is as follows:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <solid android:color="@color/black_semi_transparent"/>
    <padding
        android:left="16dp"
        android:top="4dp"
        android:right="16dp"
        android:bottom="4dp"/>
    <corners
        android:radius="2dp"/>
</shape>


The ic_add_24dp, ic_timer_24dp and ic_accessibility_24dp in the layout file can be selected by right-clicking the drawable folder--New--Vector asset, and clicking choose under the material icon to select the icon.

Delete the code about FloatingActionButton in MainActivity, and then run the application to get the following effect:

【Picture 2】

Scroll hide implementation

In this article , the scrolling hiding of the FloatingActionButton is implemented. Here we use the same method to implement the scrolling hiding of the FloatingActionsMenu.
First, use Android Studio to create a new RecyclerView, right-click under the package name--New--Fragment--Fragment(List), and then AS will automatically create the classes and layout files required by RecyclerView for us. And a RecyclerView containing 25 items is generated by default , and we can use it directly here.
Delete this line in the main layout file activity_main
<include layout="@layout/content_main"/>


Place a fragment container at this location:
<FrameLayout
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/fragmentContainer"/>
Add a Fragment containing RecyclerView to the onCreate() method in MainActivity :
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    FragmentManager fm=getSupportFragmentManager();
    Fragment mFragment=fm.findFragmentById(R.id.fragmentContainer);

    if (mFragment==null){
        mFragment=new ItemFragment();
        fm.beginTransaction().add(R.id.fragmentContainer,mFragment).commit();
    }
}
Because the default generated ItemFragment has a listening interface, we need to implement this interface in MainActivity and override the methods in the interface. You can choose to do nothing or add the click event you need:
public class MainActivity extends AppCompatActivity implements ItemFragment.OnListFragmentInteractionListener {
    @Override
    public void onListFragmentInteraction(DummyContent.DummyItem item) {

    }


Then create a new ScrollAwareFABBehavior class, inherited from CoordinatorLayout.Behavior<FloatingActionsMenu>, the code is as follows:

public class ScrollAwareFABBehavior extends CoordinatorLayout.Behavior<FloatingActionsMenu> {

    private static final android.view.animation.Interpolator INTERPOLATOR=new FastOutSlowInInterpolator();
    private boolean mIsAnimatingOut=false;

    public ScrollAwareFABBehavior(Context context, AttributeSet attrs){
        super();
    }
    @Override
    public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View directTargetChild, View target, int nestedScrollAxes) {
        //处理垂直方向上的滚动事件
        return nestedScrollAxes== ViewCompat.SCROLL_AXIS_VERTICAL|| super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
    }

    @Override
    public void onNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionsMenu child, View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed) {
        super.onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed);
        //向上滚动进入,向下滚动隐藏
        if (dyConsumed>0&&!this.mIsAnimatingOut && child.getVisibility()==View.VISIBLE){
            //如果是展开的话就先收回去
            if (child.isExpanded()){
                child.collapse();
            }
            //animateOut()和animateIn()都是私有方法,需要重新实现
            animateOut(child);
        } else if (dyConsumed<0 && child.getVisibility()!=View.VISIBLE){
            animateIn(child);
        }
    }

    private void animateOut(final FloatingActionsMenu button){
            ViewCompat.animate(button).translationY(500)
                .setInterpolator(INTERPOLATOR).withLayer()
                    .setListener(new ViewPropertyAnimatorListener() {
                        @Override
                        public void onAnimationStart(View view) {
                            ScrollAwareFABBehavior.this.mIsAnimatingOut=true;
                        }

                        @Override
                        public void onAnimationEnd(View view) {
                            ScrollAwareFABBehavior.this.mIsAnimatingOut=false;
                            view.setVisibility(View.GONE);
                        }

                        @Override
                        public void onAnimationCancel(View view) {
                            ScrollAwareFABBehavior.this.mIsAnimatingOut=false;

                        }
                    }).start();
        }

    private void animateIn(FloatingActionsMenu button){
        button.setVisibility(View.VISIBLE);
            ViewCompat.animate(button).translationY(0)
                    .setInterpolator(INTERPOLATOR).withLayer().setListener(null)
                    .start();
        }
}

Finally, add the following properties to the FloatingActionsMenu of the layout file (remember to change the package name to your own):

app:layout_behavior="com.android.wangkang.fabdemo.ScrollAwareFABBehavior"

 
 
Run the application, you can get the auto-hide effect, and the menu expanded before hiding will be retracted first:

【Picture 4】

Demo source code: https://github.com/w-kahn/FABDemo


Guess you like

Origin blog.csdn.net/w_kahn/article/details/50364149