【笔记】简单实现可向周围展开的菜单容器

前些天在谷歌开发者公众号上看到一篇文章——取舍的艺术:Evernote

其中有说道一个效果,在悬浮按钮上应用快捷指令的设置,点击展开后呈现六种不同的记录笔记的方式,结合菜单展开时的动画效果,让人眼前一亮。



大致思考了一下,可以将这样的菜单分为两部分,一部分是一直显示着的悬浮按钮,另一部分是带有动画效果可以展开消失的菜单部分。

LinearLayout的线性布局显然很适合,可以设置横向或纵向,再配上简单的动画效果,确实可以实现这种展开菜单的效果。


定义一个菜单容器,用于放置展开后需要呈现的菜单列表。最外面是菜单容器,里面是四个悬浮按钮作为菜单项。

    <com.sjl.expandmenu.view.ExpandMenu
        android:id="@+id/expandMenu4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        app:menuDrawable="@drawable/ic_open_close"
        app:menuGravity="TOP">

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/menu41"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/iv_previous_white" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/menu42"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/iv_play_white" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/menu43"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/iv_next_white" />

        <android.support.design.widget.FloatingActionButton
            android:id="@+id/menu44"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/iv_stop_white" />
    </com.sjl.expandmenu.view.ExpandMenu>


初始化菜单

主要分为几个步骤:

1、将菜单容器中的菜单加入list列表中,之后移除这些菜单(之后的显示和取消都是从list中动态添加删除);

2、初始化要一直显示的悬浮按钮和之后菜单显示的容器;

3、根据菜单要显示的位置,添加悬浮按钮和菜单容器(右边和下边就先添加悬浮按钮,反之先添加菜单容器);

4、添加按钮点击事件;

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        //布局加载后初始化菜单
        initMenuList();
    }

    /**
     * 初始化菜单列表
     */
    private void initMenuList() {
        menuList = new ArrayList<>();
        for (int i = 0; i < getChildCount(); i++) {
            //将菜单添加进菜单列表
            View childView = getChildAt(i);
            childView.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (onMenuItemClickListener != null) {
                        onMenuItemClickListener.onClick(v);
                    }
                }
            });
            menuList.add(childView);
        }
        removeAllViews();
        //初始化菜单容器
        menuLayout = new LinearLayout(getContext());
        menuLayout.setOrientation(getOrientation());
        //初始化展开按钮
        floatingActionButton = new FloatingActionButton(getContext());
        if (menuDrawable != null) {
            floatingActionButton.setImageDrawable(menuDrawable);
        }
        if (menuBackground != null) {
            floatingActionButton.setBackgroundDrawable(menuBackground);
        }
        //根据位置添加菜单
        if (menuGravity == TOP || menuGravity == LEFT) {
            addView(menuLayout);
            addView(floatingActionButton);
        } else {
            addView(floatingActionButton);
            addView(menuLayout);
        }
        //设置菜单容器透明
        ViewCompat.setAlpha(menuLayout, 0);

        floatingActionButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //切换菜单状态
                toggle();
            }
        });
    }


菜单状态切换动画

菜单展开需要先将列表中的菜单项添加到布局中,再一一显示菜单。

    /**
     * 添加菜单项
     */
    private void addMenuItems() {
        //设置菜单容器不透明
        ViewCompat.setAlpha(menuLayout, 1f);
        for (View view : menuList) {
            menuLayout.addView(view);
        }
    }

菜单显示动画
    /**
     * 单个菜单进入动画
     *
     * @param view
     * @param index 第几个显示的菜单,可根据该值设置启动延迟
     */
    private void animateInMenuItem(View view, int index) {
        //设置开始状态
        ViewCompat.setScaleX(view, 0.25f);
        ViewCompat.setScaleY(view, 0.25f);
        //设置菜单透明是为了在延迟结束前都不可见菜单
        ViewCompat.setAlpha(view, 0);

        //进入动画
        ViewCompat.animate(view)
                .setDuration(duration * 4)
                .scaleX(1f)
                .scaleY(1f)
                .alpha(1f)
                .setStartDelay(duration * index)//动画启动延迟
                .setInterpolator(new FastOutSlowInInterpolator())
                .setListener(new ViewPropertyAnimatorListenerAdapter() {
                    @Override
                    public void onAnimationStart(View view) {
                        super.onAnimationStart(view);
                        //动画开始时,设置不透明
                        ViewCompat.setAlpha(view, 1f);
                        isAnimating = true;
                    }

                    @Override
                    public void onAnimationEnd(View view) {
                        super.onAnimationEnd(view);
                        isAnimating = false;
                    }
                })
                .start();
    }

效果



下载源码



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值