1. 資源
- 效果: 由於現csdn只支持某些平臺視頻 想看效果請點擊瀑布流效果
- 源碼: 源碼請加載github
2. 開發中遇到的問題
-
兩列內容沒有居中顯示,如下圖:
處理方法:讓內容item的佈局文件最頂層佈局寬度不要寫死,設置其爲math_parent -
滑動時列表會閃爍,兩列內容交換(由於ViewHolder的複用):
- 處理方法:
final StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); //防止item 交換位置 layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);
- 如果單獨做這個處理會發現列表頂部有時會出現空白部分,只需再做處理:
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); layoutManager.invalidateSpanAssignments(); //防止第一行到頂部有空白區域 } });
- 處理方法:
-
“沒有更多” item 只展示一列:
- 處理方法:設置FooterViewHolder設置其爲滿行展示
-
1: 在FooterViewHolder時設置其爲滿行展示
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == NORMAL_DATA) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false); return new Holder(view); } else { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer, parent, false); StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.setFullSpan(true); view.setLayoutParams(layoutParams); return new FooterHolder(view); } }
-
2: 在onViewAttachedToWindow()判斷是否是最後一個item 如果是則滿行展示
@Override public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { super.onViewAttachedToWindow(holder); if (isFooter(position)) { ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams(); if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) { StaggeredGridLayoutManager.LayoutParams p = (StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams(); p.setFullSpan(true); } } }
-
3. 源碼:
- MainActivity:
public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView; private List<DataInfo> list = new ArrayList<>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initData(); initView(); showList(); } private void showList() { Adapter adapter = new Adapter(list); recyclerView.setAdapter(adapter); } private void initData() { Random r = new Random(1); for (int i = 0; i < 20; i++) { DataInfo info = new DataInfo(); info.height = r.nextInt(1000); info.width = r.nextInt(1000); info.title = String.format(Locale.CANADA, "這是第%d個", i); list.add(info); } } private void initView() { recyclerView = findViewById(R.id.recycle_view); final StaggeredGridLayoutManager layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); //防止item 交換位置 layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int newState) { super.onScrollStateChanged(recyclerView, newState); layoutManager.invalidateSpanAssignments(); //防止第一行到頂部有空白區域 } }); recyclerView.setLayoutManager(layoutManager); } }
- activity_main:
<?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"> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recycle_view" android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
- Adapter:
public class Adapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public final static int FOOTER = 1; public final static int NORMAL_DATA = 2; private List<DataInfo> datas; Adapter(List<DataInfo> datas) { this.datas = datas; } @NonNull @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { if (viewType == NORMAL_DATA) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_view, parent, false); return new Holder(view); } else { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_footer_view, parent, false); //加載更多滿行展示 StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); layoutParams.setFullSpan(true); view.setLayoutParams(layoutParams); return new FooterHolder(view); } } public DataInfo getItem(int position) { return datas.get(position); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) { if (holder instanceof Holder) { DataInfo info = getItem(position); ViewGroup.LayoutParams params = ((Holder) holder).referencePicture.getLayoutParams(); params.height = info.height; params.width = info.width; ((Holder) holder).referencePicture.setLayoutParams(params); ((Holder) holder).goodName.setText(String.format(Locale.CANADA, "%s %d %d", info.title, info.width, info.height)); } } @Override public int getItemViewType(int position) { if (position == getItemCount() - 1) { return FOOTER; } else { return NORMAL_DATA; } } @Override public int getItemCount() { return datas != null ? datas.size() + 1 : 0; } static class Holder extends RecyclerView.ViewHolder { ImageView referencePicture; TextView goodName; Holder(View itemView) { super(itemView); referencePicture = itemView.findViewById(R.id.reference_picture); goodName = itemView.findViewById(R.id.good_name); } } static class FooterHolder extends RecyclerView.ViewHolder { FooterHolder(View itemView) { super(itemView); } } }
- item_data_view:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="5dp" android:background="#FF999999" android:orientation="vertical"> <ImageView android:id="@+id/reference_picture" android:layout_width="338dp" android:layout_height="234dp" android:layout_gravity="center_horizontal" android:background="#FF711111" android:scaleType="fitXY" /> <TextView android:id="@+id/good_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:layout_marginTop="24dp" android:layout_marginRight="20dp" android:textColor="#FFFFFFFF" android:textSize="28dp" /> </LinearLayout>
- item_footer_view:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#55555555" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center" android:padding="10dp" android:text="沒有更多" /> </LinearLayout>