Android中RecyclerView巢狀RecyclerView或巢狀ListView
效果圖:
RecyclerView巢狀RecyclerView
RecyclerView巢狀ListView
原理
RecyclerView巢狀RecyclerView的條目,專案中可能會經常有這樣的需求,但是我們將子條目設定為RecyclerView之後,卻顯示不出來。自己試了很久,終於找到了原因:必須先設定子RecylcerView的高度。你要花精力確定出子RecyclerView裡面條目的高度,然後從而確定子RecyclerView的高度,設定給子RecylcerView,這樣做RecyclerView就可以正確顯示出子ReclyclerView。
程式碼
首頁佈局就是一個豎直排列的RecyclerView
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.RecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/recylcerview"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
- 1
- 2
- 3
- 4
- 5
- 6
接下來在MainActivity對該佈局進行初始化,然後製造一些假資料
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
basicParamInit();
initData();
initRecyclerView();
}
private void basicParamInit() {
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
screenWidth = metric.widthPixels;
}
private void initData() {
data = new DataInfor();
ArrayList<Integer> resourceList =new ArrayList<>();
resourceList.add(R.drawable.aaa);
resourceList.add(R.mipmap.ic_launcher);
resourceList.add(R.drawable.aaa);
resourceList.add(R.mipmap.ic_launcher);
resourceList.add(R.drawable.aaa);
resourceList.add(R.mipmap.ic_launcher);
resourceList.add(R.drawable.aaa);
resourceList.add(R.mipmap.ic_launcher);
data.gridData = data.horizontalData = data.verticalData = resourceList;
}
private void initRecyclerView() {
recylcerview = (RecyclerView) findViewById(R.id.recylcerview);
recylcerview.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL,false));
recylcerview.setBackgroundResource(R.color.c_e0e0e2);
recylcerview.setAdapter(new RecyclerViewAdapter());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
接下來看看RecyclerView的Adapter:
private class RecyclerViewAdapter extends RecyclerView.Adapter<BaseHolder>{
private final int HORIZONTAL_VIEW = 1000;
private final int VERTICAL_VIEW = 1001;
private final int GRID_VIEW = 1002;
@Override
public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
switch (viewType){
case HORIZONTAL_VIEW:
return new HorizontalViewHolder(R.layout.item_recyclerview,parent,viewType);
case GRID_VIEW:
return new GridViewHolder(R.layout.item_recyclerview,parent,viewType);
case VERTICAL_VIEW:
return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);
}
return null;
}
@Override
public void onBindViewHolder(BaseHolder holder, int position) {
if(holder instanceof HorizontalViewHolder){
holder.refreshData(data.horizontalData,position);
}else if(holder instanceof GridViewHolder){
holder.refreshData(data.gridData,position);
}else if(holder instanceof ItemViewHolder){
holder.refreshData(data.verticalData.get(position - 2),position - 2);
}
}
@Override
public int getItemCount() {
return 2 + data.verticalData.size();
}
@Override
public int getItemViewType(int position) {
if(position == 0) return HORIZONTAL_VIEW;
if(position == 1) return GRID_VIEW;
return VERTICAL_VIEW;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
可以看出,我們一共有三種條目型別,第一種是水平滑動的子RecyclerView,第二種是GridView形的子RecyclerView,第三種就是正常的子條目,根據viewType來返回不同的ViewHolder,到這裡應該都沒什麼問題。
接下來就是各個型別的ViewHolder了,在Holder當中,我們要計算條目的高度然後設定給子RecyclerView
private class HorizontalViewHolder extends BaseHolder<List<Integer>>{
private RecyclerView hor_recyclerview;
private List<Integer> data;
public HorizontalViewHolder(int viewId, ViewGroup parent, int viewType) {
super(viewId, parent, viewType);
hor_recyclerview = (RecyclerView) itemView.findViewById(R.id.item_recyclerview);
}
@Override
public void refreshData(List<Integer> data, int position) {
this.data = data;
ViewGroup.LayoutParams layoutParams = hor_recyclerview.getLayoutParams();
//高度等於=條目的高度+ 10dp的間距 + 10dp(為了讓條目居中)
layoutParams.height = screenWidth/3 + dip2px(20);
hor_recyclerview.setLayoutParams(layoutParams);
hor_recyclerview.setLayoutManager(new LinearLayoutManager(MainActivity.this, LinearLayoutManager.HORIZONTAL,false));
hor_recyclerview.setBackgroundResource(R.color.colorAccent);
hor_recyclerview.setAdapter(new HorizontalAdapter());
}
private class HorizontalAdapter extends RecyclerView.Adapter<BaseHolder>{
@Override
public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);
}
@Override
public void onBindViewHolder(BaseHolder holder, int position) {
holder.refreshData(data.get(position),position);
}
@Override
public int getItemCount() {
return data.size();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
水平的子RecyclerView的高度還是比較容易計算的,畢竟只有一行,高度相對來說是固定的。但是像GridView的高度是動態的,根據條目數量的不同,可能會有多行,所以我們需要先計算行數,然後每行的高度*行數才是子RecyclerView的高度
private class GridViewHolder extends BaseHolder<List<Integer>>{
private RecyclerView item_recyclerview;
private final int ONE_LINE_SHOW_NUMBER = 3;
private List<Integer> data;
public GridViewHolder(int viewId, ViewGroup parent, int viewType) {
super(viewId, parent, viewType);
item_recyclerview = (RecyclerView) itemView.findViewById(R.id.item_recyclerview);
}
@Override
public void refreshData(List<Integer> data, int position) {
super.refreshData(data, position);
this.data = data;
//每行顯示3個,水平顯示
item_recyclerview.setLayoutManager(new GridLayoutManager(MainActivity.this,ONE_LINE_SHOW_NUMBER,LinearLayoutManager.HORIZONTAL,false));
ViewGroup.LayoutParams layoutParams = item_recyclerview.getLayoutParams();
//計算行數
int lineNumber = data.size()%ONE_LINE_SHOW_NUMBER==0? data.size()/ONE_LINE_SHOW_NUMBER:data.size()/ONE_LINE_SHOW_NUMBER +1;
//計算高度=行數*每行的高度 +(行數-1)*10dp的margin + 10dp(為了居中)
//因為每行顯示3個條目,為了保持正方形,那麼高度應該是也是寬度/3
//高度的計算需要自己好好理解,否則會產生巢狀recyclerView可以滑動的現象
layoutParams.height = lineNumber *(screenWidth/3) + (lineNumber-1)*dip2px(10) + dip2px(10);
item_recyclerview.setLayoutParams(layoutParams);
item_recyclerview.setBackgroundResource(R.color.colorPrimary);
item_recyclerview.setAdapter(new GridAdapter());
}
private class GridAdapter extends RecyclerView.Adapter<BaseHolder>{
@Override
public BaseHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new ItemViewHolder(R.layout.item_x2_imageview,parent,viewType);
}
@Override
public void onBindViewHolder(BaseHolder holder, int position) {
holder.refreshData(data.get(position),position);
}
@Override
public int getItemCount() {
return data.size();
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
總體來說,RecyclerView巢狀RecyclerView是很簡單的,而且也相當好用,希望這個demo可以給大家一些靈感。
下面是我修改後的例子:有任何問題都可以聯絡我:[email protected]
效果圖:
原始碼下載:
轉載地址: