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 manifestandroid: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