美文网首页
Android UI进阶之旅11--Material Desig

Android UI进阶之旅11--Material Desig

作者: 小楠总 | 来源:发表于2017-05-21 16:46 被阅读172次

    FloatingActionButton

    一个基本的使用例子如下:

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_gravity="right|bottom"
        android:onClick="rotate"
        android:src="@drawable/ic_add_white_24dp"
        app:backgroundTint="?attr/colorPrimary"
        app:elevation="10dp"
        app:fabSize="normal"
        app:rippleColor="#f00"
        />
    

    其中:

    1. src属性是设置图标
    2. backgroundTint是设置背景色(图标是透明背景的)
    3. elevation是设置阴影大小
    4. fabsize是设置图标的大小,一般为normal(不用设置)
    5. rippleColor是设置水波纹的颜色

    点击事件如下(旋转):

    private boolean reverse = false;
    
    public void rotate(View v) {
        float toDegree = reverse ? -180f : 180f;
        ObjectAnimator animator = ObjectAnimator
                .ofFloat(v, "rotation", 0.0f, toDegree)
                .setDuration(400);
        animator.start();
        reverse = !reverse;
    }
    

    兼容性问题

    与CardViewy一样:

    阴影的细微差别,这里直接在不同的dimen中设置即可:

    1. 5.x系统:边距阴影比较小,需要手动添加边距16dp,android:layout_margin="16dp"
    2. 4.x系统:边距阴影比较大,手动修改边距0dp(原因:兼容包里面设置阴影效果自动设置了margin来处理16dp)

    FloatingActionButton动画

    列表滑动的时候FloatingActionButton隐藏与显示

    通过自定义OnScrollListener实现

    核心的逻辑如下:

    public class FabScrollListener extends OnScrollListener {
        private static final int THRESHOLD = 20;
        private int distance = 0;
        private HideScrollListener hideListener;
        private boolean visible = true;//是否可见
    
        public FabScrollListener(HideScrollListener hideScrollListener) {
            this.hideListener = hideScrollListener;
        }
    
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            /**
             * dy:Y轴方向的增量
             * 有正和负
             * 当正在执行动画的时候,就不要再执行了
             */
            if (distance > THRESHOLD && visible) {
                //隐藏动画
                visible = false;
                hideListener.onHide();
                distance = 0;
            } else if (distance < -THRESHOLD && !visible) {
                //显示动画
                visible = true;
                hideListener.onShow();
                distance = 0;
            }
            if (visible && dy > 0 || (!visible && dy < 0)) {
                distance += dy;
            }
        }
    
    }
    

    自定义一个OnScrollListener,重写onScrolled方法。判断当前的滚动方向、滚动距离、当前的FloatingActionButton是否显示来进行相应的逻辑处理。

    其中HideScrollListener是一个自定义的监听接口:

    public interface HideScrollListener {
        void onHide();
        void onShow();
    }
    

    由Activity实现这个接口:

    public class FabAnimActivity extends AppCompatActivity implements HideScrollListener {
    
        private RecyclerView recyclerview;
        private ImageButton fab;
        private Toolbar toolbar;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //省略一些代码
    
            //添加滑动监听
            recyclerview.addOnScrollListener(new FabScrollListener(this));
        }
    
        @Override
        public void onHide() {
            // 隐藏动画--属性动画
            toolbar.animate().translationY(-toolbar.getHeight()).setInterpolator(new AccelerateInterpolator(3));
            RelativeLayout.LayoutParams layoutParams = (LayoutParams) fab.getLayoutParams();
    
            fab.animate().translationY(fab.getHeight() + layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3));
        }
    
        @Override
        public void onShow() {
            // 显示动画--属性动画
            toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
    
            fab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
        }
    }
    

    通过自定义FloatingActionButton的Behavior实现

    通过协调并调度里面的子控件或者布局来实现触摸(一般是指滑动)产生一些相关的动画效果。可以通过设置view的Behavior来实现触摸的动画调度。

    继承FloatingActionButton的Behavior:

    public class FabBehavior extends FloatingActionButton.Behavior {
        private boolean visible = true;//是否可见
    
        //实例化CoordinatorLayout.LayoutParams时反射生成Behavior实例,这就是为什么自定义behavior需要重写如下的构造函数
        public FabBehavior(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        @Override
        public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, FloatingActionButton child, View directTargetChild, View target, int nestedScrollAxes) {
            // 当观察的View(RecyclerView)发生滑动的开始的时候回调的
            //nestedScrollAxes:滑动关联轴, 我们现在只关心垂直的滑动。
            return nestedScrollAxes == ViewCompat.SCROLL_AXIS_VERTICAL || super.onStartNestedScroll(coordinatorLayout, child, directTargetChild, target, nestedScrollAxes);
        }
    
        @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);
            // 当观察的view滑动的时候回调的
            //根据情况执行动画
            if (dyConsumed > 0 && visible) {
                //show
                visible = false;
                onHide(child);
            } else if (dyConsumed < 0) {
                //hide
                visible = true;
                onShow(child);
            }
    
        }
    
        public void onHide(FloatingActionButton fab) {
            // 隐藏动画--属性动画
    //      toolbar.animate().translationY(-toolbar.getHeight()).setInterpolator(new AccelerateInterpolator(3));
    
            CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
    //      fab.animate().translationY(fab.getHeight()+layoutParams.bottomMargin).setInterpolator(new AccelerateInterpolator(3));
            //FAB 缩小
            ViewCompat.animate(fab).scaleX(0f).scaleY(0f).start();
        }
    
        public void onShow(FloatingActionButton fab) {
            // 显示动画--属性动画
    //      toolbar.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
    
            CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) fab.getLayoutParams();
    //      fab.animate().translationY(0).setInterpolator(new DecelerateInterpolator(3));
            //FAB放大
            ViewCompat.animate(fab).scaleX(1f).scaleY(1f).start();
        }
    
    }
    

    其中:

    构造方法必须重写,重写onStartNestedScroll返回判断哪个方向的滑动,重写onNestedScroll进行相应的逻辑处理(FloatingActionButton的属性动画显示与隐藏)。

    最后在布局文件中使用CoordinatorLayout布局,并且给FloatingActionButton添加自定义的Behavior:

    <android.support.design.widget.CoordinatorLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:clipChildren="false"
            android:clipToPadding="false"
            android:paddingTop="?attr/actionBarSize"
            />
    
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:title="Fab动画"
            app:titleTextColor="#fff"/>
    
        <android.support.design.widget.FloatingActionButton
            android:id="@+id/fab"
            android:layout_width="58dp"
            android:layout_height="58dp"
            android:layout_gravity="bottom|end"
            android:layout_margin="16dp"
            android:src="@drawable/ic_favorite_outline_white_24dp"
            app:layout_behavior="com.nan.advancedui.fab.anim.behavior.FabBehavior"
            />
    
    </android.support.design.widget.CoordinatorLayout>
    

    如果觉得我的文字对你有所帮助的话,欢迎关注我的公众号:

    公众号:Android开发进阶

    我的群欢迎大家进来探讨各种技术与非技术的话题,有兴趣的朋友们加我私人微信huannan88,我拉你进群交(♂)流(♀)

    相关文章

      网友评论

          本文标题:Android UI进阶之旅11--Material Desig

          本文链接:https://www.haomeiwen.com/subject/puqvxxtx.html