【问题标题】:RecyclerView creating margins between itemsRecyclerView 在项目之间创建边距
【发布时间】:2017-01-04 04:40:12
【问题描述】:

首先,对不起,如果这是一个愚蠢的问题。我不是偷懒。 所以,问题是,我试图在 Android 应用程序中实现 CardView/RecyclerView。我做到了,但问题是卡片彼此隔开,我不知道如何修复它。我探索了代码,但一切似乎都很好。

代码:

回收站视图

<android.support.v7.widget.RecyclerView
        android:id="@+id/collapsing_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:padding="@dimen/activity_horizontal_margin">

 </android.support.v7.widget.RecyclerView>

卡片视图项

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.CardView
    android:id="@+id/card_view"
    card_view:cardBackgroundColor="@color/colorAccent"
    android:layout_gravity="center"
    android:layout_width="fill_parent"
    android:layout_height="100dp"
    android:layout_margin="5dp"
    card_view:cardCornerRadius="2dp">

    <TextView
        android:gravity="center"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="New Text"
        android:id="@+id/cardview.name" />

</android.support.v7.widget.CardView>


</LinearLayout>

适配器:

public class MyRecyclerViewAdapter extends RecyclerView
    .Adapter<MyRecyclerViewAdapter
    .DataObjectHolder> {
private static String LOG_TAG = "MyRecyclerViewAdapter";
private ArrayList<CardViewItem> mDataset;
private static MyClickListener myClickListener;

public static class DataObjectHolder extends RecyclerView.ViewHolder
        implements View
        .OnClickListener {
    TextView label;

    public DataObjectHolder(View itemView) {
        super(itemView);
        label = (TextView) itemView.findViewById(R.id.cardview_name);
        Log.i(LOG_TAG, "Adding Listener");
        itemView.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        myClickListener.onItemClick(getAdapterPosition(), v);
    }
}

public void setOnItemClickListener(MyClickListener myClickListener) {
    this.myClickListener = myClickListener;
}

public MyRecyclerViewAdapter(ArrayList<CardViewItem> myDataset) {
    mDataset = myDataset;
}

@Override
public DataObjectHolder onCreateViewHolder(ViewGroup parent,
                                           int viewType) {
    View view = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.example_card_view, parent, false);

    DataObjectHolder dataObjectHolder = new DataObjectHolder(view);
    return dataObjectHolder;
}

@Override
public void onBindViewHolder(DataObjectHolder holder, int position) {
    holder.label.setText(mDataset.get(position).getName());;
}

public void addItem(CardViewItem dataObj, int index) {
    mDataset.add(index, dataObj);
    notifyItemInserted(index);
}

public void deleteItem(int index) {
    mDataset.remove(index);
    notifyItemRemoved(index);
}

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

public interface MyClickListener {
    public void onItemClick(int position, View v);
}
}

希望你们能帮助我。谢谢!

编辑:所以,我找到了答案。罪魁祸首是 android:layout_height="match_parent" 在我的 cardview 项目中。我将其更改为“wrap_content”并解决了问题。谢谢你们的帮助! :)

【问题讨论】:

  • 请提供您当前布局的屏幕截图和说明您希望它如何与众不同的模型。

标签: android android-recyclerview material-design


【解决方案1】:

您是否尝试过使用您的 RecyclerView ItemDecoration ?这对于在 RecyclerView 中自定义分隔线很有用

你可以这样看: 我的自定义 ItemDecoration 像这样使用getItemOffsets()

public class MyItemDecoration extends RecyclerView.ItemDecoration {

    private final int decorationHeight;
    private Context context;

    public MyItemDecoration(Context context) {
        this.context = context;
        decorationHeight = context.getResources().getDimensionPixelSize(R.dimen.decoration_height);
    }

    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        super.getItemOffsets(outRect, view, parent, state);

        if (parent != null && view != null) {

            int itemPosition = parent.getChildAdapterPosition(view);
            int totalCount = parent.getAdapter().getItemCount();

            if (itemPosition >= 0 && itemPosition < totalCount - 1) {
                outRect.bottom = decorationHeight;
            }

        }

    }
}

然后您可以将您的R.dimen.decoration_height 设置为您想要的值。

在我的活动中,当我实例化我的 RecyclerListView 时,我需要这样做:

myList.addItemDecoration(MyItemDecoration(this))
myList.setLayoutManager(LinearLayoutManager(this))
myList.setAdapter(adapter)

希望对你有帮助

【讨论】:

    【解决方案2】:

    从您的 CardView 项目 .xml 中删除此行

    android:layout_margin="5dp"

    您可能希望它是 padding 而不是 margin

    【讨论】:

    • 您好,感谢您的帮助。不幸的是,这并不能解决问题:/
    【解决方案3】:

    为了在项目之间创建间距,我们可以使用RecyclerView's ItemDecorator's:

    addItemDecoration(object : RecyclerView.ItemDecoration() {
    
        override fun getItemOffsets(
            outRect: Rect,
            view: View,
            parent: RecyclerView,
            state: RecyclerView.State,
        ) {
            super.getItemOffsets(outRect, view, parent, state)
            if (parent.getChildAdapterPosition(view) > 0) {
                outRect.top = 8.dp // Change this value with anything you want. Remember that you need to convert integers to pixels if you are working with dps :)
            }
        }
    })
    

    考虑到我粘贴的代码,有几点需要考虑:

    • 您实际上不需要调用super.getItemOffsets,但我选择了,因为我想扩展基类定义的行为。如果库有更新在幕后做更多的逻辑,我们会错过它。

    • 作为向Rect 添加顶部间距的替代方法,您还可以添加底部间距,但与获取适配器的最后一项相关的逻辑更复杂,因此这可能会稍微好一些。

    • 我使用扩展属性将简单整数转换为 dps:8.dp。这样的事情可能会奏效:

    val Int.dp: Int
        get() = (this * Resources.getSystem().displayMetrics.density + 0.5f).toInt()
    
    // Extension function works too, but invoking it would become something like 8.dp()
    

    【讨论】:

      【解决方案4】:

      CardView 默认添加填充。尝试使用 CardView 属性 card_view:contentPadding 但像这样设置属性的负值

      card_view:contentPadding="-3"

      【讨论】: