I haven’t published in a year, and I switched from Java to Kotlin. I’ve been working on a lot of stuff lately, but I’ll update it later, or can the code bring people joy and affection
1. The rendering
2. Implementation idea
Final Goal:
- When there is no data, the plus layout is displayed, the plus layout is hidden when the image reaches the maximum value, and the plus layout is displayed again when an image is deleted
The picture selection frame used inside is Zhihu Matisse, picture loading is Glide, permission application is Permissionx, the specific use will not be detailed, if there is a need for a separate article in the future.
Here mainly talk about the picture after recyclerview plus layout display and hide, here used recyclerView multi-layout realization
The general steps of implementation:
-
(1) Rewrite the getItemCount() method of the Adapter and return data.size+1.
-
(2) Rewrite the getItemViewType() method to return the plus sign layout if position+1=getItemCount(), otherwise return the image layout. Use recyclerView multi-layout, to achieve plus layout and picture layout switch.
Implementation principle: Because position counts from 0 and getItemCount() counts from 1 because we return data.size+1. When data has no data, position is 0 and getItemCount() is 1. Position +1=getItemCount() When data has data, getItemCount() is 3, position is 0,1, the layout is displayed, and position is 2, because 2+1=3, the layout is displayed
-
(3) Rewrite onBindViewHolder() to determine data.size when the holder is a plus holder. If it is >= the maximum value, holder.itemView is set to hide, otherwise it is displayed
4. Implementation
4.1 Creating an Adapter
class MyCommonAdapter(private val data: MutableList<String>,private val maxNum: Int) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
// Plus layout
val ADD_ITEM = 1
// Image layout
val PIC_ITEM = 2
}
Copy the code
4.2 Creating a Multi-layout viewHolder
// Plus layout
inner class AddViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
// Common layout
inner class PicViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val pic: ImageView = itemView.findViewById(R.id.ivImage)
val del: ImageView = itemView.findViewById(R.id.ivDelete)
}
Copy the code
4.3 Override getItemViewType and getItemCount methods
/** * If the current position +1=itemCount, then it is the last one, because the position is counted from 0 and itemCount is counted from 1 */
override fun getItemViewType(position: Int): Int {
return if (position + 1 == itemCount) {
ADD_ITEM
} else {
PIC_ITEM
}
}
/** * returns the number +1 in order to add position */ to the plus layout
override fun getItemCount(a): Int {
return data.size + 1
}
Copy the code
4.4 Creating and Binding a Layout
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
ADD_ITEM -> {
var view =
LayoutInflater.from(parent.context).inflate(R.layout.add_item, parent, false)
return AddViewHolder(view)
}
else- > {var view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return PicViewHolder(view)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
// The layout of the plus sign
if (holder is AddViewHolder) {
// Add layout
if (data.size >= maxNum) {
holder.itemView.visibility = View.GONE
} else{ holder.itemView.visibility = View.VISIBLE holder.itemView.setOnClickListener { onItemClickListener? .onItemAddClick(position) } } }// Load the layout of the image
else {
Glide.with(holder.itemView.context).load(data[position])
.into((holder asPicViewHolder).pic) holder.pic.setOnClickListener { onItemClickListener? .onItemPicClick(position) } holder.del.setOnClickListener { onItemClickListener?.onItemDelClick(position) } } }interface OnItemClickListener {
// Click the add button
fun onItemAddClick(position: Int)
// Click the delete button
fun onItemDelClick(position: Int)
// Click the image
fun onItemPicClick(position: Int)
}
Copy the code
4.5 Problems
The result is as follows
GetItemCount () returns data.size()+1, but the layout is still hidden, as shown in figure 2
Solutions:
-
(1) the getItemCount() method returns data.size() when data.size() reaches the maximum value, and returns data.size()+1 when data.size() does not
-
GetItemCount () : getItemViewType() : getItemCount() : getItemViewType() : getItemCount() : getItemViewType() : getItemCount(); Otherwise return the image layout
-
(3) In this way, you can remove the logic in onBindViewHolder() to hide the plus layout when data.size reaches its maximum value
The result is as follows
4.6 Complete Code
class MyCommonAdapter(private val data: MutableList<String>,private val maxNum:Int) :
RecyclerView.Adapter<RecyclerView.ViewHolder>() {
val ADD_ITEM = 1
val PIC_ITEM = 2
private var onItemClickListener: OnItemClickListener? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
when (viewType) {
ADD_ITEM -> {
var view =
LayoutInflater.from(parent.context).inflate(R.layout.add_item, parent, false)
return AddViewHolder(view)
}
else- > {var view = LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false)
return PicViewHolder(view)
}
}
}
/** * Returns the number +1 when the number is less than the maximum, in order to add positions to the plus layout * otherwise returns the normal data size (after the maximum is reached, no positions to the plus layout) */
override fun getItemCount(a): Int {
return if(data.size<maxNum){
data.size+1
}else{
data.size
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
// The layout of the plus sign
if (holder isAddViewHolder) { holder.itemView.setOnClickListener { onItemClickListener? .onItemAddClick(position) } }// Load the layout of the image
else {
Glide.with(holder.itemView.context).load(data[position])
.into((holder asPicViewHolder).pic) holder.pic.setOnClickListener { onItemClickListener? .onItemPicClick(position) } holder.del.setOnClickListener { onItemClickListener?.onItemDelClick(position) } } }Otherwise, if the current position +1=itemCount, it means that it is the last one, because positions are counted from 0 and itemCount is counted from 1 */
override fun getItemViewType(position: Int): Int {
if(data.size==maxNum){
return PIC_ITEM
}else{
return if (position + 1 == itemCount) {
ADD_ITEM
} else {
PIC_ITEM
}
}
}
// Plus layout
inner class AddViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)
// Common layout
inner class PicViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val pic: ImageView = itemView.findViewById(R.id.ivImage)
val del: ImageView = itemView.findViewById(R.id.ivDelete)
}
// Set the interface callback to implement the click function
fun setOnMyClickListener(onClickListener: OnItemClickListener?). {
onItemClickListener = onClickListener
}
interface OnItemClickListener {
// Click the add button
fun onItemAddClick(position: Int)
// Click the delete button
fun onItemDelClick(position: Int)
// Click the image
fun onItemPicClick(position: Int)}}Copy the code
5. To summarize
Matters needing attention:
- Because Android10 and above began to use partition storage, simple dynamic application for reading permission, may appear after selecting photos in recyclerView can not load pictures, because can not get, the simple way is to add in the manifest
android:requestLegacyExternalStorage="true"
Matisse property is disabled on Android11 and needs to be changed.Matisse photo gallery takes photos on Android10 and previews issues
Think down the process, in fact, is relatively simple, figure out the logic inside, in fact, is to use the Recyclerview Adapter multi-layout, with basic functions, click pictures or long press delete effect can be done.
Github address, if it is helpful to you, please give a start
6. Refer to the article
Android wechat circle of friends release dynamic function
Matisse: making