到目前为止,我们已经在**RecyclerView** .中显示了相同类型的视图在本教程中,我们将在一个RecclerView中实现异类布局。
回收器查看♪
具有异构布局的视图通常用于显示节标题和详细信息(两者都需要不同的布局,因此不同的视图类型)。此外,它还用于Newsfeed应用程序(如Facebook,Instagram),这些应用程序为不同类型显示基本上不同的视图。例如:文本,图像,gif,视频等,其中每一个都需要在QuixlerView中使用不同的布局类型。它也用于[NavigationDrawer](/community/tutorials/android-navigation-drawer-example-tutorial),将Header与其他部分分开。不浪费任何时间,让我们在我们的应用程序中实现它。
Android RecEconerView多个视图类型项目结构
我们将实现三种视图类型(文本、图像、音频),它们由三种不同的布局放大。每个都在Adapter类中指定了自己的实现。
代码
我们的ACTIVITY_Main.xml 包含了作为根的OrganatorLayout,而RecclerView作为它的子视图。
1<?xml version="1.0" encoding="utf-8"?>
2<android.support.design.widget.CoordinatorLayout xmlns:android="https://schemas.android.com/apk/res/android"
3 xmlns:app="https://schemas.android.com/apk/res-auto"
4 xmlns:tools="https://schemas.android.com/tools"
5 android:layout_width="match_parent"
6 android:layout_height="match_parent"
7 android:fitsSystemWindows="true"
8 tools:context="com.journaldev.recyclerviewmultipleviewtype.MainActivity">
9
10 <android.support.design.widget.AppBarLayout
11 android:layout_width="match_parent"
12 android:layout_height="wrap_content"
13 android:theme="@style/AppTheme.AppBarOverlay">
14
15 <android.support.v7.widget.Toolbar
16 android:id="@+id/toolbar"
17 android:layout_width="match_parent"
18 android:layout_height="?attr/actionBarSize"
19 android:background="?attr/colorPrimary"
20 app:popupTheme="@style/AppTheme.PopupOverlay" />
21
22 </android.support.design.widget.AppBarLayout>
23
24 <android.support.v7.widget.RecyclerView
25 android:id="@+id/recyclerView"
26 android:layout_width="match_parent"
27 app:layout_behavior="@string/appbar_scrolling_view_behavior"
28 android:layout_height="match_parent" />
29
30</android.support.design.widget.CoordinatorLayout>
请注意回收器视图中的行app:layout_behavior=
@string/appbar_scrolling_view_behavior``。取消此选项将在整个屏幕上滚动Reccle View,从而使其与AppBarLayout重叠。在Adapter中填充数据的Model.Java类如下所示
1public class Model {
2
3 public static final int TEXT_TYPE=0;
4 public static final int IMAGE_TYPE=1;
5 public static final int AUDIO_TYPE=2;
6
7 public int type;
8 public int data;
9 public String text;
10
11 public Model(int type, String text, int data)
12 {
13 this.type=type;
14 this.data=data;
15 this.text=text;
16 }
17}
它由三种数据类型组成。
1.int类型
保持view类型不变。
2.字符串文本
包含要在TextView中显示的字符串。
3.int data
变量用于存储我们将填充的各个数据。理想情况下,它将包含一个可绘制或原始类型的资源。
下面给出了MainActivity.Java类
1package com.journaldev.recyclerviewmultipleviewtype;
2
3import android.os.Bundle;
4import android.support.v7.app.AppCompatActivity;
5import android.support.v7.widget.DefaultItemAnimator;
6import android.support.v7.widget.LinearLayoutManager;
7import android.support.v7.widget.OrientationHelper;
8import android.support.v7.widget.RecyclerView;
9import android.support.v7.widget.Toolbar;
10import java.util.ArrayList;
11
12public class MainActivity extends AppCompatActivity {
13
14 @Override
15 protected void onCreate(Bundle savedInstanceState) {
16 super.onCreate(savedInstanceState);
17 setContentView(R.layout.activity_main);
18 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
19 setSupportActionBar(toolbar);
20
21 ArrayList<Model> list= new ArrayList();
22 list.add(new Model(Model.TEXT_TYPE,"Hello. This is the Text-only View Type. Nice to meet you",0));
23 list.add(new Model(Model.IMAGE_TYPE,"Hi. I display a cool image too besides the omnipresent TextView.",R.drawable.wtc));
24 list.add(new Model(Model.AUDIO_TYPE,"Hey. Pressing the FAB button will playback an audio file on loop.",R.raw.sound));
25 list.add(new Model(Model.IMAGE_TYPE,"Hi again. Another cool image here. Which one is better?",R.drawable.snow));
26
27 MultiViewTypeAdapter adapter = new MultiViewTypeAdapter(list,this);
28 LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, OrientationHelper.VERTICAL, false);
29
30 RecyclerView mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);
31 mRecyclerView.setLayoutManager(linearLayoutManager);
32 mRecyclerView.setItemAnimator(new DefaultItemAnimator());
33 mRecyclerView.setAdapter(adapter);
34 }
35}
R.raw.sound
是一个sound.mp3文件,将在音频视图类型中播放。RecclerView的Adapter类包含三个需要重写的主要方法。
getItemViewType()
onCreateViewHolder()
onBindViewHolder()
我们将在getItemViewType()方法中使用Switch语句来返回各自的viewType
。这个viewType
变量是Adapter类的内部变量。在onCreateViewHolder()和onBindViewHolder中使用它来膨胀和填充映射的布局。在我们开始实现Adapter类之前,让我们先来看看为每种视图类型定义的布局类型。Text_type.xml
1<android.support.v7.widget.CardView xmlns:card_view="https://schemas.android.com/apk/res-auto"
2 xmlns:android="https://schemas.android.com/apk/res/android"
3 android:id="@+id/card_view"
4 android:layout_width="match_parent"
5 android:layout_height="wrap_content"
6 android:layout_marginTop="@dimen/activity_horizontal_margin"
7 card_view:cardElevation="10dp">
8 <TextView
9 android:id="@+id/type"
10 android:layout_width="match_parent"
11 android:layout_height="wrap_content"
12 android:padding="10dp"
13 />
14
15</android.support.v7.widget.CardView>
Image_type.xml
1<android.support.v7.widget.CardView xmlns:card_view="https://schemas.android.com/apk/res-auto"
2 xmlns:android="https://schemas.android.com/apk/res/android"
3 android:id="@+id/card_view"
4 android:layout_width="match_parent"
5 android:layout_height="wrap_content"
6 android:layout_margin="@dimen/activity_horizontal_margin"
7 card_view:cardElevation="10dp">
8
9 <LinearLayout
10 android:layout_width="match_parent"
11 android:orientation="vertical"
12 android:layout_height="wrap_content">
13
14 <TextView
15 android:id="@+id/type"
16 android:layout_width="match_parent"
17 android:layout_height="wrap_content"
18 android:padding="10dp"
19 />
20
21 <ImageView
22 android:id="@+id/background"
23 android:layout_width="match_parent"
24 android:layout_height="150dp"
25 android:scaleType="centerCrop"
26 android:src="@drawable/snow"
27 />
28
29 </LinearLayout>
30
31 </android.support.v7.widget.CardView>
Audio_type.xml
1<android.support.v7.widget.CardView xmlns:card_view="https://schemas.android.com/apk/res-auto"
2 xmlns:android="https://schemas.android.com/apk/res/android"
3 android:id="@+id/card_view"
4 android:layout_width="match_parent"
5 android:layout_height="wrap_content"
6 android:layout_margin="@dimen/activity_horizontal_margin"
7 card_view:cardElevation="10dp">
8
9 <RelativeLayout
10 android:layout_width="match_parent"
11 android:layout_height="wrap_content">
12
13 <TextView
14 android:id="@+id/type"
15 android:layout_width="match_parent"
16 android:layout_height="wrap_content"
17 android:padding="10dp"
18 />
19
20 <android.support.design.widget.FloatingActionButton
21 android:layout_width="wrap_content"
22 android:layout_height="wrap_content"
23 android:layout_centerHorizontal="true"
24 android:tint="#FFFFFF"
25 android:id="@+id/fab"
26 android:layout_below="@+id/type"
27 android:layout_margin="@dimen/activity_horizontal_margin"
28 android:src="@drawable/volume"/>
29
30 </RelativeLayout>
31
32 </android.support.v7.widget.CardView>
注意:在build.gradle 文件中添加对cardview的以下依赖项
1compile 'com.android.support:cardview-v7:24.2.0'
确保appCompat依赖项的版本号与cardview依赖项的版本号匹配。(对我来说,现在是24.2.0。对你来说可能是不同的。)我们将为上述每个布局创建三个单独的ViewHolder类,如下面的MultiViewTypeAdapter.Java类所示。
1package com.journaldev.recyclerviewmultipleviewtype;
2
3import android.content.Context;
4import android.media.MediaPlayer;
5import android.support.design.widget.FloatingActionButton;
6import android.support.v7.widget.CardView;
7import android.support.v7.widget.RecyclerView;
8import android.view.LayoutInflater;
9import android.view.View;
10import android.view.ViewGroup;
11import android.widget.ImageView;
12import android.widget.TextView;
13
14import java.util.ArrayList;
15
16/**
17 * Created by anupamchugh on 09/02/16.
18 */
19public class MultiViewTypeAdapter extends RecyclerView.Adapter {
20
21 private ArrayList<Model>dataSet;
22 Context mContext;
23 int total_types;
24 MediaPlayer mPlayer;
25 private boolean fabStateVolume = false;
26
27 public static class TextTypeViewHolder extends RecyclerView.ViewHolder {
28
29 TextView txtType;
30 CardView cardView;
31
32 public TextTypeViewHolder(View itemView) {
33 super(itemView);
34
35 this.txtType = (TextView) itemView.findViewById(R.id.type);
36 this.cardView = (CardView) itemView.findViewById(R.id.card_view);
37 }
38 }
39
40 public static class ImageTypeViewHolder extends RecyclerView.ViewHolder {
41
42 TextView txtType;
43 ImageView image;
44
45 public ImageTypeViewHolder(View itemView) {
46 super(itemView);
47
48 this.txtType = (TextView) itemView.findViewById(R.id.type);
49 this.image = (ImageView) itemView.findViewById(R.id.background);
50 }
51 }
52
53 public static class AudioTypeViewHolder extends RecyclerView.ViewHolder {
54
55 TextView txtType;
56 FloatingActionButton fab;
57
58 public AudioTypeViewHolder(View itemView) {
59 super(itemView);
60
61 this.txtType = (TextView) itemView.findViewById(R.id.type);
62 this.fab = (FloatingActionButton) itemView.findViewById(R.id.fab);
63 }
64 }
65
66 public MultiViewTypeAdapter(ArrayList<Model>data, Context context) {
67 this.dataSet = data;
68 this.mContext = context;
69 total_types = dataSet.size();
70 }
71
72 @Override
73 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
74
75 View view;
76 switch (viewType) {
77 case Model.TEXT_TYPE:
78 view = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_type, parent, false);
79 return new TextTypeViewHolder(view);
80 case Model.IMAGE_TYPE:
81 view = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_type, parent, false);
82 return new ImageTypeViewHolder(view);
83 case Model.AUDIO_TYPE:
84 view = LayoutInflater.from(parent.getContext()).inflate(R.layout.audio_type, parent, false);
85 return new AudioTypeViewHolder(view);
86 }
87 return null;
88 }
89
90 @Override
91 public int getItemViewType(int position) {
92
93 switch (dataSet.get(position).type) {
94 case 0:
95 return Model.TEXT_TYPE;
96 case 1:
97 return Model.IMAGE_TYPE;
98 case 2:
99 return Model.AUDIO_TYPE;
100 default:
101 return -1;
102 }
103 }
104
105 @Override
106 public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int listPosition) {
107
108 Model object = dataSet.get(listPosition);
109 if (object != null) {
110 switch (object.type) {
111 case Model.TEXT_TYPE:
112 ((TextTypeViewHolder) holder).txtType.setText(object.text);
113
114 break;
115 case Model.IMAGE_TYPE:
116 ((ImageTypeViewHolder) holder).txtType.setText(object.text);
117 ((ImageTypeViewHolder) holder).image.setImageResource(object.data);
118 break;
119 case Model.AUDIO_TYPE:
120
121 ((AudioTypeViewHolder) holder).txtType.setText(object.text);
122
123 ((AudioTypeViewHolder) holder).fab.setOnClickListener(new View.OnClickListener() {
124 @Override
125 public void onClick(View view) {
126
127 if (fabStateVolume) {
128 if (mPlayer.isPlaying()) {
129 mPlayer.stop();
130
131 }
132 ((AudioTypeViewHolder) holder).fab.setImageResource(R.drawable.volume);
133 fabStateVolume = false;
134
135 } else {
136 mPlayer = MediaPlayer.create(mContext, R.raw.sound);
137 mPlayer.setLooping(true);
138 mPlayer.start();
139 ((AudioTypeViewHolder) holder).fab.setImageResource(R.drawable.mute);
140 fabStateVolume = true;
141
142 }
143 }
144 });
145 break;
146 }
147 }
148 }
149
150 @Override
151 public int getItemCount() {
152 return dataSet.size();
153 }
154}
在上面的代码中,我们保留了一个全局布尔变量,用于存储每次单击时切换的音量按钮状态(以及更改FloatingActionButton 的图像资源)。上述应用程序的输出如下所示。本教程到此结束。您可以从下面的链接下载最终的Android** RecclerViewMultipleViewType** 项目。