Как добавить кнопку в конце RecyclerView?

Я хочу показать кнопку в конце RecyclerView.

С ListView появился метод addFooterView(), как сделать то же самое с RecylerView.

Ответ 1

Один из способов сделать это - сделать ваш нижний колонтитул "ViewType" вашего адаптера. Для этого переопределяет getItemViewType для возврата другого значения для вашего последнего элемента.

@Override
public int getItemViewType(int position) {
    return (position == mData.size()) ? VIEW_TYPE_FOOTER : VIEW_TYPE_CELL;
}

Затем в onCreateViewHolder обрабатывает другой тип viewType.

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    if (viewType == VIEW_TYPE_CELL) {

        //Create viewholder for your default cell
    }
    else {

        //Create viewholder for your footer view
    }
}

Не забудьте обновить возвращаемое значение getCount(), добавив 1, и выделить два типа ViewHolder в OnBindViewHolder (например, instanceof).

Ответ 2

Я столкнулся с этой проблемой и нашел этот ответ. Текущий выбранный ответ верен, но в нем отсутствуют некоторые детали. Вот полная реализация,

Добавьте этот метод к адаптеру

@Override
public int getItemViewType(int position) {
    return (position == myItems.size()) ? R.layout.button : R.layout.item;
}

Он проверит, находится ли текущая позиция за последним элементом в вашем списке, если это будет тогда, оно вернет значение макета кнопки для этого метода,

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

    View itemView;

    if(viewType == R.layout.item){
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
    }

    else {
        itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.button, parent, false);
    }

    return new MyViewHolder(itemView);
}

Вышеуказанный метод проверяет, прошел ли переданный viewType макет item или макет button, а затем завышает представление и отправляет раздутый вид этому методу,

@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
    if(position == myItems.size()) {
        holder.button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Toast.makeText(context, "Button Clicked", Toast.LENGTH_LONG).show();
            }
        });
    }
    else {
        final String name = myItems.get(position);
        holder.title.setText(name);
    }
}

Это проверяет, прошло ли мы за последним item в списке, и если мы потом, то мы устанавливаем метод onClick на нашу кнопку. В противном случае он создает нормальный item.

Нам также нужно изменить метод getItemCount на этот

@Override
public int getItemCount() {
    return myItems.size() + 1;
}

Поскольку мы проходим через все items, а затем добавляем a button в конец, + 1 является нашей кнопкой.

Затем, наконец, нам нужно добавить наше представление в класс myViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder {
    public TextView title;
    public Button button;

    public MyViewHolder(View view) {
        super(view);
        title  = (TextView) view.findViewById(R.id.title);
        button = (Button) view.findViewById(R.id.bottom_button);
    }
}

Надеюсь, это поможет!

Ответ 3

Существует очень простой способ для этого сначала вам нужно добавить +1 к размеру списка

    @Override
    public int getItemCount() {
        return badgesModels.size() + 1;
    }

затем проверьте, является ли позиция списка более крупной, чем размер списка. в моем случае:

        if (position == badgesModels.size()) {
            holder.imageViewBadege.setImageDrawable(getResources().getDrawable(R.drawable.plus));
            holder.imageViewBadege.setBackgroundColor(getResources().getColor(R.color.bg_gray));
            holder.textViewBadgeTitle.setText("Make Badge");

            holder.imageViewBadege.setOnClickListener(v -> {
                ListDialog.newInstanceChooseBadge().show(Objects.requireNonNull(getFragmentManager()),"makeBadge");
            });
        } else {
            GlideApp.with(Objects.requireNonNull(getContext())).load(results.get(position).getImage_link()).placeholder(R.drawable.badge).into(holder.imageViewBadege);
            holder.textViewBadgeTitle.setText(results.get(position).getTitle());
            holder.imageViewBadege.setOnClickListener(v -> {
                apiService.assginBadgesStudent(classId, studentId, results.get(position).getId());
                dismiss();
                Objects.requireNonNull(getTargetFragment()).onResume();
                playFromAsset("sounds/ding.wav");
            });
        }

Ответ 4

Это то, что я использую в kotlin. Надеюсь, это кому-нибудь поможет.

class ThumbnailsAdapter(
        private val mContext: Context,
        private val list: ArrayList<Image>
) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        return when (viewType) {
            R.layout.z_thumbnail -> {
                val view = LayoutInflater.from(mContext)
                        .inflate(R.layout.z_thumbnail, parent, false)
                ThumbnailViewHolder(view)
            }
            R.layout.z_thumbanail_add -> {
                val view = LayoutInflater.from(mContext)
                        .inflate(R.layout.z_thumbanail_add, parent, false)
                PlaceholderViewHolder(view)
            }
            else -> throw IllegalArgumentException("unknown view type $viewType")
        }
    }

    override fun getItemCount(): Int {
        return list.size + 1
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
        when (getItemViewType(position)) {
            R.layout.z_thumbnail -> (holder as ThumbnailViewHolder).bind(list[position].path)
            R.layout.z_thumbanail_add -> (holder as PlaceholderViewHolder).bind()
        }
    }

    override fun getItemViewType(position: Int): Int {
        return when (position) {
            list.size -> R.layout.z_thumbanail_add
            else -> R.layout.z_thumbnail
        }
    }

    inner class ThumbnailViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val imageView = itemView.findViewById<ImageView>(R.id.thumbnail)

        fun bind(path: String) {
            Glide.with(mContext).load(path).into(imageView)
        }
    }

    inner class PlaceholderViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val btn = itemView.findViewById<ImageView>(R.id.add_images_btn)

        fun bind() {
            btn.setOnClickListener {
                //Do your logic here for the button
            }
        }
    }

}

Ответ 5

Вот трюк, который работает для меня без создания нового макета представления. По сути, вы должны сравнить размер массива и положение держателя представления, чтобы сгенерировать новое представление в onBindViewHolder.
Напишите следующий код:

@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
    //This is necessary even if you mention view gone in xml file.
    holder.mAddBtn.setVisibility(View.GONE);
    //Compare size and add button at buttom of view,ie arraylist size
    if(position==mComplaintList.size()-1){
        holder.mAddBtn.setVisibility(View.VISIBLE);
    }
    holder.mAddBtn.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
        //Write code
        }
    });
}