▲ Android 自定义可收缩的菜单

▲ Android 自定义可收缩的菜单

先给各位大爷们看一下 我要实现的效果 =_=!
这里写图片描述

大家肯定会说这有什么难的?so easy 这不就是弄个渐变缩放动画 来显示固定好的 5个按钮嘛。

但是我这里要说的是通过计算来实现这个效果,很6的做法

实现原理
先根据圆的半径来定位每一张图片的位置

然后大家可以清晰的看出
X轴的移动距离 = radius sin(a)
Y轴的移动距离 = radius
cos(a) ————- radius 是半径,a是夹角的度数

这里写图片描述

实现过程
【1】先要确定这个a是多少度?
菜单的夹角和是90°,共有5个菜单项,相当于把90°分为4等份。一个夹角的度数大约是22° (90/4=22)
然后第一个菜单的夹角是0°,第二个菜单的夹角是22° 第三个菜单的夹角是(222)° ,第四个菜单的夹角是 (223)°,第五个菜单的夹角是(22*4)°

假设index表示当前位置的索引,从0开始,第一个索引就是0,第二个就是1… 所以当前菜单与Y轴之间的夹角就是(22*index)°

【2】如何计算对应的正弦值,余弦值?

这几个可以放心,因为Java中有个一Math类,该类有三个函数已经帮咱们处理好了

//对应弧度的正弦值
double sin (double d)

//对应弧度的余弦值
double cos (double d)

//对应弧度的正切值
double tan(double d)

**注意一点啊,这个三个函数输入的参数不是度数,而是度数对应的弧度值 **

啥叫弧度值? 如图↓ 画的太low =_=!
这里写图片描述

获取弧度有2中方法

第一种呢,Math类中Math.PI不仅代表圆周率π,也代表180°所对应的弧度值,所以Math.sin(Math.PI)就是180°的正弦值,/2就是90°的正玄值了。

第二种就是 根据度数来获取弧度值,Math中提供了一个函数

double toReadians(double angdeg)

代码实现

XML布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginBottom="10dp"
        android:layout_marginRight="10dp">

        <Button
            android:id="@+id/item1"
            android:layout_width="43dp"
            android:layout_height="43dp"
            android:layout_gravity="bottom|right"
            android:background="@mipmap/ice"
            android:visibility="gone" />
        <Button
            android:id="@+id/item2"
            android:layout_width="43dp"
            android:layout_height="43dp"
            android:layout_gravity="bottom|right"
            android:background="@mipmap/icb"
            android:visibility="gone" />

        <Button
            android:id="@+id/item3"
            android:layout_width="43dp"
            android:layout_height="43dp"
            android:layout_gravity="bottom|right"
            android:background="@mipmap/icc"
            android:visibility="gone" />

        <Button
            android:id="@+id/item4"
            android:layout_width="43dp"
            android:layout_height="43dp"
            android:layout_gravity="bottom|right"
            android:background="@mipmap/icd"
            android:visibility="gone" />

        <Button
            android:id="@+id/item5"
            android:layout_width="43dp"
            android:layout_height="43dp"
            android:layout_gravity="bottom|right"
            android:background="@mipmap/icf"
            android:visibility="gone" />


        <Button
            android:id="@+id/menu"
            android:layout_width="55dp"
            android:layout_height="55dp"
            android:layout_gravity="bottom|right"
            android:background="@mipmap/ica" />
    </FrameLayout>
</LinearLayout>

java代码 实现

  @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_animation_b);
        Button menu = findViewById(R.id.menu);
        item1 = findViewById(R.id.item1);
        item2 = findViewById(R.id.item2);
        item3 = findViewById(R.id.item3);
        item4 = findViewById(R.id.item4);
        item5 = findViewById(R.id.item5);
        menu.setOnClickListener(this);
        item1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this,"第一个条目",Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.menu:
                if (!mIsMenuOpen) {
                    mIsMenuOpen = true;
                    oPenMenu();
                } else {
                    mIsMenuOpen = false;
                    closeMenu();
                }
                break;
        }
    }

    private void oPenMenu() {
        doAnimateOpen(item1, 0, 5, 300);
        doAnimateOpen(item2, 1, 5, 300);
        doAnimateOpen(item3, 2, 5, 300);
        doAnimateOpen(item4, 3, 5, 300);
        doAnimateOpen(item5, 4, 5, 300);
    }

    private void doAnimateOpen(View view, int index, int total, int radius) {
        if (view.getVisibility() != View.VISIBLE) {
            view.setVisibility(View.VISIBLE);
        }
        double degree = Math.toRadians(90) / (total - 1) * index;
        int translationX = -(int) (radius * Math.sin(degree));
        int translationY = -(int) (radius * Math.cos(degree));
        AnimatorSet set = new AnimatorSet();
        //包括平移 缩放 透明 动画
        set.playTogether(ObjectAnimator.ofFloat(view, "translationX", 0, translationX),
                ObjectAnimator.ofFloat(view, "translationY", 0, translationY),
                ObjectAnimator.ofFloat(view, "scaleX", 0f, 1f),
                ObjectAnimator.ofFloat(view, "scaleY", 0f, 1f),
                ObjectAnimator.ofFloat(view, "alpha", 0f, 1f));
        set.setDuration(800).start();
    }

    private void closeMenu() {
        doAnimateClose(item1,0,5,300);
        doAnimateClose(item2,1,5,300);
        doAnimateClose(item3,2,5,300);
        doAnimateClose(item4,3,5,300);
        doAnimateClose(item5,4,5,300);
    }

    private void doAnimateClose(View view, int index, int total, int radius) {
        if (view.getVisibility()!=View.VISIBLE){
            view.setVisibility(View.VISIBLE);
        }
        double degree = Math.PI * index / ((total - 1) * 2);
        int translationX = -(int)(radius*Math.sin(degree));
        int translationY = -(int)(radius*Math.cos(degree));
        AnimatorSet set = new AnimatorSet();
        //包括平移 缩放 透明 动画
        set.playTogether(ObjectAnimator.ofFloat(view, "translationX", translationX,0),
                ObjectAnimator.ofFloat(view, "translationY", translationY,0),
                ObjectAnimator.ofFloat(view, "scaleX", 1f, 0.1f),
                ObjectAnimator.ofFloat(view, "scaleY", 1f, 0.1f),
                ObjectAnimator.ofFloat(view, "alpha", 1f, 0f));
        set.setDuration(800).start();
    }

最后是源码地址 https://download.csdn.net/download/macaopark/10658331

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/2844.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mysql批量插入大量数据「建议收藏」

    mysql批量插入大量数据「建议收藏」mysql批量插入大量数据时间:2020年11月25日今天遇到了一个批量插入大量数据任务,然后出于小白本能,直接for-each循环插入不就好了,于是手上开始噼里啪啦一顿操作,写好了从读取excel到插入数据库的工作,于是就美滋滋的开始了自己的测试,试了一把,一次通过perfect,然后后面就悲剧了,后面发现数据量稍微大一点,速度就会很慢很慢。于是掏出自己的制胜法典,后来我在知识和海洋中获取到了两种靠谱的方法。下面一点一点讲。测试的服务器信息1核2g5m的阿里云服务器(你懂得),mysql直接装

    2022年10月5日
    2
  • android之OkHttpClient通信「建议收藏」

    android之OkHttpClient通信OkHttpClient用法1:自定义缓存OkHttpClienthttpclient=newOkHttpClient.Builder().cache(newCache(newFile("cacheDirectory"),newLong(10*1024*1024))).build();用法2:当…

    2022年4月17日
    313
  • vue怎么和后端对接_vue搭配什么后端

    vue怎么和后端对接_vue搭配什么后端简单分享一下jeeplus框架部署liunx服务器跨域问题 ,因为我这个是前后端服务器分离所以配置了俩份java后端配置1.跨域后端配置nginx(图-1)上配置 server { listen 80; server_name xxx.xx.xxx; #后端服务域名 #charset koi8-r; #access_log logs/host.access.log main; locatio

    2022年8月19日
    8
  • uniapp 全局数据(globalData)的设置,获取,更改

    uniapp 全局数据(globalData)的设置,获取,更改因为 uniapp 基本上都是将页面 或者页面中相同的部分 进行组件化 所以会存在父 子 子 父 之间的传值的情况 但在某些情况下 可以选择将内容设置为一个全局的变量 并根据需求来进行内容的更新 大大减少了代码的使用 和传值可能遇到的各种复制的计算等等的情况下面来看看如何设置将一个变量设置为全局变量

    2025年7月13日
    4
  • pycharm使用技巧及常用快捷键_pycharm快捷键大全图

    pycharm使用技巧及常用快捷键_pycharm快捷键大全图Pycharm常用快捷键1、编辑(Editing)Ctrl+Space基本的代码完成(类、方法、属性)Ctrl+Alt+Space快速导入任意类Ctrl+Shift+Enter语句完成Ctrl+P参数信息(在方法中调用参数)Ctrl+Q快速查看文档F1外部文档Shift+F1外部文档,进入web文档主页Ctrl+Shift+Z–>Redo重做Ctrl+鼠标简介/进入代码定义Ctrl+F1显示错误描述或警告.

    2022年8月26日
    5
  • MT4安卓版下载安装

    MT4安卓版下载安装投资者安卓手机可以使用MT4软件吗?答案是:当然可以。MT4软件作为投资者通用的交易软件mt4.M1.xinclo.xyz涵盖了多个版本,电脑版MT4、手机版(包含IOS和安卓)MT4、MAC版MT4。如果是安卓手机,下载和安装安卓版的即可。安卓手机是无法在应用商店搜索到MT4的,因此大多都在网页上先获取安装包。下载交易软件,该软件商店中的移动终端。点击安装,软件会存储在手机桌面上,主界面上会显示MT4交易系统软件。…

    2022年8月15日
    7

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号