Android Material Design学习之RecyclerView代替 ListView

来源:互联网 发布:婚纱照相册排版软件 编辑:程序博客网 时间:2024/05/21 07:07

前言 #

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

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

本文链接 http://www.alijava.com/recyclerview-basics/ 转载请注明出处

复习 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中每一项的布局 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行,超出部分用省略号显示。

预览效果

这里写图片描述

新闻列表的 xml 文件,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));//这里用线性宫格显示 类似于瀑布流

统计结果1

统计结果1

知识点

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

intString 有三种方法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

  • Picasso 图片缓存库的学习
  • 实现 RecyclerView 每个项各自的布局

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

参考文章

Android RecyclerView Example | Java Techig

2 0
原创粉丝点击