我正在尝试创建一个包含项目列表的布局,其中最后一项是添加"标准"的新项目的按钮。类型。它应该像Google Keep列表一样,具有永久性的"添加"列表末尾的项目。 Google Keep list example
我尝试过两种方法来实现它。第一个很简单,但我发现了一个问题。第二个并不那么简单,性能更差。另外,我认为第二种方式是以一种非预期的方式使用RecyclerView
,我认为我可以找到性能问题。
你会怎么做?
第一种方式
第一个应该是最简单的,即在同一布局中添加RecyclerView
后跟ViewGroup
,其中包含"添加"项目。作为父母,我使用LinearLayout
RecyclerView
和Include
标记引用"添加"项目布局。这实际上在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 值。我还在视图中添加了一个标记,以便View
在ViewHolder
使用onBindViewHolder
而不会遇到大麻烦。
我必须更改getItemCount
因为如果我正在膨胀&#34;添加&#34;看来,我不想绑定任何东西,因为视图已经定义了。
我还必须修改BottomSheetBehaviour
方法以返回我的 mDataset 的大小加上#34;添加&#34;图。
最后,我必须通过ViewHolder
将Adapter
实例一直发送到BottomSheet
,以便能够使用{{1}打开onClick
在ViewHolder
中定义,我认为这非常有效。
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
获取标签,并根据它设置了不同的监听器。
答案 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