在上一篇文章《安卓開發筆記——打造屬于自己的博客園APP(二)》中,我們基本上實現了主界面的搭建,網絡框架的搭建,各博客列表頁面的展示包括更新效果,對圖片做了三級緩存處理(后面會把文章,新聞做成離線閃存,實現無網絡也能照常瀏覽)。
今天來講講博客詳情頁和評論頁面的實現,國際慣例,先上效果圖:(動態圖片比較大,加載需要點時間)
這里說下,關于上篇文章xml的解析,我后來查了下確實有一些方便解析的工具,例如:FastXML,Xstram等且效率更高,這里是在它的官方找到的一張數據圖:
文章里我就還是先采用原生的pull解析了,等重構代碼時候再換上工具類吧,先把項目做完。
好了,廢話不多說了,直接進入主題:
1、關于RecyclerView的點擊事件
首先先來說下關于RecyclerView的點擊監聽事件,在上篇文章提到,RecyclerView是ListView升級版,顧名思義它是為效率而生的,它不關心多余的任何事情,比如Item項的動作監聽,Item項的分割線,Item項的添加動畫效果,只專注于數據的展示實現,相比ListView它更符合軟件設計原則,更加解耦。
上面提到它不關心Item項的動作監聽,很自然,它沒有和ListView控件一樣提供類似setOnItemClickListener這種監聽方法,需要我們自己來實現,那么很自然的,我們會選擇在Adapter里去設置監聽事件,關于RecyclerView不熟悉的朋友可以先看下這篇文章:http://blog.csdn.net/lmj623565791/article/details/45059587
首先我們在Adapter設置一個點擊回調接口,并提供setter方法:
1 /** 2 * 自定義點擊回調接口 3 */ 4 public interface RecyclerViewListener { 5 void setOnclickListener(View view, int pos); 6 } 7 8 PRivate RecyclerViewListener mRecyclerViewListener; 9 10 /**11 * 提供setter方法12 *13 * @param recyclerViewListener14 */15 public void setRecyclerViewListener(RecyclerViewListener recyclerViewListener) {16 this.mRecyclerViewListener = recyclerViewListener;17 }
然后我們在onBindViewHolder中設置監聽事件:
1 //設置點擊監聽2 viewholder.itemView.setTag(i);3 viewholder.mMore.setTag(Integer.MAX_VALUE);4 viewholder.itemView.setOnClickListener(new ItemClick());5 viewholder.mMore.setOnClickListener(new ItemClick());
再來個實現接口:
/** * 點擊事件實現類 */ public class ItemClick implements View.OnClickListener{ @Override public void onClick(View v) { if(mRecyclerViewListener!=null){ mRecyclerViewListener.setOnclickListener(v,(int)v.getTag()); } } }
這樣子,我們就可以在我們的博客列表頁面設置點擊事件了,關于下面的showPopUpMenu是一個點擊彈出窗口,可以實現收藏博文和關注博主的功能,我們下一篇文章會提到。這里我們實現當點擊RecyclerView條目的時候會通過Intent傳遞Blog對象到博文詳情頁面。
1 //設置條目點擊監聽 2 mBlogListAdapter.setRecyclerViewListener(new BlogListAdapter.RecyclerViewListener() { 3 @Override 4 public void setOnclickListener(View view, int pos) { 5 6 if (view.getId() == R.id.ib_more) { 7 //點擊菜單按鈕 8 showPopUpMenu(view, pos); 9 } else {10 //點擊條目,傳遞對象11 Intent intent = new Intent();12 intent.setClass(getActivity(), BlogContentActivity.class);13 Bundle bundle = new Bundle();14 bundle.putSerializable("blog", mBlogs.get(pos));15 intent.putExtras(bundle);16 startActivity(intent);17 }18 }19 });
2、關于博文詳情頁面的實現
這里是關于博文詳情的接口:http://wcf.open.VEVb.com/blog/post/body/{POSTID}(POSTID代表文章Id)
這里是關于博文詳情的XML解析代碼:
1 package com.lcw.rabbit.myblog.parser; 2 3 import org.xmlpull.v1.XmlPullParser; 4 import org.xmlpull.v1.XmlPullParserException; 5 import org.xmlpull.v1.XmlPullParserFactory; 6 7 import java.io.IOException; 8 import java.io.InputStream; 9 10 /**11 * 對博文詳情xml數據的解析12 * Created by Lichenwei13 * Date: 2015-08-1714 * Time: 13:3215 */16 public class BlogContentXmlParser {17 18 19 /**20 * 用于解析博文詳情的xml,返回Avatar的List集合對象21 *22 * @param inputStream23 * @param encode24 * @return25 * @throws XmlPullParserException26 * @throws IOException27 */28 public static String getBlogContent(InputStream inputStream, String encode) throws XmlPullParserException, IOException {29 30 String info="";31 //獲取XmlPullParser實例32 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();33 XmlPullParser parser = factory.newPullParser();34 parser.setInput(inputStream, encode);35 //獲取解析事件36 int eventType = parser.getEventType();37 //當xml文檔未到尾端時38 while (eventType != XmlPullParser.END_DOCUMENT) {39 switch (eventType) {40 //解析根標簽的時候,實例化集合41 case XmlPullParser.START_DOCUMENT:42 break;43 case XmlPullParser.START_TAG:44 if("string".equals(parser.getName())){45 parser.next();46 info=parser.getText();47 }48 break;49 }50 eventType = parser.next();51 }52 return info;53 54 }55 56 }
關于博文詳情頁的實現,我做了很多方法的嘗試,因為我們獲取的數據是Html代碼,我們很自然的會想到用WebView,但是用WebView來展示,我們需要一個固定的樣式來控制頁面內容,不然會導致頁面格式無法控制,比如文字的排布換行,圖片的大小控制,包括整體頁面的屏幕適配,由于我們獲取的只是部分Html代碼,所以會純在很多問題,并且有滑動卡頓(對于安卓來說,WebView本來就是個軟肋)。
然后我嘗試著用Html類下的fromHtml方法來實現對頁面代碼的格式化,它是基于TextView的,發現滑動很流暢,文字大小也可以控制的很好,但又有一個問題出現了,關于圖片的展示問題,雖然fromHtml提供了另外一個包含ImageGetter的構造方法,但是在我們通過異步獲取圖片的時候它不發預知圖片尺寸的大小,導致最后獲取出來的圖片會覆蓋了文字。
效果如圖:
后來我嘗試的去GitHub上找找開源的組件發現了HtmlTextView:https://github.com/sufficientlysecure/html-textview,但是也不能夠達到想要的效果,最后無奈的用了一個最笨的方法去做,就是在我們獲取到Html格式數據的時候,我們通過String的replace方法用正則表達式方式去判斷位置,比如<img/>標簽,然后通過添加換行符號<br/>來人工換行,這樣子看似沒什么問題,但是圖片畢竟有很多,有大有小,也并不是很完美的可以解決問題。
最后我覺得不應該老在安卓端里去考慮問題,畢竟我們的數據是從網絡獲取下來的,我們對它們具有完全的掌控權,為啥不從Html代碼端去考慮問題的解決呢?然后我決定寫一個靜態的Html模板,對它做了移動端的屏幕適配,然后再把我們獲取到的內容插入進去。(這里而外再提一個方法,我們也可以通過Jsoup去解析Html代碼,然后去創建一個實體對象,把內容加入到List集合,然后再通過頁面展示)
好了,看下我的Html靜態模板的實現:
這是Html模板:
1 <html> 2 <head> 3 <title>Blog Content</title> 4 <meta name="viewport" 5 content="width=device-width, minimum-scale=0.5, initial-scale=1.2, maximum-scale=2.0, user-scalable=1"/> 6 <link rel="stylesheet" type="text/CSS" href="css.css"/> 7 8 </head> 9 <body>10 <div id="header">11 <h3>12 #title#13 </h3>14 15 <div class="describe"><p/>#author#<p/>16 17 <div id="info">#info#<p/>#time#</div>18 </div>19 </div>20 <div id="content">21 #content#22 </div>23 </body>24 </html>BlogContent.html
這是Css文件:
1 body{font-family:Helvetica,"Microsoft Yahei",Verdana,Helvetica,SimSun,Arial,"Arial Unicode MS",MingLiu,PMingLiu,"MS Gothic",sans-serief;margin:0;padding:0 8px;background-color:#efeff0;color:#333;Word-wrap:break-word;} 2 p{margin-top:0;margin-bottom:5pt;line-height: 1.6em;} 3 #header{text-align:center;background:transparent url('webBgLine.png') repeat-x scroll center bottom; padding-top:6pt;margin-bottom:5pt;-webkit-background-size:320px 2px;} 4 #header h3{margin-bottom:0px; margin-top:5px;font-size:14pt;padding:0 5pt;color:#464646;line-height:1.3em;} 5 .describe{color:#8e8e8e;font-size:12pt;padding:4pt 0; color:#333;} 6 #info{ font-size:10pt;line-height:1.6; color:#787878;} 7 #content{ font-size:12pt;line-height:1.8;} 8 img{max-width:80%;height:auto;} 9 div.bimg{text-align:center;padding:0;}10 .photo_title{font-weight:bold;font-size:14pt;margin-top:15px;}11 .langs_cn{color:#006200;}12 audio{width:100%}13 *{-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */14 /*-webkit-text-size-adjust: none;*/ /* prevent webkit from resizing text to fit */15 -webkit-tap-highlight-color: rgba(0,0,0,0.15); /* make transparent link selection, adjust last value opacity 0 to 1.0 */16 /*-webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */17 }18 @media screen and (-webkit-device-pixel-ratio: 2) {19 #header{background-image:transparent url('webBgLine@2x.png') repeat-x scroll center bottom;-webkit-background-size:320px 1px;}20 }Css.css
這樣我們就可以通過Java端實現動態插入了,由于是加載了靜態模板,滑動起來也不會出現卡頓。
1 InputStream inputStream = getAssets().open("NewsDetail.html");2 byte[] temp = AppUtil.readInputStream(inputStream);3 String content = new String(temp);4 mWebView.loadDataWithBaseURL("file:///android_asset/", content.replace("#title#", mBlog.getBlogTitle()).replace("#author#", "作者:" + mBlog.getAuthorName()).replace("#info#", "推薦:" + mBlog.getBlogDiggs() + "/t/t評論:" + mBlog.getBlogComments() + "/t/t瀏覽:" + mBlog.getBlogViews()).replace("#time#", TimeUtil.ParseDateToString(TimeUtil.ParseUTCDate(mBlog.getBlogPublished())))5 .replace("#content#", mInfo), "text/html", "utf-8", null);
看下布局文件,這里用到了一個Material Design里的FAB(Floating Action Button)浮動按鈕,這個控件很簡單,只需要設置對應的屬性,然后其他用法和普通控件是保持一致的。
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:fitsSystemWindows="true" 6 android:orientation="vertical"> 7 8 <!--ToolBar--> 9 <include layout="@layout/activity_toolbar" />10 11 12 <FrameLayout13 android:layout_width="match_parent"14 android:layout_height="match_parent">15 16 <WebView17 android:id="@+id/wv_blog_content"18 android:layout_width="match_parent"19 android:layout_height="match_parent"20 android:scrollbars="vertical"21 />22 23 <ProgressBar24 android:id="@+id/pb_bar"25 style="@style/MyProgressBar"26 android:layout_width="match_parent"27 android:layout_height="wrap_content"28 android:layout_gravity="center_vertical"29 android:indeterminate="true" />30 31 <android.support.design.widget.FloatingActionButton32 android:id="@+id/fab_comment"33 android:layout_width="wrap_content"34 android:layout_height="wrap_content"35 android:layout_gravity="right|bottom"36 android:layout_marginBottom="30dp"37 android:layout_marginRight="20dp"38 android:src="@mBlogContent.xml這里只是先簡單的一個圖片替換和Toast的顯示,具體操作等下篇文章我們用到數據庫的時候再說。
1 mFloatingActionButton = (FloatingActionButton) findViewById(R.id.fab_comment); 2 3 mFloatingActionButton.setOnClickListener(new View.OnClickListener() { 4 @Override 5 public void onClick(View v) { 6 if (!isLike) { 7 isLike = true; 8 mFloatingActionButton.setImageResource(R.mipmap.ic_grade_white_24dp); 9 Toast.makeText(BlogContentActivity.this, "文章已收藏", Toast.LENGTH_SHORT).show();10 //添加收藏文章到數據庫11 } else {12 isLike = false;13 mFloatingActionButton.setImageResource(R.mipmap.ic_star_outline_white_24dp);14 Toast.makeText(BlogContentActivity.this, "取消文章收藏", Toast.LENGTH_SHORT).show();15 //從數據庫刪除收藏文章16 }17 }18 });然后這里是關于WebView的設置,大家也可以參考這篇文章自己做設置:http://www.pedant.cn/2014/09/10/webview-optimize-points/#0-tsina-1-5518-397232819ff9a47a7b7e80a40613cfe1
1 mWebView = (WebView) findViewById(R.id.wv_blog_content); 2 //避免中文亂碼 3 mWebView.getSettings().setDefaultTextEncodingName("utf-8"); 4 //適配低版本,關閉圖片自動加載 5 if (Build.VERSION.SDK_INT >= 19) { 6 mWebView.getSettings().setLoadsImagesAutomatically(true); 7 } else { 8 mWebView.getSettings().setLoadsImagesAutomatically(false); 9 }10 //等頁面加載完畢再加載圖片11 WebViewClient webViewClient = new WebViewClient() {12 @Override13 public void onPageFinished(WebView view, String url) {14 //關閉Progress15 mProgressBar.setVisibility(View.GONE);16 if (!view.getSettings().getLoadsImagesAutomatically()) {17 view.getSettings().setLoadsImagesAutomatically(true);18 }19 }20 };21 mWebView.setWebViewClient(webViewClient);22 mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_OVERLAY);23 mWebView.getSettings().setJavascriptEnabled(false);24 mWebView.getSettings().setSupportZoom(false);25 mWebView.getSettings().setBuiltInZoomControls(false);26 mWebView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);27 mWebView.getSettings().setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);3、關于評論詳情頁面的實現
這里是關于博文詳情的接口:http://wcf.open.VEVb.com/blog/post/{POSTID}/comments/{PAGEINDEX}/{PAGESIZE}(POSTID代表文章Id,PAGEINDEX代表評論頁數,PAGESIZE代表評論每頁展示的條數)這里不得不吐槽下接口的殘疾,都沒提供用戶頭像數據,只能用默認灰白頭像做了。
這個就很簡單了,直接可以復制我們之前做首頁列表的XML布局文件甚至是Fragment里的主邏輯代碼,只需要做一下頁面內容的小改動就可以了,下面直接給代碼。
博文評論主頁樣式:
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:fitsSystemWindows="true" 6 android:gravity="center" 7 android:orientation="vertical"> 8 9 <!--ToolBar-->10 <include layout="@layout/activity_toolbar" />11 <android.support.v4.widget.SwipeRefreshLayout12 android:id="@+id/swipe_refresh"13 android:layout_width="match_parent"14 android:layout_height="match_parent"15 android:layout_margin="4dp">16 17 <android.support.v7.widget.RecyclerView18 android:id="@+id/rv_view"19 android:layout_width="match_parent"20 android:layout_height="match_parent"21 android:background="@color/md_grey_200"22 android:scrollbars="vertical"23 />24 </android.support.v4.widget.SwipeRefreshLayout>25 26 <com.lcw.rabbit.myblog.view.MyProgressBar27 android:id="@+id/progressbar"28 android:layout_width="match_parent"29 android:layout_height="20dp"30 android:layout_gravity="bottom"31 android:visibility="gone"32 />33 34 35 36 </LinearLayout>activity_blog_comment.xml列表樣式和詳細內容樣式:
1 <android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 android:id="@+id/cv_cardview" 4 android:layout_width="match_parent" 5 android:layout_height="wrap_content" 6 android:layout_margin="8dp" 7 android:gravity="center" 8 app:cardCornerRadius="6dp"> 9 10 <include layout="@layout/recyclerview_item_blogcommentlist_content" />11 12 </android.support.v7.widget.CardView>recyclerview_blogcommentlist.xml1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:app="http://schemas.android.com/apk/res-auto" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:background="?android:selectableItemBackground" 6 android:orientation="horizontal" 7 android:padding="3dp"> 8 9 <!--信息內容-->10 <LinearLayout11 android:layout_width="0dp"12 android:layout_height="wrap_content"13 android:layout_marginLeft="3dp"14 android:layout_weight="1"15 android:orientation="vertical">16 17 <LinearLayout18 android:layout_width="wrap_content"19 android:layout_height="wrap_content"20 android:layout_marginLeft="3dp"21 android:layout_weight="1"22 android:padding="3dp"23 android:orientation="horizontal">24 25 <!--頭像-->26 <com.makeramen.roundedimageview.RoundedImageView27 android:id="@+id/iv_userhead"28 android:layout_width="25dp"29 android:layout_height="25dp"30 android:layout_gravity="center_vertical"31 android:layout_marginRight="5dp"32 android:src="@mipmap/avatar_default"33 app:riv_border_color="#ffffff"34 app:riv_border_width="2dip"35 app:riv_corner_radius="30dip"36 app:riv_mutate_background="true"37 app:riv_oval="true"38 app:riv_tile_mode="repeat" />39 40 <TextView41 android:id="@+id/tv_name"42 android:layout_width="match_parent"43 android:layout_height="wrap_content"44 android:layout_gravity="center_vertical"45 android:layout_marginTop="2dp"46 android:layout_weight="1"47 android:ellipsize="end"48 android:singleLine="true"49 50 android:text="用戶昵稱"51 android:textColor="@color/md_green_700"52 android:textSize="16sp"53 android:textStyle="bold" />54 </LinearLayout>55 56 <TextView57 android:id="@+id/tv_comment"58 android:layout_width="match_parent"59 android:layout_height="wrap_content"60 android:layout_weight="1"61 android:maxLines="3"62 android:layout_marginLeft="3dp"63 android:text="文章評論內容"64 android:textSize="16sp" />65 66 <LinearLayout67 android:layout_width="match_parent"68 android:layout_height="match_parent"69 android:layout_margin="1dp"70 android:layout_weight="1"71 android:padding="3dp"72 android:orientation="horizontal">73 74 <TextView75 android:layout_width="wrap_content"76 android:layout_height="match_parent"77 android:gravity="center_vertical"78 android:text="評論時間:"79 android:textColor="@color/md_grey_500"80 android:textSize="12sp" />81 82 <TextView83 android:id="@+id/tv_time"84 android:layout_width="wrap_content"85 android:layout_height="match_parent"86 android:layout_marginRight="5dp"87 android:gravity="center_vertical"88 android:textColor="@color/md_grey_500"89 android:textSize="12sp" />90 91 </LinearLayout>92 93 </LinearLayout>94 95 96 </LinearLayout>recyclerview_blogcommentlist_content.xml主代碼:
1 package com.lcw.rabbit.myblog; 2 3 import android.os.Bundle; 4 import android.support.v4.widget.SwipeRefreshLayout; 5 import android.support.v7.app.AppCompatActivity; 6 import android.support.v7.widget.DefaultItemAnimator; 7 import android.support.v7.widget.LinearLayoutManager; 8 import android.support.v7.widget.RecyclerView; 9 import android.support.v7.widget.Toolbar; 10 import android.view.View; 11 12 import com.android.volley.Request; 13 import com.android.volley.Response; 14 import com.android.volley.VolleyError; 15 import com.android.volley.toolbox.StringRequest; 16 import com.lcw.rabbit.myblog.adapter.BlogCommentListAdapter; 17 import com.lcw.rabbit.myblog.entity.Comment; 18 import com.lcw.rabbit.myblog.parser.BlogCommentXmlParser; 19 import com.lcw.rabbit.myblog.utils.VolleyRequestQueueManager; 20 import com.lcw.rabbit.myblog.view.MyProgressBar; 21 import com.mugen.Mugen; 22 import com.mugen.MugenCallbacks; 23 import com.mugen.attachers.BaseAttacher; 24 25 import org.xmlpull.v1.XmlPullParserException; 26 27 import java.io.ByteArrayInputStream; 28 import java.io.IOException; 29 import java.util.ArrayList; 30 import java.util.List; 31 32 /** 33 * 博文評論頁 34 */ 35 public class BlogCommentActivity extends AppCompatActivity { 36 private Toolbar mToolbar; 37 private SwipeRefreshLayout mSwipeRefreshLayout; 38 private RecyclerView mRecyclerView; 39 private BlogCommentListAdapter mBlogCommentListAdapter; 40 //無限滾動 41 private BaseAttacher mBaseAttacher; 42 private MyProgressBar myProgressBar; 43 44 private String mBlogId; 45 private List<Comment> mComments; 46 47 //默認第一頁 48 private int currentPage = 1; 49 //是否正在加載 50 private boolean isLoading = false; 51 52 53 @Override 54 protected void onCreate(Bundle savedInstanceState) { 55 super.onCreate(savedInstanceState); 56 setContentView(R.layout.activity_blog_comment); 57 initView(); 58 initData(); 59 initAction(); 60 getBlogComment(mBlogId, 1, 10); 61 } 62 63 private void initAction() { 64 //設置下拉刷新 65 mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { 66 @Override 67 public void onRefresh() { 68 getBlogComment(mBlogId, 1, 10); 69 } 70 }); 71 72 73 //設置無限滾動,上拉加載 74 mBaseAttacher = Mugen.with(mRecyclerView, new MugenCallbacks() { 75 @Override 76 public void onLoadMore() { 77 //加載更多 78 isLoading = true; 79 mBaseAttacher.setLoadMoreEnabled(false); 80 myProgressBar.setVisibility(View.VISIBLE); 81 getBlogComment(mBlogId, (currentPage + 1), 10); 82 } 83 84 @Override 85 public boolean isLoading() { 86 return isLoading; 87 } 88 89 @Override 90 public boolean hasLoadedAllItems() { 91 return isLoading; 92 } 93 }).start(); 94 //離底部一項的時候加載更多 95 mBaseAttacher.setLoadMoreOffset(1); 96 } 97 98 /** 99 * 獲取Intent傳遞過來的數據100 */101 private void initData() {102 mBlogId = getIntent().getExtras().getString("blogId");103 //設置空數據源104 mComments=new ArrayList<Comment>();105 mBlogCommentListAdapter = new BlogCommentListAdapter(this,mComments);106 mRecyclerView.setAdapter(mBlogCommentListAdapter);107 }108 109 110 /**111 * 獲取博客評論數據并設置112 * @param blogId113 * @param page114 * @param num115 */116 private void getBlogComment(String blogId, final int page, int num) {117 //更新當前頁數118 currentPage = page;119 StringRequest request = new StringRequest(Request.Method.GET, "http://wcf.open.VEVb.com/blog/post/" + blogId + "/comments/" + page + "/" + num, new Response.Listener<String>() {120 @Override121 public void onResponse(String s) {122 try {123 //獲取評論數據數據并解析XML124 ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes());125 List<Comment> comments = BlogCommentXmlParser.getBlogComment(inputStream, "utf-8");126 if (page == 1) {127 //清空之前的數據預防重復加載128 mComments.clear();129 }130 for (Comment comment : comments) {131 //整理數據源132 mComments.add(comment);133 }134 135 if (mBlogCommentListAdapter == null) {136 //如果Adapter不存在137 mBlogCommentListAdapter = new BlogCommentListAdapter(BlogCommentActivity.this,mComments);138 mRecyclerView.setAdapter(mBlogCommentListAdapter);139 } else {140 //存在通知adatper數據源更新141 mBlogCommentListAdapter.refreshData(mComments);142 143 }144 //關閉下拉刷新樣式145 mSwipeRefreshLayout.setRefreshing(false);146 isLoading = false;147 myProgressBar.setVisibility(View.GONE);148 mBaseAttacher.setLoadMoreEnabled(true);149 150 151 } catch (XmlPullParserException e) {152 e.printStackTrace();153 } catch (IOException e) {154 e.printStackTrace();155 }156 }157 }, new Response.ErrorListener() {158 @Override159 public void onErrorResponse(VolleyError volleyError) {160 161 }162 });163 VolleyRequestQueueManager.addRequest(request, "BlogCommentList");164 165 }166 167 private void initView() {168 mToolbar = (Toolbar) findViewById(R.id.activity_toolbar);169 mToolbar.setTitle("文章評論");170 setSupportActionBar(mToolbar);171 getSupportActionBar().setDisplayHomeAsUpEnabled(true);172 173 mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);174 //設置拉下刷新滾動條顏色175 mSwipeRefreshLayout.setColorSchemeResources(android.R.color.holo_blue_light, android.R.color.holo_red_light, android.R.color.holo_orange_light, android.R.color.holo_green_light);176 mRecyclerView = (RecyclerView) findViewById(R.id.rv_view);177 mRecyclerView.setLayoutManager(new LinearLayoutManager(this));178 mRecyclerView.setItemAnimator(new DefaultItemAnimator());179 myProgressBar = (MyProgressBar)findViewById(R.id.progressbar);180 181 182 }183 184 185 }適配器代碼:
1 package com.lcw.rabbit.myblog.adapter; 2 3 import android.content.Context; 4 import android.content.res.Resources; 5 import android.graphics.Bitmap; 6 import android.graphics.BitmapFactory; 7 import android.support.v7.widget.RecyclerView; 8 import android.text.Html; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.ViewGroup; 12 import android.widget.TextView; 13 14 import com.lcw.rabbit.myblog.R; 15 import com.lcw.rabbit.myblog.entity.Comment; 16 import com.lcw.rabbit.myblog.utils.TimeUtil; 17 import com.makeramen.roundedimageview.RoundedImageView; 18 19 import java.util.List; 20 21 /** 22 * 推薦博文評論列表適配器 23 * Created by Lichenwei 24 * Date: 2015-08-16 25 * Time: 22:34 26 */ 27 public class BlogCommentListAdapter extends RecyclerView.Adapter<BlogCommentListAdapter.RecyclerViewViewHolder> { 28 29 private Context mContext; 30 private List<Comment> mComments; 31 32 public BlogCommentListAdapter(Context context, List<Comment> comments) { 33 this.mContext = context; 34 this.mComments = comments; 35 } 36 37 /** 38 * 設置新的數據源,提醒adatper更新 39 * 40 * @param comments 41 */ 42 public void refreshData(List<Comment> comments) { 43 this.mComments = comments; 44 this.notifyDataSetChanged(); 45 } 46 47 /** 48 * 創建ViewHolder 49 * 50 * @param viewGroup 51 * @param i 52 * @return 53 */ 54 @Override 55 public RecyclerViewViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 56 View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_item_blogcommentlist, viewGroup, false); 57 return new RecyclerViewViewHolder(view); 58 } 59 60 /** 61 * 根據資源ID返回Bitmap對象 62 * 63 * @param resId 64 * @return 65 */ 66 public Bitmap getBitmapFromRes(int resId) { 67 Resources res = mContext.getResources(); 68 return BitmapFactory.decodeResource(res, resId); 69 70 } 71 72 /** 73 * 綁定數據 74 * 75 * @param viewholder 76 * @param i 77 */ 78 @Override 79 public void onBindViewHolder(RecyclerViewViewHolder viewholder, int i) { 80 //設置頭像 81 // if (mAuthors.get(i).getAuthorPic() != null && !"".equals(mAuthors.get(i).getAuthorPic())) { 82 // ImageCacheManager.loadImage(mAuthors.get(i).getAuthorPic(), viewholder.mUserhead, getBitmapFromRes(R.mipmap.avatar_default), getBitmapFromRes(R.mipmap.avatar_default)); 83 // } else { 84 // viewholder.mUserhead.setImageResource(R.mipmap.avatar_default); 85 // } 86 viewholder.mName.setText(mComments.get(i).getAuthorName()); 87 //處理評論內容里的Html代碼 88 viewholder.mContent.setText(Html.fromHtml(mComments.get(i).getCommentContent())); 89 //處理日期特殊格式 90 viewholder.mTime.setText(TimeUtil.DateToChineseString(TimeUtil.ParseUTCDate(mComments.get(i).getCommentTime()))); 91 } 92 93 @Override 94 public int getItemCount() { 95 return mComments.size(); 96 } 97 98 /** 99 * 自定義ViewHolder100 */101 public static class RecyclerViewViewHolder extends RecyclerView.ViewHolder {102 private RoundedImageView mUserhead;103 private TextView mName;104 private TextView mContent;105 private TextView mTime;106 107 public RecyclerViewViewHolder(View view) {108 super(view);109 mUserhead = (RoundedImageView) view.findViewById(R.id.iv_userhead);110 mName = (TextView) view.findViewById(R.id.tv_name);111 mContent = (TextView) view.findViewById(R.id.tv_comment);112 mTime = (TextView) view.findViewById(R.id.tv_time);113 114 }115 116 117 }118 }獲取博文詳情XML解析:
1 package com.lcw.rabbit.myblog.parser; 2 3 import com.lcw.rabbit.myblog.entity.Comment; 4 5 import org.xmlpull.v1.XmlPullParser; 6 import org.xmlpull.v1.XmlPullParserException; 7 import org.xmlpull.v1.XmlPullParserFactory; 8 9 import java.io.IOException;10 import java.io.InputStream;11 import java.util.ArrayList;12 import java.util
新聞熱點
疑難解答