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)
: 获取指定行对应的IDpublic View getView(int position, View convertView, ViewGroup parent)
:获取每一个Item的显示内容
一般
ListView
每一项都是相同的布局,若想各个项实现不同的布局,可复写getItemViewType
和getViewTypeCount
实现
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));//这里用线性宫格显示 类似于瀑布流
知识点
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
- Picasso 图片缓存库的学习
- 实现 RecyclerView 每个项各自的布局
源码地址(欢迎star) https://github.com/studychen/SeeNewsV2
参考文章
Android RecyclerView Example | Java Techig
- Android Material Design学习之RecyclerView代替 ListView
- Material Design之RecyclerView
- Android:Material Design之RecyclerView使用
- Android RecyclerView之代替ListView与GridView
- android material design widget recyclerview
- Android Material Design之在RecyclerView中嵌套CardView实现
- android 新特性material design 之recyclerview 详解
- Android Material Design系列之RecyclerView和CardView
- Android学习之Material Design之style
- Android Material Design 控件之TabLayout 学习
- Android Material Design学习之二AppBarLayout
- Android Material Design学习之三TabLayout
- Android Material Design 之 TabLayout学习
- Android Material Design学习之五CollapsingToolbarLayout
- Android Material Design学习之四CardView
- 【Android 学习笔记】之 Material design
- Android Material Design 之 TabLayout学习
- Android Material Design学习之二AppBarLayout
- ARM4开发板的EMWIN设计
- 虚拟机安装Ubuntu黑屏解决方法(分区问题)
- 生成N个二进制位的组合
- 最短排序子数组
- 一个简单的爬虫(1)
- Android Material Design学习之RecyclerView代替 ListView
- JNI & NDK 实例讲解二 (通过NDK创建JNI项目)
- IOS学习笔记之网格视图
- Ionic基础——CSS布局
- ALAsset 的用法(时间、url 、图片的获取)
- tableview的调用方法
- iOS7崩溃报 UIView _didChangeToFirstResponder
- HDU 5605 geometry
- LeetCode Spiral Matrix