Android 循环视图示例 - 多种视图类型

到目前为止,我们已经在**RecyclerView** .中显示了相同类型的视图在本教程中,我们将在一个RecclerView中实现异类布局。

回收器查看♪

具有异构布局的视图通常用于显示节标题和详细信息(两者都需要不同的布局,因此不同的视图类型)。此外,它还用于Newsfeed应用程序(如Facebook,Instagram),这些应用程序为不同类型显示基本上不同的视图。例如:文本,图像,gif,视频等,其中每一个都需要在QuixlerView中使用不同的布局类型。它也用于[NavigationDrawer](/community/tutorials/android-navigation-drawer-example-tutorial),将Header与其他部分分开。不浪费任何时间,让我们在我们的应用程序中实现它。

Android RecEconerView多个视图类型项目结构

我们将实现三种视图类型(文本、图像、音频),它们由三种不同的布局放大。每个都在Adapter类中指定了自己的实现。Android回收器查看多视图类型project

代码

我们的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 Receierview多类型output本教程到此结束。您可以从下面的链接下载最终的Android** RecclerViewMultipleViewType** 项目。

下载安卓回收器查看多视类型Project

Published At
Categories with 技术
Tagged with
comments powered by Disqus