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

3,522 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第29天,点击查看活动详情

👉关于作者

众所周知,人生是一个漫长的流程,不断克服困难,不断反思前进的过程。在这个过程中会产生很多对于人生的质疑和思考,于是我决定将自己的思考,经验和故事全部分享出来,以此寻找共鸣!!!

专注于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>

😜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();
        }
    }
}

从代码中可看出也就用到了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()
        }
    }
}

布局中直接使用即可

<?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>
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()
            }
        }
}

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

📢作者:小空和小芝中的小空

📢转载说明-务必注明来源:芝麻粒儿 的个人主页 - 专栏 - 掘金 (juejin.cn)

📢这位道友请留步☁️,我观你气度不凡,谈吐间隐隐有王者霸气💚,日后定有一番大作为📝!!!旁边有点赞👍收藏🌟今日传你,点了吧,未来你成功☀️,我分文不取,若不成功⚡️,也好回来找我。