首页 > 解决方案 > 创建回收站视图项目动画

问题描述

我正在尝试在回收站视图中创建动画。我正在寻找的那种动画是 Telegram android 应用程序中可用的那种。

当您在电报中打开聊天并长按消息时,recyclerview 多选选项带有复选框。我正在尝试创建相同的效果。

我现在的状态: 在此处输入图像描述

ListItemAdapter.kt

    class ListItemAdapter(private val values: List<PlaceholderContent.PlaceholderItem>
) : RecyclerView.Adapter<ListItemAdapter.ItemViewHolder>() {

    private lateinit var itemClick: OnItemClick
    private var selectedIndex: Int = -1
    private var selectedItems: SparseBooleanArray = SparseBooleanArray()
    private var isActive: Boolean = false

    fun setItemClick(itemClick: OnItemClick) {
        this.itemClick = itemClick
    }

    override fun onCreateViewHolder(
        parent: ViewGroup,
        viewType: Int
    ): ListItemAdapter.ItemViewHolder {
        val view = LayoutInflater.from(parent.context).inflate(
            R.layout.fragment_item,
            parent,
            false
        )
        return ItemViewHolder(view)
    }

    override fun onBindViewHolder(holder: ListItemAdapter.ItemViewHolder, position: Int) {
        holder.itemView.apply {
            findViewById<TextView>(R.id.item_number).text = values[position].id
            findViewById<TextView>(R.id.content).text = values[position].content
        }

        holder.itemView.setOnClickListener {
            itemClick.onItemClick(values[position], position)
        }

        holder.itemView.setOnLongClickListener {
            itemClick.onLongPress(values[position], position)
            true
        }
        toggleIcon(holder, position)
    }

    override fun getItemCount(): Int {
        return values.size
    }



    fun toggleIcon(holder: ItemViewHolder, position: Int){
        val checkBox = holder.itemView.findViewById<RadioButton>(R.id.is_selected)
        if(selectedItems.get(position, false)){
            checkBox.isGone = false
            checkBox.isChecked = true
        }
        else{
            checkBox.isGone = true
            checkBox.isChecked = false
        }
        if(isActive) checkBox.isGone = false
        if(selectedIndex == position) selectedIndex = - 1
    }

    fun selectedItemCount() = selectedItems.size()

    fun toggleSelection(position: Int){

        selectedIndex = position
        if (selectedItems.get(position, false)){
            selectedItems.delete(position)
        }else {
            selectedItems.put(position, true)
        }
        notifyItemChanged(position)

        isActive = selectedItems.isNotEmpty()
        notifyDataSetChanged()
    }

    fun clearSelection(){
        selectedItems.clear()
        notifyDataSetChanged()
    }

    interface OnItemClick {
        fun onItemClick(item: PlaceholderContent.PlaceholderItem, position: Int)
        fun onLongPress(item: PlaceholderContent.PlaceholderItem, position: Int)
    }

    inner class ItemViewHolder(itemView: View): RecyclerView.ViewHolder(itemView){
    }

}

片段项目.xml

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:id="@+id/list_item"
    >
    <RadioButton
        android:id="@+id/is_selected"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="gone"
        android:layout_margin="16dp"
        />

    <TextView
        android:id="@+id/item_number"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem" />

    <TextView
        android:id="@+id/content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/text_margin"
        android:textAppearance="?attr/textAppearanceListItem" />


</LinearLayout>

MainActivity.kt

    adapter = ListItemAdapter(PlaceholderContent.ITEMS)
    val recyclerViewList = view.findViewById<RecyclerView>(R.id.list)
    recyclerViewList.adapter = adapter
    recyclerViewList.layoutManager = LinearLayoutManager(view.context, LinearLayoutManager.VERTICAL, false)
    val myHelper = ItemTouchHelper(myCallback)
    myHelper.attachToRecyclerView(recyclerViewList)

    adapter.setItemClick(object : ListItemAdapter.OnItemClick{
        override fun onItemClick(
            item: PlaceholderContent.PlaceholderItem,
            position: Int
        ) {
            if(adapter.selectedItemCount() > 0)
                toggleSelection(position)
        }

        override fun onLongPress(
            item: PlaceholderContent.PlaceholderItem,
            position: Int
        ) {
            toggleSelection(position)
        }

    })


    return view
}

private fun toggleSelection(position: Int){
    adapter.toggleSelection(position)
}

标签: androidkotlinandroid-animation

解决方案


要添加动画过渡,最简单的方法是添加

animateLayoutChanges="true"

到单个项目根(因为那是您希望它动画的地方),在您的情况下是:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/list_item"
animateLayoutChanges="true" <!-- Around here -->
>
    ...
</LinearLayout>

要让它看起来与电报中的完全一样,您需要从一些不同的设计开始,但这是另一个问题(并且在某种程度上是坚持不懈的问题:P);

此外,如果您想要不同类型的动画,则需要以不同的方式进行处理,您可以通过向视图添加动画来实现:( alpha 通常从 0f 变为 1f((不可见-可见)) ,如果需要,您需要将视图可见性参数更改为可见/不可见/消失,以便它不会根据您的需要在该区域注册点击事件.无论如何,这应该是试错你想要的行为)

is_selected.animate().alpha(1f).setInterpolator(AccelerateDecelerateInterpolator())
is_selected.visibility = View.VISIBLE

您还可以阅读一些关于可用的 android interpolators 的内容,因为我们不能确定它们是否会删除一些(不太可能)/添加新的。


推荐阅读