Android : 使用 kotlin 的可点击图像水平滑块

Android : clickable Image horizontal slider using kotlin

我想添加水平图像滚动条,如下图所示。我知道有解决方案,但所有解决方案都有 4 到 5 年的历史,在 Kotlin 和约束布局之后,我假设现在有一些好的方法可以实现这一目标。请帮助我并分享最好和最简单的方法来做到这一点。提前致谢。

并非专门针对 RecyclerViews,但您可以使用一些不错的 Kotlin 语言功能。

我个人不会使用约束布局,而是使用 RecyclerView. Kotlin offers a couple of nice options for working with collections so its worth using those if you need to do any manipulation. I would advice you to not make the list available as mutable outside the adapter. This can be achieved with the use of backing properties

至于让它们可点击,您可以使用 OnItemTouchListener。但是我个人更喜欢使用 OnClickListener 和回调。回调属于适配器,OnClickListener 被添加到视图持有者的根视图。

除此之外,您还可以使用各种不错的技巧,例如 typealias

这是我可以快速想出的代码(我没有用 recyclerviews 完成任何非测试应用程序工作,所以没有正确设计的示例可以借鉴):

class ImageListAdapter : RecyclerView.Adapter<ImageListAdapter.ImageListItemVH>() {
    private val _items = mutableListOf<ImageItem>()
    val items: List<ImageItem>
        get() = _items

    var clickCallback: ImageClickCallback? = null

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageListItemVH {
        val itemView = LayoutInflater.from(parent.context)
            .inflate(
                R.layout.viewholder_image_list_item,
                parent,
                false
            )
        return ImageListItemVH(itemView)
    }

    override fun getItemCount(): Int = _items.size

    override fun onBindViewHolder(holder: ImageListItemVH, position: Int) {
        holder.bind(_items[position]) { clickCallback?.invoke(it) }
    }

    fun addItem(newItem: ImageItem) {
        _items += newItem
        notifyItemInserted(_items.size - 1)
    }

    fun addItems(newItems: List<ImageItem>) {
        val sizeBefore = _items.size
        _items += newItems
        notifyItemRangeInserted(sizeBefore - 1, newItems.size)
    }

    fun clearItems() {
        val sizeBefore = _items.size
        _items.clear()
        notifyItemRangeRemoved(0, sizeBefore - 1)
    }

    fun setItems(items: List<ImageItem>) {
        _items.clear()
        _items += items
        notifyDataSetChanged()
    }

    class ImageListItemVH(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bind(imageItem: ImageItem, callback: (id: String) -> Unit) =
            itemView.setOnClickListener { callback(imageItem.id) }
    }
}

data class ImageItem(
    val id: String,
    val location: String
)

typealias ImageClickCallback = (id: String) -> Unit

如果图片集很大或不限于少量静态项目,您应该使用 paging library, specifically in this case the PagedList

创建项目:

<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginBottom="16dp"
    android:background="@color/colorAccent"
    card_view:cardCornerRadius="8dp"
    card_view:cardUseCompatPadding="true">

    <LinearLayout
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:orientation="vertical">

        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="150dp"
            android:scaleType="centerCrop"
            android:src="@mipmap/ic_launcher_round" />

        <androidx.appcompat.widget.AppCompatTextView
            android:id="@+id/tvName"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:gravity="center_horizontal"
            android:padding="8dp"
            android:text="@string/app_name"
            android:textColor="#000000"
            android:textSize="16sp" />

    </LinearLayout>

</androidx.cardview.widget.CardView>

然后将此项目添加到您的 RecyclerView:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="@color/colorPrimary" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" />

</LinearLayout>

然后从您的 Activity 调用它并为它设置一个 HORIZONTAL LayoutManager 然后它的适配器:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        displayList()
    }

    private fun displayList() {
        val imageList = ArrayList<ImageDataModel>()
        imageList.clear()
        imageList.add(ImageDataModel("https://conversionxl.com/wp-content/uploads/2018/09/coding-language.jpg", "Test"))
        imageList.add(ImageDataModel("https://makeawebsitehub.com/wp-content/uploads/2016/02/learn-code-e1455713167295.jpg", "Test"))
        imageList.add(ImageDataModel("https://www.tecmint.com/wp-content/uploads/2016/11/Convert-PNG-to-JPG-Using-for-loop-Command.png", "Test"))
        imageList.add(ImageDataModel("https://conversionxl.com/wp-content/uploads/2018/09/coding-language.jpg", "Test"))
        imageList.add(ImageDataModel("https://www.tecmint.com/wp-content/uploads/2016/11/Convert-PNG-to-JPG-Using-for-loop-Command.png", "Test"))
        recyclerView.layoutManager = LinearLayoutManager(this, LinearLayout.HORIZONTAL, false)
        recyclerView.adapter = ViewAdapter(imageList)
    }
}

如您所见,RecyclerView 也需要一个适配器,它是一个简单的适配器,使用 Glide 来显示如下图像:

class ViewAdapter(private val imageDataModelList: ArrayList<ImageDataModel>) : RecyclerView.Adapter<ViewAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(LayoutInflater.from(parent.context).inflate(R.layout.item_list, parent, false))
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bindItems(imageDataModelList[position])
    }

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

    class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        fun bindItems(imageDataModel: ImageDataModel) {
            val textView = itemView.findViewById<TextView>(R.id.tvName)
            val imageView = itemView.findViewById<ImageView>(R.id.imageView)
            textView.text = imageDataModel.name

            Glide.with(itemView.context).load(imageDataModel.url).into(imageView)
        }
    }
}

别忘了在你的应用级别添加 Glide 的依赖项 build.gradle:

dependencies {
  implementation 'com.github.bumptech.glide:glide:4.10.0'
  annotationProcessor 'com.github.bumptech.glide:compiler:4.10.0'
}

该应用程序应如下所示: https://imgur.com/WFSnKyz