Tôi đang cố gắng sử dụng RecyclerView
và GridLayoutManager
để tạo lưới 3 cột và tôi sử dụng ItemDecoration
để tạo khoảng cách cột, hiện tại vấn đề là mục chiều rộng trong cột thứ ba nhỏ hơn mục trong cột đầu tiên và cột thứ hai! Xem ảnh chụp màn hình bên dưới.Các mục không có cùng chiều rộng khi sử dụng RecyclerView GridLayoutManager để tạo khoảng cách cột theo ItemDecoration
Nếu tôi không thêm các tùy chỉnh ItemDecoration
-RecyclerView
, mọi thứ đều OK.
Đây là mã của tôi:
MainActivity.java:
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mAdapter = new MyAdapter();
mRecyclerView.setAdapter(mAdapter);
GridLayoutManager gridLayoutManager = new GridLayoutManager(this, 3);
mRecyclerView.setLayoutManager(gridLayoutManager);
int horizontalSpacing = 20;
int verticalSpacing = 10;
SpacingDecoration decoration = new SpacingDecoration(horizontalSpacing, verticalSpacing, true);
mRecyclerView.addItemDecoration(decoration);
}
private static class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private int[] mColors = new int[]{Color.RED, Color.BLUE, Color.MAGENTA};
private static class ItemHolder extends RecyclerView.ViewHolder {
public MyTextView title;
public ItemHolder(View itemView) {
super(itemView);
title = (MyTextView) itemView.findViewById(android.R.id.text1);
title.setTextColor(Color.WHITE);
}
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
ItemHolder holder = new ItemHolder(itemView);
holder.itemView.setOnClickListener(itemClickListener);
return holder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder rHolder, int position) {
ItemHolder holder = (ItemHolder) rHolder;
holder.title.setText(String.format("[%d]width:%d", position, holder.itemView.getWidth()));
holder.itemView.setBackgroundColor(mColors[position % mColors.length]);
holder.itemView.setTag(position);
holder.title.setTag(position);
}
@Override
public int getItemCount() {
return 50;
}
private View.OnClickListener itemClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
int position = (int) v.getTag();
showText(v.getContext(), String.format("[%d]->width:%d", position, v.getWidth()));
}
};
}
public static class SpacingDecoration extends RecyclerView.ItemDecoration {
private int mHorizontalSpacing = 5;
private int mVerticalSpacing = 5;
private boolean isSetMargin = true;
public SpacingDecoration(int hSpacing, int vSpacing, boolean setMargin) {
isSetMargin = setMargin;
mHorizontalSpacing = hSpacing;
mVerticalSpacing = vSpacing;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
boolean isSetMarginLeftAndRight = this.isSetMargin;
int bottomOffset = mVerticalSpacing;
int leftOffset = 0;
int rightOffset = 0;
RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) view.getLayoutParams();
if (parent.getLayoutManager() instanceof GridLayoutManager) {
GridLayoutManager lm = (GridLayoutManager) parent.getLayoutManager();
GridLayoutManager.LayoutParams gridLp = (GridLayoutManager.LayoutParams) lp;
if (gridLp.getSpanSize() == lm.getSpanCount()) {
// Current item is occupied the whole row
// We just need to care about margin left and right now
if (isSetMarginLeftAndRight) {
leftOffset = mHorizontalSpacing;
rightOffset = mHorizontalSpacing;
}
} else {
// Current item isn't occupied the whole row
if (gridLp.getSpanIndex() > 0) {
// Set space between items in one row
leftOffset = mHorizontalSpacing;
} else if (gridLp.getSpanIndex() == 0 && isSetMarginLeftAndRight) {
// Set left margin of a row
leftOffset = mHorizontalSpacing;
}
if (gridLp.getSpanIndex() == lm.getSpanCount() - gridLp.getSpanSize() && isSetMarginLeftAndRight) {
// Set right margin of a row
rightOffset = mHorizontalSpacing;
}
}
}
outRect.set(leftOffset, 0, rightOffset, bottomOffset);
}
}
private static Toast sToast;
public static void showText(Context context, String text) {
if (sToast != null) {
sToast.cancel();
}
sToast = Toast.makeText(context, text, Toast.LENGTH_LONG);
sToast.show();
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.liuqing.rvgldemo.MyTextView
android:id="@android:id/text1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp"
android:textColor="#ffffff"
android:textAppearance="?android:attr/textAppearanceMedium"/>
</LinearLayout>
MyTextView.java
public class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void onWindowFocusChanged(boolean hasWindowFocus) {
super.onWindowFocusChanged(hasWindowFocus);
if (hasWindowFocus) {
setText("[" + getTag() + "]width:" + getWidth());
}
}
}
Nó sẽ được đánh giá cao nếu ai đó có thể giải thích vấn đề này.
Trong công thức của bạn, '+ 1' trong lề phải không thực sự là' + 1', nó phải là '+ spanSize của cell'. (bạn có thể lấy kích thước span với spanSizeLookup hoặc trong LayoutParams của ô) – pdegand59