IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android列表单选点击缩放动画 -> 正文阅读

[移动开发]Android列表单选点击缩放动画

recycleView单选的时候,一般的处理就是选中的item做个stroke或者字体颜色改变,但要提升用户体验就得加点动画了。也就是点击选中的元素放大,同时之前选中的item缩小,不便截gif图,只能放一张静态图,大家脑补脑补~
在这里插入图片描述
图中的CheckBox,代码实现其实是imageview,它的选中、取消也是有动画的,不是控制visible,而是通过改变图片透明度来实现选中取消的。具体看代码:

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.view.View;
import android.widget.ImageView;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.xxx.Wallpaper;
import org.jetbrains.annotations.NotNull;
import java.util.List;

/**
 * Created by ly on 2021/4/22 14:11
 */
public class ManageHomeBgAdapter extends BaseSingleSelectAdapter<Wallpaper> {

    public ManageHomeBgAdapter(List<Wallpaper> mList) {
        super(R.layout.m_item_manage_home_bg, mList, false);
    }

    @Override
    protected void convert(@NotNull BaseViewHolder baseViewHolder, Wallpaper wallInfo) {
        super.convert(baseViewHolder, wallInfo);
        baseViewHolder.setText(R.id.m_tv_item_home_bg_name, wallInfo.name);

        ImageView ivBg = baseViewHolder.getView(R.id.m_iv_item_home_bg);
        GlideUtil.loadRound(getContext(), wallInfo.url, ivBg, PixelUtil.dp2px(8));

        View iv = baseViewHolder.getView(R.id.m_iv_item_home_bg_sel);
        int position = baseViewHolder.getAdapterPosition();
        if (wallInfo.isSelected) {
            //选中动画
            PropertyValuesHolder vb1 = PropertyValuesHolder.ofFloat(View.SCALE_X, 0.5f, 1.3f, 1f);
            PropertyValuesHolder vb2 = PropertyValuesHolder.ofFloat(View.SCALE_Y, 0.5f, 1.3f, 1f);
            PropertyValuesHolder vb3 = PropertyValuesHolder.ofFloat(View.ALPHA, 0.5f, 1f);
            ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(iv, vb1, vb2, vb3);
            objectAnimator.setDuration(duration).start();

            //背景选中放大动画(理论上可以使用ItemAnimator实现,但我们这里只针对图片缩放,而不是整个item,所以采用view的动画实现)
            ivBg.animate().scaleX(1f).scaleY(1f)
                    .withEndAction(() -> ivBg.animate().scaleX(1.05f).scaleY(1.05f).setDuration(duration))
                    .setDuration(0).start();
        } else {
            //此处只对上次选择的item执行动画
            if (getLastSelIndex() >= 0 && getLastSelIndex() == position) {
                ObjectAnimator.ofFloat(iv, "alpha", 1f, 0).setDuration(duration).start();

                //背景取消选中动画
                ivBg.animate().scaleX(1.05f).scaleY(1.05f)
                        .withEndAction(() -> ivBg.animate().scaleX(1f).scaleY(1f).setDuration(duration))
                        .setDuration(0).start();
            } else {
                iv.setAlpha(0);
            }
        }
    }
}

对应的item布局,注意,最好用padding来实现item之间的间隙,不然放大后可能由于空间不足导致itemView显示不全:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:paddingBottom="7dp"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/m_iv_item_home_bg"
        android:layout_width="match_parent"
        android:layout_height="@dimen/item_wallpaper_h"
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"
        android:paddingLeft="7dp"
        android:paddingRight="7dp"
        android:paddingTop="7dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:src="@mipmap/ic_mine_bg" />

    <ImageView
        android:id="@+id/m_iv_item_home_bg_sel"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:layout_marginBottom="10dp"
        android:alpha="0"
        app:layout_constraintBottom_toBottomOf="@+id/m_iv_item_home_bg"
        app:layout_constraintEnd_toEndOf="@+id/m_iv_item_home_bg"
        app:layout_constraintStart_toStartOf="@+id/m_iv_item_home_bg"
        android:src="@mipmap/ic_select_bg" />

    <TextView
        android:id="@+id/m_tv_item_home_bg_name"
        style="@style/text_second_s"
        android:paddingTop="9dp"
        app:layout_constraintEnd_toEndOf="@+id/m_iv_item_home_bg"
        app:layout_constraintStart_toStartOf="@+id/m_iv_item_home_bg"
        app:layout_constraintTop_toBottomOf="@+id/m_iv_item_home_bg"
        tools:text="壁纸1" />


</androidx.constraintlayout.widget.ConstraintLayout>

父类是我做的封装,方便其他地方用到,大家酌情参考一下:

import android.annotation.SuppressLint;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.core.view.ViewCompat;

import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.viewholder.BaseViewHolder;
import com.xxx.SelectableItem;

import org.jetbrains.annotations.Nullable;

import java.util.List;

/**
 * 单选通用baseAdapter
 * 需要注意的是要将recycleView的setItemAnimator设置为null,不然动画会冲突(错乱)
 * Created by ly on 2021/7/21 16:02
 */
public abstract class BaseSingleSelectAdapter<T extends SelectableItem> extends BaseQuickAdapter<T, BaseViewHolder> {
    private int selIndex = -1, lastSelIndex = -1;
    /**
     * 动画时长
     */
    protected int duration = 300;
    /**
     * 动画缩放因子
     */
    protected float factor = 0.05f;

    private boolean showItemAni = true;

    public BaseSingleSelectAdapter(int layoutResId) {
        super(layoutResId);
    }

    public BaseSingleSelectAdapter(int layoutResId, @Nullable List<T> data) {
        super(layoutResId, data);
    }

    public BaseSingleSelectAdapter(int layoutResId, @Nullable List<T> data, boolean showItemAni) {
        super(layoutResId, data);
        this.showItemAni = showItemAni;
    }

    /**
     * 子类需要调用该方法以获取准确的selIndex以及item动画展示
     * Created by ly on 2021/7/23 16:04
     */
    @Override
    protected void convert(@NonNull BaseViewHolder baseViewHolder, T t) {
        //选中动画
        if (t.isSelected) {
            selIndex = baseViewHolder.getAdapterPosition();
            if (showItemAni) scaleUp(baseViewHolder.itemView);
        } else {
            if (showItemAni) scaleDown(baseViewHolder.itemView);
        }
    }

    public @Nullable
    T selectOne(int index) {
        if (selIndex != index) {//不处理点击已选中的情况
            if (selIndex >= 0 && selIndex < getItemCount())
                getItem(selIndex).isSelected = false;
            if (index >= 0 && index < getItemCount()) {
                getItem(index).isSelected = true;
            }

            notifyItemChanged(selIndex);
            notifyItemChanged(index);

            lastSelIndex = selIndex;
            selIndex = index;
        }
        return getSelectItem();
    }

    @SuppressLint("NotifyDataSetChanged")
    public void selectNone() {
        if (selIndex >= 0 && selIndex < getData().size()) {
            getData().get(selIndex).isSelected = false;
            notifyItemChanged(selIndex);
        }else {
            for (T datum : getData()) {
                datum.isSelected = false;
            }
            notifyDataSetChanged();
        }
        selIndex = -1;
    }

    public @Nullable
    T getSelectItem() {
        return selIndex >= 0 && selIndex < getItemCount() ? getItem(selIndex) : null;
    }

    public int getSelectIndex() {
        return selIndex;
    }

    protected int getLastSelIndex() {
        return lastSelIndex;
    }

    protected void scaleUp(View view) {
        ViewCompat.animate(view)
                .setDuration(duration)
                .scaleX(1f + factor)
                .scaleY(1f + factor)
                .start();
    }

    protected void scaleDown(View view) {
        ViewCompat.animate(view)
                .setDuration(duration)
                .scaleX(1f)
                .scaleY(1f)
                .start();
    }
}

对应的选中通用实体类,用你自己的类继承SelectableItem即可:

/**
 * Created by ly on 2021/7/21 16:05
 */
public class SelectableItem {
    /**
     * 是否选中 true:选中
     */
    public boolean isSelected;

}

以上的BaseSingleSelectAdapter通用于列表单选场景,使用的时候继承即可,根据自己的业务来吧。

文中代码依赖第三方库:BaseRecyclerViewAdapterHelper,如果你用不到,用我贴的核心代码也能实现动效~

好啦,简单的选中动画就实现完成了,建议大家项目里面多用动画来提升用户体验。

谢谢观看~

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:45:30  更:2021-07-31 16:47:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/7 3:28:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码