Android Material Design学习之RecyclerView代替 ListView

前言 #

Android Material Design越来越流行,以前很常用的 ListView 现在也用RecyclerView代替了,实现原理还是相似的。笔者实现一下 RecyclerView,代码比较简单,适合初学者,如有错误,欢迎指出。

源码地址(欢迎star) https://github.com/studychen/SeeNewsV2

本文链接 http://blog.csdn.net/never_cxb/article/details/50495505,转载请注明出处。

复习 ListView

可以查看这篇博客 Android ListView 基础入门 简介以及深入优化,了解关于 ListView 的基础知识。

实现过程中需要复写BaseAdapter,主要是这4个方法

  • public int getCount() :适配器中数据集中 数据的个数,即ListView需要显示的数据个数
  • public Object getItem(int position) : 获取数据集中与指定索引对应的数据项
  • public long getItemId(int position) : 获取指定行对应的ID
  • public View getView(int

    position, View convertView, ViewGroup parent) :获取每一个Item的显示内容

一般 ListView 每一项都是相同的布局,若想各个项实现不同的布局,可复写 getItemViewTypegetViewTypeCount实现

RecyclerView 实现

xml 布局

下面是RecyclerView中每一项的布局 layout下面的item_article_type_1.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:fresco="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cv_item"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:foreground="?android:attr/selectableItemBackground"
    app:cardCornerRadius="5dp"
    app:cardElevation="5dp"
    app:contentPadding="2dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.facebook.drawee.view.SimpleDraweeView
            android:id="@+id/rcv_article_photo"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:layout_centerVertical="true"
            fresco:actualImageScaleType="centerInside"
            fresco:roundAsCircle="true"
            fresco:roundingBorderColor="@color/lightslategray"
            fresco:roundingBorderWidth="1dp" />

        <LinearLayout
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:orientation="vertical">

            <TextView
                android:id="@+id/rcv_article_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="2dp"
                android:gravity="center"
                android:text="关于举办《经典音乐作品欣赏与人文审美》讲座的通知"
                android:textColor="@color/primary_text" />
            <!-- 新闻 发布时间 来源 阅读次数-->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:gravity="center"
                android:orientation="horizontal">

                <TextView
                    android:id="@+id/rcv_article_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="10dp"
                    android:layout_marginRight="2dp"
                    android:text="2015-01-09" />

                <TextView
                    android:id="@+id/rcv_article_source"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="2dp"
                    android:layout_marginRight="2dp"
                    android:text="科学研究院" />

                <TextView
                    android:id="@+id/rcv_article_readtimes"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="2dp"
                    android:layout_marginRight="2dp"
                    android:text="1129次" />

            </LinearLayout>

            <TextView
                android:id="@+id/rcv_article_preview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginTop="5dp"
                android:ellipsize="end"
                android:maxLines="2"
                android:text="讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识..." />

        </LinearLayout>
    </LinearLayout>

</android.support.v7.widget.CardView> 

布局思路就是 CardView里面嵌入了一个LinearLayout。图片部分用固定宽度100dp,文字部分利用android:layout_weight=”1”占据了其他部分。

TextView利用android:gravity=”center”使得标题的文字居中。

LinearLayout里面利用android:gravity=”center”使得“2015-01-09 科学研究院 1129次”居中,

新闻详情内容的TextView利用

android:maxLines="2"
android:ellipsize="end"

将文章内容限定为2行,超出部分用省略号显示。

使用fresco这儿有个坑需要注意,请移步这篇文章

Android 之 Fresco 显示圆形图片 之坑

预览效果

新闻列表的 xml 文件,layout 文件夹下面的fragment_article.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">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/rcv_article"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />
</LinearLayout>

Adapter 实现

主要步骤是:

  • 根据上面的 item_article_type_1.xml实现一个 class ImageItemArticleViewHolder extends RecyclerView.ViewHolder
  • 继承RecyclerView.Adapter ,class ItemArticleListAdapter extends RecyclerView.Adapter <...>

    重写三个方法

    • public int getItemCount()
    • public TestAdapter.ImageItemArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    • public void onBindViewHolder(ImageItemArticleViewHolder holder, int position)
/**
 * Created by tomchen on 1/11/16.
 */
public class ItemArticleAdapter extends RecyclerView.Adapter<ItemArticleAdapter.ImageItemArticleViewHolder> {

    //新闻列表
    private List<ItemArticle> articleList;

    //context
    private Context context;

    private LayoutInflater mLayoutInflater;

    public ItemArticleAdapter(Context context,List<ItemArticle> articleList) {
        this.context = context;
        this.articleList = articleList;
        mLayoutInflater = LayoutInflater.from(context);
    }

    @Override
    public ItemArticleAdapter.ImageItemArticleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = mLayoutInflater.inflate(
                R.layout.item_article_type_1, parent, false);
        return new ImageItemArticleViewHolder(view);
    }

    @Override
    public void onBindViewHolder(ImageItemArticleViewHolder holder, int position) {
        ItemArticle article = articleList.get(position);
        holder.rcvArticlePhoto.setImageURI(Uri.parse(article.getImageUrl()));
        holder.rcvArticleTitle.setText(article.getTitle());
        holder.rcvArticleDate.setText(article.getPublishDate());
        holder.rcvArticleSource.setText(article.getSource());
        //注意这个阅读次数是 int 类型,需要转化为 String 类型
        holder.rcvArticleReadtimes.setText(article.getReadTimes()+"次");
        holder.rcvArticlePreview.setText(article.getPreview());
    }

    @Override
    public int getItemCount() {
        return articleList.size();
    }

    class ImageItemArticleViewHolder extends RecyclerView.ViewHolder {

        @InjectView(R.id.rcv_article_photo)
        SimpleDraweeView rcvArticlePhoto;
        @InjectView(R.id.rcv_article_title)
        TextView rcvArticleTitle;
        @InjectView(R.id.rcv_article_date)
        TextView rcvArticleDate;
        @InjectView(R.id.rcv_article_source)
        TextView rcvArticleSource;
        @InjectView(R.id.rcv_article_readtimes)
        TextView rcvArticleReadtimes;
        @InjectView(R.id.rcv_article_preview)
        TextView rcvArticlePreview;

        public ImageItemArticleViewHolder(View itemView) {
            super(itemView);
            ButterKnife.inject(this, itemView);
        }
    }

}

新闻实体类 javabean

有新闻的 index,图片 url,标题,发布时间,来源,阅读次数,新闻内容预览

/**
 * Created by tomchen on 1/10/16.
 * 新闻类,这是在 RecycleView 使用的新闻 javabean
 * 还有一个新闻详情javabean
 */
public class ItemArticle {
    private int index;
    private String imageUrl;
    private String title;
    private String publishDate;
    private String source;
    private int readTimes;
    private String preview;

    public ItemArticle(int index, String imageUrl, String title, String publishDate, String source, int readTimes, String preview) {
        this.index = index;
        this.imageUrl = imageUrl;
        this.title = title;
        this.publishDate = publishDate;
        this.source = source;
        this.readTimes = readTimes;
        this.preview = preview;
    }

    public int getIndex() {
        return index;
    }

    public void setIndex(int index) {
        this.index = index;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public void setImageUrl(String imageUrl) {
        this.imageUrl = imageUrl;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getPublishDate() {
        return publishDate;
    }

    public void setPublishDate(String publishDate) {
        this.publishDate = publishDate;
    }

    public String getSource() {
        return source;
    }

    public void setSource(String source) {
        this.source = source;
    }

    public int getReadTimes() {
        return readTimes;
    }

    public void setReadTimes(int readTimes) {
        this.readTimes = readTimes;
    }

    public String getPreview() {
        return preview;
    }

    public void setPreview(String preview) {
        this.preview = preview;
    }
}

fragment 里面使用 RecyclerView

思路就是开启一个异步线程,读取多条新闻,加入List itemArticleList,由这个itemArticleList构造ItemArticleAdapter,最后利用setAdapter()方法给RecyclerView加上适配器。

/**
 * Created by tomchen on 2015/8/28.
 */
public class ArticleFragment extends Fragment {
    private static final String STORE_PARAM = "param";
    @InjectView(R.id.rcv_article)
    RecyclerView rcvArticle;

    private String mParam;
    //新闻列表数据
    private List<ItemArticle> itemArticleList = new ArrayList<ItemArticle>();

    //获取 fragment 依赖的 Activity,方便使用 Context
    private Activity mAct;

    public static Fragment newInstance(String param) {
        ArticleFragment fragment = new ArticleFragment();
        Bundle args = new Bundle();
        args.putString(STORE_PARAM, param);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam = getArguments().getString(STORE_PARAM);
        }
    }

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_article, null);
        Log.i(STORE_PARAM, "in StoreFragment");
        mAct = getActivity();
        ButterKnife.inject(this, view);
        return view;
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        rcvArticle.setLayoutManager(new LinearLayoutManager(mAct));//这里用线性显示 类似于listview
//        rcvArticle.setLayoutManager(new GridLayoutManager(mAct, 2));//这里用线性宫格显示 类似于grid view
//        rcvArticle.setLayoutManager(new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL));//这里用线性宫格显示 类似于瀑布流

        new LatestArticleTask().execute();

    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        ButterKnife.reset(this);
    }

    class LatestArticleTask extends AsyncTask<String, Void, List<ItemArticle>> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
        }

        @Override
        protected List<ItemArticle> doInBackground(String... params) {
            ItemArticle storeInfo1 =
                    new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129,
                            "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...");
            ItemArticle storeInfo2 =
                    new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129,
                            "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...");
            ItemArticle storeInfo3 =
                    new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129,
                            "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...");
            ItemArticle storeInfo4 =
                    new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129,
                            "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...");
            ItemArticle storeInfo5 =
                    new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129,
                            "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...");
            ItemArticle storeInfo6 =
                    new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "关于举办《经典音乐作品欣赏与人文审美》讲座的通知", "2015-01-09", "科学研究院", 1129,
                            "讲座主要内容:以中、西方音乐历史中经典音乐作品为基础,通过作曲家及作品创作背景、相关音乐文化史知识及音乐欣赏常识...");
            itemArticleList.add(storeInfo1);
            itemArticleList.add(storeInfo2);
            itemArticleList.add(storeInfo3);
            itemArticleList.add(storeInfo4);
            itemArticleList.add(storeInfo5);
            itemArticleList.add(storeInfo6);
            return itemArticleList;
        }

        @Override
        protected void onPostExecute(List<ItemArticle> data) {
            super.onPostExecute(data);
            ItemArticleAdapter adapter = new ItemArticleAdapter(mAct, data);
            rcvArticle.setAdapter(adapter);
        }
    }

}

效果图

利用修改布局,线性显示或者宫格显示。(以前宫格显示很麻烦,现在一条命令就好了,google 搞得这么简单,我们 Android 工程师要失业的好伐?!!)

rcvArticle.setLayoutManager(new LinearLayoutManager(mAct));//这里用线性显示 类似于listview
//        rcvArticle.setLayoutManager(new GridLayoutManager(mAct, 2));//这里用线性宫格显示 类似于grid view
//        rcvArticle.setLayoutManager(new StaggeredGridLayoutManager(2, OrientationHelper.VERTICAL));//这里用线性宫格显示 类似于瀑布流

知识点

TextView需要有setText(int resid) 方法,但是这儿 int 表示 resourceId,如果我想把阅读次数(int 1123)赋给这个 TextView,不能使用这个方法。

需要把 int 转化为 String

int 转 String 有三种方法
int i =8;
String s =Integer.toString(i);
String g =String.valueOf(i);
String h =i+"";
holder.rcvArticleReadtimes.setText(String.valueOf(article.getReadTimes()));    


源码地址(欢迎star) https://github.com/studychen/SeeNewsV2

总结 Todo List


遇到的坑

rcvArticle.setLayoutManager()需要在onActivityCreated()方法里调用,如果在onCreateView()调用会抛出空指针异常。

    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.fragment_one_latest, container, false);
        mAct = getActivity();
        //错误,需要在onActivityCreated里面调用
        rcvArticle.setLayoutManager(new LinearLayoutManager(mAct));//这里用线性显示 类似于listview
        ButterKnife.inject(this, view);
        return view;
    }

java.lang.NullPointerException

at com.example.administrator.seenews.ui.fragment.common.ArticleFragment.onCreateView(ArticleFragment.java:111)

参考文章

Android RecyclerView Example | Java Techig

时间: 2024-10-07 19:42:17

Android Material Design学习之RecyclerView代替 ListView的相关文章

Android Material Design之在RecyclerView中嵌套CardView实现

前言: 第一眼就爱上了Android的Material Design风格.以前倒对Android的界面风格不那么喜欢,扁平化的界面设计真是好看. 其实,这个嵌套操作在实现上并没有什么难点.可是,我还在Eclipse上没有试验成功.后来换到Android Studio上就OK了.以下是实现过程. 笔者开发环境: 系统:Windows 7 旗舰版 IDE:Android Studio v1.0 工具包:cardview-v7-21.0.0.aar recyclerview-v7-21.0.0.aar

Android Material Design 学习笔记 - Matrial Theme

google在2014年 I/O大会上推出了一种新的设计设计语言—Material design,这种设计语言语言旨在为手机.平板电脑.台式机和“其他平台”提供更一致.更广泛的“外观和感觉”(附上官方链接:http://developer.android.com/training/material/index.html) 在以后的Android中,我觉得Design风格将逐渐流行,所以:为了跟着潮流,我们也是要不断的与时俱进 --->> 如何使用Design主题? 使用的时候,你仅仅需要在St

Android Material Design系列之RecyclerView和CardView

去年很早之前,我就讲解过RecyclerView的使用,今天我们就在讲解CardView的时候,顺便再把RecyclerView同时讲解一下.RecyclerView.CardView为用于显示复杂视图的新增Widget.接下来看看如何使用吧. RecyclerView RecyclerView介绍 RecyclerView作为替代ListView使用,它更先进,更灵活,RecyclerView标准化了ViewHolder,ListView中convertView是复用的,在RecyclerVi

Android Material Design 兼容库的使用

Android Material Design 兼容库的使用 mecury 前言:近来学习了Android Material Design 兼容库,为了把这个弄懂,才有了这篇博客,这里先推荐两篇博客:1.Android Material Design 兼容库的使用详解2.Android应用Design Support Library完全使用实例第一篇博客是这个兼容库的详细解析,我参考了里面的许多内容,第二篇是兼容库的大致介绍,如果你能把这两篇全部弄懂,我这篇也没有必要看了.说了这么多,开始正文吧

android Material design是什么

Material design概述: Material design是一套UI样式标准,应该会提供一些新的API这写API包含了以下五大模块内容,分别是: Material Theme New Widgets View Shadows Animations New Capabilities for Drawables 1.material新的主题样式. 主题的颜色.动画.反馈效果都可以自定义: 2.控件阴影. 在原来的X,Y的基础之上增加了Z轴的阴影控制,Z值大的控件将显示在上面. 3.Recy

MATERIAL DESIGN学习笔记

一.核心思想 ,aterial design的核心思想,就是把物理世界的体验带进屏幕.去掉现实中的杂质和随机性,保留其最原始纯净的形态.空间关系.变化与过渡,配合虚拟世界的灵活特性,还原最贴近真实的体验,达到简洁与直观的效果. Material design是最重视跨平台体验的一套设计语言.由于规范严格细致,保证它在各个平台使用体验高度一致.不过目前还只有Google自家的服务这么做,毕竟其他平台有自己的规范与风格. 二.材质与空间 材质 Material design中,最重要的信息载体就是魔

Material Design:利用RecyclerView CardView实现新闻卡片样式

Material Design:利用RecyclerView CardView实现新闻卡片样式 明桑Android 主要介绍:`RecyclerView` 和 `CardView`的用法,通过RecyclerView和CardView实现新闻卡片样式... worlduc.com/blog2012.aspx?bid=34337742 worlduc.com/blog2012.aspx?bid=34337761 worlduc.com/blog2012.aspx?bid=34337794 worl

Android Material Design带来的UI变革

谷歌Matias Duarte称,"Material Design是美丽和大胆的,因为干净的排版和布局简单且容易理解.内容才是焦点. 谷歌I/O 014开发者大会上宣布全新的设计语言"Material Design",适用于旗下所有平台,包括 Android.Chrome OS 和网页. 谷歌Matias Duarte称,"Material Design是美丽和大胆的,因为干净的排版和布局简单且容易理解.内容才是焦点." Material Design 初

Android Material Design : Ripple Effect水波波纹荡漾的视觉交互设计

?? Android Material Design : Ripple Effect水波波纹荡漾的视觉交互设计 Android Ripple Effect波纹荡漾效果,是Android Material Design视觉设计引入的一种交互设计效果简言之:当点击某个view时候,view会出现像水波波纹一样的荡漾传播效果.在最新版的Android如Android 5.0或以上版本中默认具有该效果,但在低版本Android中没有,如果需要向下兼容低版本设备,则需要自己写代码实现,实现步骤: 第1步: