學習Android Material Design(RecyclerView代替ListView)
本文實例實現(xiàn)一下 RecyclerView,代碼比較簡單,適合初學者,如有錯誤,歡迎指出。
復習 ListView
可以查看這篇文章深入淺出學習Android ListView基礎,了解關于ListView 的基礎知識。
實現(xiàn)過程中需要復寫B(tài)aseAdapter,主要是這4個方法
- public int getCount() :適配器中數(shù)據(jù)集中 數(shù)據(jù)的個數(shù),即ListView需要顯示的數(shù)據(jù)個數(shù)
- public Object getItem(int position) : 獲取數(shù)據(jù)集中與指定索引對應的數(shù)據(jù)項
- public long getItemId(int position) : 獲取指定行對應的ID
- public View getView(int position, View convertView, ViewGroup parent) :獲取每一個Item的顯示內(nèi)容
一般 ListView 每一項都是相同的布局,若想各個項實現(xiàn)不同的布局,可復寫 getItemViewType和getViewTypeCount實現(xiàn)
RecyclerView 實現(xiàn)
1、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="關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知" android:textColor="@color/primary_text" /> <!-- 新聞 發(fā)布時間 來源 閱讀次數(shù)--> <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="講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..." /> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView>
布局思路就是 CardView里面嵌入了一個LinearLayout。圖片部分用固定寬度100dp,文字部分利用android:layout_weight=”1”占據(jù)了其他部分。
TextView利用android:gravity=”center”使得標題的文字居中。
LinearLayout里面利用android:gravity=”center”使得“2015-01-09 科學研究院 1129次”居中,
新聞詳情內(nèi)容的TextView利用
android:maxLines="2" android:ellipsize="end"
將文章內(nèi)容限定為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>
2、Adapter 實現(xiàn)
主要步驟是:
根據(jù)上面的 item_article_type_1.xml實現(xiàn)一個 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)
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()); //注意這個閱讀次數(shù)是 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); } } }
3、新聞實體類 javabean
有新聞的 index,圖片 url,標題,發(fā)布時間,來源,閱讀次數(shù),新聞內(nèi)容預覽
/** * 新聞類,這是在 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; } }
4、fragment 里面使用 RecyclerView
思路就是開啟一個異步線程,讀取多條新聞,加入List itemArticleList,由這個itemArticleList構造ItemArticleAdapter,最后利用setAdapter()方法給RecyclerView加上適配器。
public class ArticleFragment extends Fragment { private static final String STORE_PARAM = "param"; @InjectView(R.id.rcv_article) RecyclerView rcvArticle; private String mParam; //新聞列表數(shù)據(jù) 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", "關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知", "2015-01-09", "科學研究院", 1129, "講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..."); ItemArticle storeInfo2 = new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知", "2015-01-09", "科學研究院", 1129, "講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..."); ItemArticle storeInfo3 = new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知", "2015-01-09", "科學研究院", 1129, "講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..."); ItemArticle storeInfo4 = new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知", "2015-01-09", "科學研究院", 1129, "講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..."); ItemArticle storeInfo5 = new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知", "2015-01-09", "科學研究院", 1129, "講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..."); ItemArticle storeInfo6 = new ItemArticle(20123, "http://i2.sinaimg.cn/ent/j/2012-05-20/U5912P28T3D3634984F328DT20120520152700.JPG", "關于舉辦《經(jīng)典音樂作品欣賞與人文審美》講座的通知", "2015-01-09", "科學研究院", 1129, "講座主要內(nèi)容:以中、西方音樂歷史中經(jīng)典音樂作品為基礎,通過作曲家及作品創(chuàng)作背景、相關音樂文化史知識及音樂欣賞常識..."); 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); } } }
效果圖
利用修改布局,線性顯示或者宮格顯示。(以前宮格顯示很麻煩,現(xiàn)在一條命令就好了,google 搞得這么簡單,我們Android 工程師要失業(yè)的好伐??。。?/p>
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,如果我想把閱讀次數(shù)(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()));
總結 Todo List
- Picasso 圖片緩存庫的學習
- 實現(xiàn) RecyclerView 每個項各自的布局
遇到的坑
rcvArticle.setLayoutManager()需要在onActivityCreated()方法里調(diào)用,如果在onCreateView()調(diào)用會拋出空指針異常。
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_one_latest, container, false); mAct = getActivity(); //錯誤,需要在onActivityCreated里面調(diào)用 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)
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助。
相關文章
Android ViewPager制作新手導航頁(動態(tài)加載)
這篇文章主要為大家詳細介紹了Android ViewPager制作新手導航頁,了解什么是動態(tài)加載指示器,感興趣的小伙伴們可以參考一下2016-05-05Android開發(fā)中數(shù)據(jù)庫升級且表添加新列的方法
這篇文章主要介紹了Android開發(fā)中數(shù)據(jù)庫升級且表添加新列的方法,結合具體實例形式分析了Android數(shù)據(jù)庫升級開發(fā)過程中常見問題與相關操作技巧,需要的朋友可以參考下2017-09-09Android編程實現(xiàn)根據(jù)經(jīng)緯度查詢地址并對獲取的json數(shù)據(jù)進行解析的方法
這篇文章主要介紹了Android編程實現(xiàn)根據(jù)經(jīng)緯度查詢地址并對獲取的json數(shù)據(jù)進行解析的方法,結合實例形式分析了Android的經(jīng)緯度地址解析與json格式數(shù)據(jù)操作相關技巧,需要的朋友可以參考下2017-02-02Android TextView Marquee的應用實例詳解
這篇文章主要介紹了Android TextView Marquee的應用實例詳解的相關資料,這里說明使用方法及簡單實例和注意實現(xiàn),需要的朋友可以參考下2017-08-08Android開發(fā)實現(xiàn)ImageView加載攝像頭拍攝的大圖功能
這篇文章主要介紹了Android開發(fā)實現(xiàn)ImageView加載攝像頭拍攝的大圖功能,涉及Android基于ImageView的攝像頭拍攝圖片加載、保存及權限控制等相關操作技巧,需要的朋友可以參考下2017-11-11Android 自定義對話框 showSetPwdDialog
這篇文章主要介紹了Android 自定義對話框 showSetPwdDialog的相關資料,需要的朋友可以參考下2016-03-03