Recyclerview使用不同的最后一项作为"添加"项

时间:2016-03-10 20:50:55

标签: android performance android-layout android-recyclerview

我正在尝试创建一个包含项目列表的布局,其中最后一项是添加"标准"的新项目的按钮。类型。它应该像Google Keep列表一样,具有永久性的"添加"列表末尾的项目。 Google Keep list example

我尝试过两种方法来实现它。第一个很简单,但我发现了一个问题。第二个并不那么简单,性能更差。另外,我认为第二种方式是以一种非预期的方式使用RecyclerView,我认为我可以找到性能问题。

你会怎么做?

第一种方式

第一个应该是最简单的,即在同一布局中添加RecyclerView后跟ViewGroup,其中包含"添加"项目。作为父母,我使用LinearLayout RecyclerViewInclude标记引用"添加"项目布局。这实际上在CoordinatorLayout内,因为我使用BottomSheet来选择新的"标准"要添加的项目。

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/colorBackgroundLight"
    android:orientation="vertical">

    <!-- Other Views -->

    <android.support.v7.widget.RecyclerView
        android:id="@+id/mainRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <include
        layout="@layout/itemAdd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
</LinearLayout>

问题是&#34;添加&#34; item位于RecyclerView下方,当RecyclerView为空时,两者都会消失。

第二种方式

然后我尝试了第二种方式,即创建&#34;添加&#34;来自RecyclerView.Adapter的项目。到目前为止,这样做是有效的,尽管我确信这不是最好的方法。我将粘贴代码并在其下面解释背后的原因。

适配器

public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
    private final LayoutInflater mInflater;
    private BottomSheetBehavior bottomSheetBehavior;
    private int count = 0;
    private final List<Object> mDataset;

    // Standard constructor. I get the mInflater from Context here

    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        final View itemView;
        if (count>=mDataset.size()) {
            itemView = mInflater.inflate(R.layout.item_add, parent, false);
            itemView.setTag("ADD");
        }
        else{
            itemView = mInflater.inflate(R.layout.item_sandard, parent, false);
            itemView.setTag(null);
        }
        count += 1;
        return new MyViewHolder(itemView, bottomSheetBehavior);
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        if (position<mDataset.size()) {
            final Object object = mDataset.get(position);
            holder.bind(object); // I bind it on the ViewHolder
        }
    }

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

为此,我创建了一个私有变量 mCount ,用于计算创建的ViewHolder的数量。然后我使用 if 语句启动我的onCreateViewHolder方法,在那里我检查是否已经为最后一个&#34;标准&#34;创建了ViewHolder。我的 mDataset 的项目。根据它,我扩大了标准&#34;查看或&#34;添加&#34;视图。然后,每次用户添加或删除项目(尚未实现)时,我都必须更新 mCount 值。我还在视图中添加了一个标记,以便ViewViewHolder使用onBindViewHolder而不会遇到大麻烦。

我必须更改getItemCount因为如果我正在膨胀&#34;添加&#34;看来,我不想绑定任何东西,因为视图已经定义了。

我还必须修改BottomSheetBehaviour方法以返回我的 mDataset 的大小加上#34;添加&#34;图。

最后,我必须通过ViewHolderAdapter实例一直发送到BottomSheet,以便能够使用{{1}打开onClickViewHolder中定义,我认为这非常有效。

ViewHolder

public class MyViewHolder extends RecyclerView.ViewHolder{
    private final TextView mText;
    private final ImageButton mButton;


    public MyViewHolder(View itemView, final BottomSheetBehavior bottomSheetBehavior) {
        super(itemView);

        if (itemView.getTag() == "ADD"){
            mText = null;
            mButton = null;
            // I also set the OnClickListener to open the BottomSheet
        }
        else{
            // Set mText and an OnClickListener to the button. I use the Adapter here
        }
    }

    // The bind method goes here 
}

在这里,我从View获取标签,并根据它设置了不同的监听器。

1 个答案:

答案 0 :(得分:2)

我可能会迟到,但如果您没有找到任何解决方案,请尝试这种方式..!!

class AddMorePhotosAdapter(
val context: Context,
private val addImageListener: () -> Unit

) : RecyclerView.Adapter() {

private val imageList = ArrayList<Bitmap>()
fun addAll(list: ArrayList<Bitmap>) {
    imageList.clear()
    imageList.addAll(list)
    notifyDataSetChanged()
}

inner class MyItemHolder(val binding: ItemSelectedPhotoBinding) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind(path: Bitmap, position: Int) {
        Glide.with(context)
            .asBitmap()
            .placeholder(R.mipmap.ic_launcher)
            .load(path)
            .into(object : SimpleTarget<Bitmap>() {
                override fun onResourceReady(
                    resource: Bitmap,
                    transition: Transition<in Bitmap>?
                ) {
                    binding.tvSelectedImage.apply {
                        setImageBitmap(resource)
                        scaleType = ImageView.ScaleType.FIT_XY
                    }
                }
            })
    }
}

inner class MyFooterHolder(val binding: LayoutMultiplePhotoBinding) :
    RecyclerView.ViewHolder(binding.root) {

    fun bind() {
        binding.tvAddImage.setOnClickListener {
            addImageListener.invoke()
        }
    }
}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
    val binding: ViewBinding
    if (viewType == TYPE_ITEM) {
        binding =
            ItemSelectedPhotoBinding.inflate(LayoutInflater.from(context), parent, false)
        return MyItemHolder(binding)
    } else if (viewType == TYPE_FOOTER) {
        binding =
            LayoutMultiplePhotoBinding.inflate(LayoutInflater.from(context), parent, false)
        return MyFooterHolder(binding)
    }
    throw RuntimeException("There is no type that matches the type $viewType. Make sure you are using view types correctly!")
}

override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
    when (getItemViewType(position)) {
        TYPE_ITEM -> (holder as MyItemHolder).bind(imageList[position], position)
        TYPE_FOOTER -> (holder as MyFooterHolder).bind()
    }
}

override fun getItemCount(): Int = imageList.size + 1

override fun getItemViewType(position: Int): Int {
    return if (position == imageList.size) {
        TYPE_FOOTER
    } else {
        TYPE_ITEM
    }
}

companion object {
    private const val TYPE_ITEM = 1
    private const val TYPE_FOOTER = 0
}

}

-- 我使用 TYPE_TIME 显示带有 recyclerview 的列表和 TYPE_FOOTER 来显示“添加”图像。两种布局都会不同以膨胀。

检查此图片以供参考。Initialy it will be only "Add" image