Android列表实现单选点击缩放动画效果
时间:2022-04-28 09:08:31|栏目: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,如果你用不到,用我贴的核心代码也能实现动效~
好啦,简单的选中动画就实现完成了,建议大家项目里面多用动画来提升用户体验。
总结
栏 目:Android代码
本文地址:http://www.codeinn.net/misctech/200447.html