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
我想添加水平图像滚动条,如下图所示。我知道有解决方案,但所有解决方案都有 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