Android列表实现单选点击缩放动画效果

recycleView单选的时候,一般的处理就是选中的item做个stroke或者字体颜色改变,但要提升用户体验就得加点动画了。也就是点击选中的元素放大,同时之前选中的item缩小,不便截gif图,只能放一张静态图,大家脑补脑补~

Android列表实现单选点击缩放动画效果_第1张图片

图中的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 {

    public ManageHomeBgAdapter(List 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显示不全:




    

    

    



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

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 extends BaseQuickAdapter {
    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 data) {
        super(layoutResId, data);
    }

    public BaseSingleSelectAdapter(int layoutResId, @Nullable List 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,如果你用不到,用我贴的核心代码也能实现动效~

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

总结

到此这篇关于Android列表实现单选点击缩放动画效果的文章就介绍到这了,更多相关Android列表点击缩放内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

你可能感兴趣的:(Android列表实现单选点击缩放动画效果)