• Android案例手册 - 实现下多个按钮展开收缩动画工具类


    往期文章分享

    本文约7.2千字,新手阅读需要12分钟,复习需要3分钟收藏随时查阅不再迷路

    👉关于作者

    众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣 !!!
    专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材、源码、游戏等)
    有什么需要欢迎私我,交流群让学习不再孤单

    在这里插入图片描述

    👉前提

    这是小空坚持写的Android新手向系列,欢迎品尝。

    大佬(√)

    新手(√√√)

    👉实践过程

    今日实现一个小效果,自定义ViewGroup实现展开动画。先看效果图

    动画-多个按钮伸缩和立体效果1.gif

    我们从效果图中可以看到,动画有两种,其一是从上到下形式的展开动画,其二是从下到上形式的收缩动画。而且从图中我们也可知使用的是Y轴的移动动画(如果想要x轴同样的实现原理)。而且仔细看,按钮三在最低层,按钮二在中间,按钮一在最上层,这也符合现实逻辑。

    首先我们创建个自定义ViewGroup,然后添加对应布局。本来想着封装好一些,以外部添加View的形式来做的,想想还是算了,本身就是个小思路记录就不那么“复杂”了。

    image.png

    自定义ViewGroup的布局xml,添加进三个测试按钮

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerHorizontal="true"> 
        <Button
            android:id="@+id/viewBtn3"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="@drawable/plxz_btn_n"
            android:text="3"
            android:textSize="16dp" />
        <Button
            android:id="@+id/viewBtn2"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="@drawable/plxz_btn_n"
            android:text="2"
            android:textSize="16dp" />
        <Button
            android:id="@+id/viewBtn1"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:background="@drawable/plxz_btn_n"
            android:text="1"
            android:textSize="16dp" />
    </RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    😜Java版FloatPullDownViewJava

    /**
     * @author akitaka
     * @filename FloatPullDownView
     * @describe 具有动画下滑的view    可封装  暂时为普通的自定义
     * @email 960576866@qq.com
     */
    public class FloatPullDownViewJava extends RelativeLayout implements View.OnClickListener {
        private Context mContext;
        private List<Button> viewList = new ArrayList<>();
        //间隔距离
        private int spaceNumber = 130;
    
        public FloatPullDownViewJava(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            View root = LayoutInflater.from(context).inflate(R.layout.view_pulldown, this);
            ViewPulldownBinding viewPulldownBinding = ViewPulldownBinding.bind(root);
            viewPulldownBinding.viewBtn3.setOnClickListener(this);
            viewPulldownBinding.viewBtn2.setOnClickListener(this);
            viewPulldownBinding.viewBtn1.setOnClickListener(this);
            viewList.add(viewPulldownBinding.viewBtn3);
            viewList.add(viewPulldownBinding.viewBtn2);
            viewList.add(viewPulldownBinding.viewBtn1);
        }
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.viewBtn3:
                    Toast.makeText(mContext, "点击了按钮3", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.viewBtn2:
                    Toast.makeText(mContext, "点击了按钮2", Toast.LENGTH_SHORT).show();
                    break;
                case R.id.viewBtn1:
                    Toast.makeText(mContext, "点击了按钮1", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
        /**
         * 菜单展开动画
         */
        public void startAnim() {
            for (int i = 1; i < viewList.size(); i++) {
                ObjectAnimator anim = ObjectAnimator.ofFloat(viewList.get(i), "translationY", 0F, i * spaceNumber);
                anim.setDuration(300);   //持续时间
                anim.setStartDelay(100);  //延迟多少开始
                anim.setInterpolator(new BounceInterpolator());
                anim.start();
            }
        }
        /**
         * 关闭动画
         */
        public void closeAnim() {
            for (int i = 1; i < viewList.size(); i++) {
                ObjectAnimator anim = ObjectAnimator.ofFloat(viewList.get(i), "translationY", i * spaceNumber, 0F);
                anim.setDuration(300);
                anim.setStartDelay(100);
                anim.setInterpolator(new DecelerateInterpolator());
                anim.start();
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65

    从代码中可看出也就用到了ObjectAnimator的动画知识,对View进行translationY位移动画(如果是x轴则为translationX),设置好动画时间和延迟时间,开始动画是从0移动到阶梯指定位置,结束动画是从阶梯指定位置回归到0。

    😜Kotlin版FloatPullDownViewKotlin

    /**
     * Created by akitaka on 2022-06-23.
     * @author akitaka
     * @filename FloatPullDownView
     * @describe
     * @email 960576866@qq.com
     */
    class FloatPullDownViewKotlin : RelativeLayout, View.OnClickListener {
        constructor(context: Context?) : this(context, null)
        constructor(context: Context?, attrs: AttributeSet?) : this(context, attrs, 0)
        constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
        private var mContext: Context? = null
        private val viewList: MutableList<Button> = ArrayList()
        //间隔距离
        private val spaceNumbew = 130
     
        init {
            mContext = context
            LayoutInflater.from(context).inflate(R.layout.view_pulldown, this)
            viewBtn3.setOnClickListener(this)
            viewBtn2.setOnClickListener(this)
            viewBtn1.setOnClickListener(this)
            viewList.add(viewBtn3)
            viewList.add(viewBtn2)
            viewList.add(viewBtn1)
        }
        override fun onClick(v: View) {
            when (v.id) {
                R.id.viewBtn3 -> Toast.makeText(mContext, "点击了按钮3", Toast.LENGTH_SHORT).show()
                R.id.viewBtn2 -> Toast.makeText(mContext, "点击了按钮2", Toast.LENGTH_SHORT).show()
                R.id.viewBtn1 -> Toast.makeText(mContext, "点击了按钮1", Toast.LENGTH_SHORT).show()
                else -> {}
            }
        }
        /**
         * 菜单展开动画
         */
        fun startAnim() {
            for (i in viewList.indices) {
                val anim = ObjectAnimator.ofFloat(viewList[i], "translationY", 0f, (i * spaceNumbew).toFloat())
                anim.duration = 300 //持续时间
                anim.startDelay = 100 //延迟多少开始
                anim.interpolator = BounceInterpolator()
                anim.start()
            }
        }
        /**
         * 关闭动画
         */
        fun closeAnim() {
            for (i in viewList.indices) {
                val anim = ObjectAnimator.ofFloat(viewList[i], "translationY", (i * spaceNumbew).toFloat(), 0f)
                anim.duration = 300
                anim.startDelay = 100
                anim.interpolator = DecelerateInterpolator()
                anim.start()
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    布局中直接使用即可

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <Button
            android:id="@+id/btnAnim"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="点击展开收缩动画" />
        <cn.appstudy.customView.FloatPullDownViewJava
            android:id="@+id/testFloatPullDownView"
            android:layout_width="match_parent"
            android:layout_marginTop="60dp"
            android:layout_height="match_parent" />
    </RelativeLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    class TempActivity : AppCompatActivity() {
        var isOpenAnim: Boolean = false
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_test)
            btnAnim.setOnClickListener {
                if (isOpenAnim) {
                    isOpenAnim = false
                    testFloatPullDownView.closeAnim()
                } else {
                    isOpenAnim = true
                    testFloatPullDownView.startAnim()
                }
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    试验一下,点击,效果如开头效果图一样。

    👉其他

    📢作者:小空和小芝中的小空
    📢转载说明-务必注明来源:https://zhima.blog.csdn.net/
    📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。

    温馨提示点击下方卡片获取更多意想不到的资源。
    空名先生

  • 相关阅读:
    游戏专用....
    零宽空格引发的问题
    NB6L295M STM32 GD32 IO模拟驱动设计
    Nginx学习记录一揽子:学会配置Nginx
    $nextTick 的原理源码解读
    【RocketMQ 一】MQ概述
    由C# dynamic是否装箱引发的思考
    赚钱软件应该怎么选择?你应该知道的副业兼职赚钱软件
    [axios]使用指南
    Java多线程的面试题
  • 原文地址:https://blog.csdn.net/qq_27489007/article/details/125436226