【问题标题】:Android : clickable Image horizontal slider using kotlinAndroid:使用 kotlin 的可点击图像水平滑块
【发布时间】:2020-01-31 14:33:15
【问题描述】:

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

【问题讨论】:

  • 你试过使用 Horizo​​ntalScrollView 吗?
  • stackoverflow.com/questions/29429556/…我正在尝试使用这种方法(答案1),但我不知道如何在循环中添加不同的图像
  • 您应该使用水平 RecyclerView 并将 lambda 作为点击侦听器传递
  • @SFAH 好的,我正在为您实施一个带有多张图片的图片,并在短时间内发布作为答案。

标签: android kotlin imageview android-constraintlayout horizontal-scrolling


【解决方案1】:

创建一个项目:

<?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 也需要一个 Adapter,它是一个简单的 Adapter,它使用 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)
        }
    }
}

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

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

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

【讨论】:

  • 你在哪里定义了'recylerView'?
  • @SFAH inside MainActivity in the method displayList(), 因为它在 Kotlin 我不需要像在 Java 中那样初始化,这个类可以访问布局 activity_main 的 id recyclerView直接。
  • 在以下官方文档和示例中通过导入 Kotlin Synthetics 了解我如何使用 Kotlin 扩展:kotlinlang.org/docs/tutorials/android-plugin.html
  • 还有一个问题,imageDataModelList 是什么?我不能用它..
  • 好的,继续,没问题,我是来帮忙的。在MainActivity,在displayList() 里面,我有一个val imageList = ArrayList&lt;ImageDataModel&gt;()。然后我在这一行将这个ArrayList&lt;ImageDataModel&gt;() 传递给适配器:recyclerView.adapter = ViewAdapter(imageList)
【解决方案2】:

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

我个人不会使用约束布局而是使用RecyclerView。 Kotlin 为使用 collections 提供了几个不错的选项,因此如果您需要进行任何操作,则值得使用这些选项。我建议您不要使列表在适配器之外作为可变的可用。这可以通过使用backing properties 来实现。

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

除此之外,您还可以使用各种不错的技巧,例如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,特别是在这种情况下PagedList

【讨论】:

    猜你喜欢
    • 2015-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多