动画必须有(二):悬浮菜单了解一下!

动画必须有(一): 属性动画浅谈
githhub传送门


目录

  • 前言
  • 效果图
  • FloatingActionButton基础
  • FloatingActionButton实例
  • 最后

前言

悬浮按钮是我非常喜欢的, 可以把最关键的功能放入到悬浮按钮中. 比如日记app里的新建日记, 阅读类app里的喜欢. 稍微处理一下可以将悬浮按钮扩展成悬浮菜单, 来看下实现吧! github直接看源码


效果图

废话不多说, 先看图, 感兴趣再往下看!

动画必须有(二):悬浮菜单了解一下!_第1张图片
悬浮菜单

FloatingActionButton基础

记得导包.

compile 'com.android.support:design:26.+'

可以看看谷歌官方介绍. 你会被瞬间圈粉. 然后是官方文档, 这个文档说了如何调用.

  • 搭配Snackbar
    官方推荐配合Snackbar来使用, 这都不多说了.
动画必须有(二):悬浮菜单了解一下!_第2张图片
配合Snackbar
  • 显示和隐藏
    然后还有就是悬浮按钮的隐藏和显示函数.
Button btHide = (Button) findViewById(R.id.bt_hide);
btHide.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        fab.hide();
    }
});

Button btShow = (Button) findViewById(R.id.bt_show);
btShow.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        fab.show();
    }
});
动画必须有(二):悬浮菜单了解一下!_第3张图片
隐藏和显示
  • 颜色
    可以设置点击颜色app:rippleColor, 以及背景颜色app:backgroundTint. 我将背景色改成蓝色, 点击水波纹扩散变为紫色, 效果图如下:
设置颜色
动画必须有(二):悬浮菜单了解一下!_第4张图片
注意看颜色
  • 位置
    当然了, 位置可以随便改, 甚至可以吸附在某个控件之上.
android:layout_gravity="bottom|left"
动画必须有(二):悬浮菜单了解一下!_第5张图片
设置位置

吸附效果如下, 即使滚动也会保持相对的位置:

app:layout_anchor="@id/toolbar"
app:layout_anchorGravity="center|bottom"
动画必须有(二):悬浮菜单了解一下!_第6张图片
吸附并设置位置

FloatingActionButton实例

来看看效果图是如何实现的吧.

  • 布局文件
    布局文件是个要点, 里面塞进了两个菜单, 你选一个喜欢的用就好. 一个是扇型的, 一个是线型的.



    

        

        

        

        
    

    

        

            

                

                
            

            

                

                
            

            

                

                
            

            

                

                
            
        

        
    

    
  • normal与mini
    悬浮按钮有两种尺寸, normal和mini. 在xml中加入app:fabSize="mini"就变成mini尺寸的了. 所以在设置动画和位置的时候不是将按钮全部放置在同一位置, 需要修正位置. 修正距离就是(normal-mini)/2, 应该很好理解.
// 计算偏移值
int w = View.MeasureSpec.makeMeasureSpec(0,
        View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,
        View.MeasureSpec.UNSPECIFIED);
mFabOrigin.measure(w, h);
mFabLeft.measure(w, h);
mOffset = (mFabOrigin.getMeasuredHeight() - mFabLeft.getMeasuredHeight()) / 2;

// 修正位置
FrameLayout.LayoutParams lParams = (FrameLayout.LayoutParams) mFabLeft.getLayoutParams();
lParams.setMargins(0, 0, UIUtil.dp2px(20) + mOffset, UIUtil.dp2px(20) + mOffset);
mFabLeft.setLayoutParams(lParams);
FrameLayout.LayoutParams ltParams = (FrameLayout.LayoutParams) mFabLeftTop.getLayoutParams();
ltParams.setMargins(0, 0, UIUtil.dp2px(20) + mOffset, UIUtil.dp2px(20) + mOffset);
mFabLeftTop.setLayoutParams(ltParams);
FrameLayout.LayoutParams tParams = (FrameLayout.LayoutParams) mFabTop.getLayoutParams();
tParams.setMargins(0, 0, UIUtil.dp2px(20) + mOffset, UIUtil.dp2px(20) + mOffset);
mFabTop.setLayoutParams(tParams);
  • 关于动画
    只要位置算对了, 动画不是特别难, 当然想要像google或者apple的动画那样舒适还是很难的. 没看第一篇的可以回头看看.
/**
 * 显示扇型菜单
 */
private void showFanMenu() {
    // 标识符设置是
    mFanMenuOpen = true;

    // 按钮1向左移动
    int x = (int) mFabOrigin.getX();
    int y = (int) mFabOrigin.getY();
    ValueAnimator va1 = ValueAnimator.ofInt(x, x - ConstantUtil.FAN_OFFSET);
    va1.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int l = (int) animation.getAnimatedValue();
            int t = (int) mFabLeft.getY();
            int r = mFabLeft.getWidth() + l;
            int b = mFabLeft.getHeight() + t;
            mFabLeft.layout(l, t, r, b);
        }
    });

    // 按钮2向左上移动
    ValueAnimator va2x = ValueAnimator.ofInt(x, x - (int) (ConstantUtil.FAN_OFFSET / Math.pow(2, 1.0 / 2)));
    ValueAnimator va2y = ValueAnimator.ofInt(y, y - (int) (ConstantUtil.FAN_OFFSET / Math.pow(2, 1.0 / 2)));
    va2x.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int l = (int) animation.getAnimatedValue();
            int t = (int) mFabLeftTop.getY();
            int r = mFabLeftTop.getWidth() + l;
            int b = mFabLeftTop.getHeight() + t;
            mFabLeftTop.layout(l, t, r, b);
        }
    });
    va2y.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int l = (int) mFabLeftTop.getX();
            int t = (int) animation.getAnimatedValue();
            int r = mFabLeftTop.getWidth() + l;
            int b = mFabLeftTop.getHeight() + t;
            mFabLeftTop.layout(l, t, r, b);
        }
    });

    // 按钮3向上移动
    ValueAnimator va3 = ValueAnimator.ofInt(y, y - ConstantUtil.FAN_OFFSET);
    va3.setDuration(500).addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int l = (int) mFabTop.getX();
            int t = (int) animation.getAnimatedValue();
            int r = mFabTop.getWidth() + l;
            int b = mFabTop.getHeight() + t;
            mFabTop.layout(l, t, r, b);
        }
    });

    // 开始动画
    va1.start();
    va2x.start();
    va2y.start();
    va3.start();
}
  • 切换图标
    然后就是在不同状态切换悬浮按钮的图标, 使用setImageResource方法即可.
mFabAdd.setImageResource(mLineMenuOpen ? R.drawable.ic_add : R.drawable.ic_close);

最后

我本人还是很喜欢google的material design的, 这个悬浮按钮也非常实用. 喜欢记得点赞或者关注我哦, 有意见或者建议评论区见~

动画必须有(一): 属性动画浅谈
githhub传送门


你可能感兴趣的:(动画必须有(二):悬浮菜单了解一下!)