在上篇文章《安卓開發筆記——打造屬於本身的博客園APP(三)》中,咱們對博客文章的詳情頁和評論頁進行了實現,慢慢的一個APP已經出現雛形了,固然這只是完成了"表面效果",要真正作好一個APP並非一件很輕鬆的事情,有不少細節須要咱們一點一滴的去完善。html
好了,來說下今天要完成的效果,在優化了以前部分代碼的前提下,今天來講下關於博客搜索和博客詳情頁的實現,依舊國際慣例,來看下效果圖:(動態圖片比較大,加載須要點時間)java
效果比較簡單,不少東西咱們仍是能夠複用以前的代碼,畢竟這種列表長得都差很少,而後大體功能基本完成了,從下篇文章開始能夠引入咱們的數據庫了,開始實現緩存操做。android
一、關於搜索頁面的實現:數據庫
很簡單,分紅兩部分,上面一個EditText,下面一個RecyclerView,當咱們剛進入頁面的時候默認展現博客園給咱們的推薦用戶,當搜索的時候更新列表數據。瀏覽器
這裏是關於博客園推薦用戶的接口: http://wcf.open.cnblogs.com/blog/bloggers/recommend/{PAGEINDEX}/{PAGESIZE} {PAGEINDEX}表明頁碼,{PAGESIZE}表明每頁展現的條數緩存
這裏是搜索頁面的主佈局文件:app
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 8 <!--ToolBar--> 9 <include layout="@layout/activity_toolbar" /> 10 11 <LinearLayout 12 android:layout_width="match_parent" 13 android:layout_height="wrap_content" 14 android:background="@color/md_green_700" 15 android:paddingBottom="10dp" 16 android:paddingLeft="20dp" 17 android:paddingRight="20dp" 18 android:paddingTop="10dp"> 19 20 <RelativeLayout 21 android:layout_width="match_parent" 22 android:layout_height="40dp" 23 android:background="@drawable/bg_search" 24 android:gravity="center_vertical"> 25 26 <ImageButton 27 android:id="@+id/ib_search" 28 android:layout_width="wrap_content" 29 android:layout_height="wrap_content" 30 android:layout_alignParentRight="true" 31 android:background="@drawable/bt_search_selector" /> 32 33 <EditText 34 android:id="@+id/et_text" 35 android:layout_width="match_parent" 36 android:layout_height="wrap_content" 37 android:layout_toLeftOf="@id/ib_search" 38 android:background="@null" 39 android:hint="搜索其餘博客" /> 40 </RelativeLayout> 41 </LinearLayout> 42 43 <FrameLayout 44 android:layout_width="match_parent" 45 android:layout_height="match_parent"> 46 47 <android.support.v7.widget.RecyclerView 48 android:id="@+id/rv_view" 49 android:layout_width="match_parent" 50 android:layout_height="match_parent" 51 android:background="@color/md_grey_200" 52 android:scrollbars="none" /> 53 54 <com.lcw.rabbit.myblog.view.MyProgressBar 55 android:id="@+id/progressbar" 56 android:layout_width="match_parent" 57 android:layout_height="20dp" 58 android:layout_gravity="bottom" 59 android:visibility="gone" /> 60 </FrameLayout> 61 </LinearLayout>
這裏是下面RecyclerView列表的Item佈局:ide
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:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:layout_margin="8dp" 6 android:gravity="center" 7 app:cardCornerRadius="6dp"> 8 9 <include layout="@layout/recyclerview_item_authorlist_content" /> 10 11 </android.support.v7.widget.CardView>
這裏是Item佈局的詳細:工具
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="wrap_content" 5 android:background="?android:selectableItemBackground" 6 android:orientation="horizontal" 7 android:padding="3dp"> 8 <!--頭像--> 9 <com.makeramen.roundedimageview.RoundedImageView 10 android:id="@+id/iv_userhead" 11 android:layout_width="60dp" 12 android:layout_height="60dp" 13 android:layout_gravity="center_vertical" 14 android:layout_marginRight="5dp" 15 android:src="@mipmap/avatar_default" 16 app:riv_border_color="#ffffff" 17 app:riv_border_width="2dip" 18 app:riv_corner_radius="30dip" 19 app:riv_mutate_background="true" 20 app:riv_oval="true" 21 app:riv_tile_mode="repeat" /> 22 <!--信息內容--> 23 <LinearLayout 24 android:layout_width="0dp" 25 android:layout_height="wrap_content" 26 android:layout_marginLeft="3dp" 27 android:layout_weight="1" 28 android:orientation="vertical"> 29 30 <TextView 31 android:id="@+id/tv_name" 32 android:layout_width="match_parent" 33 android:layout_height="wrap_content" 34 android:layout_marginTop="2dp" 35 android:layout_weight="1" 36 android:ellipsize="end" 37 android:singleLine="true" 38 android:text="測試標題" 39 android:textColor="@color/md_grey_900" 40 android:textSize="16sp" 41 android:textStyle="bold" /> 42 43 <TextView 44 android:id="@+id/tv_url" 45 android:layout_width="match_parent" 46 android:layout_height="wrap_content" 47 android:layout_weight="1" 48 android:maxLines="3" 49 android:text="瀏覽器類型判斷方法有兩種:根據瀏覽器特性來判斷根據來檢測具體使用哪一種方法要看具體需求的場景場景一:爲了讓用戶有較流暢完整的體驗,在站點提示用戶使用或者,這種場景對瀏覽器類型的判斷並不是特別嚴格,可使用檢測的方法。(由於不少瀏覽器廠商會篡改標識)。場景二...." 50 android:textSize="14sp" /> 51 52 <LinearLayout 53 android:layout_width="match_parent" 54 android:layout_height="match_parent" 55 android:layout_margin="1dp" 56 android:layout_weight="1" 57 android:orientation="horizontal"> 58 59 <TextView 60 android:layout_width="wrap_content" 61 android:layout_height="match_parent" 62 android:gravity="center_vertical" 63 android:text="博文數:" 64 android:textColor="@color/md_grey_500" 65 android:textSize="12sp" /> 66 67 <TextView 68 android:id="@+id/tv_sum" 69 android:layout_width="wrap_content" 70 android:layout_height="match_parent" 71 android:layout_marginRight="5dp" 72 android:gravity="center_vertical" 73 android:textColor="@color/md_grey_500" 74 android:textSize="12sp" /> 75 76 <TextView 77 android:layout_width="wrap_content" 78 android:layout_height="match_parent" 79 android:gravity="center_vertical" 80 android:text="最後更新:" 81 android:textColor="@color/md_grey_500" 82 android:textSize="12sp" /> 83 84 <TextView 85 android:id="@+id/tv_time" 86 android:layout_width="wrap_content" 87 android:layout_height="match_parent" 88 android:layout_marginRight="5dp" 89 android:textColor="@color/md_grey_500" 90 android:textSize="12sp" /> 91 92 </LinearLayout> 93 94 </LinearLayout> 95 96 <!--操做按鈕--> 97 <ImageButton 98 android:id="@+id/ib_more" 99 android:layout_width="25dp" 100 android:layout_height="match_parent" 101 android:background="?android:selectableItemBackground" 102 android:gravity="center_horizontal" 103 android:src="@mipmap/triangle" /> 104 </LinearLayout>
關於博客園推薦博客的接口數據XML解析,和咱們以前在作博文列表數據的解析都是同樣的,只不過是XML的節點不一樣,這裏貼出解析代碼:佈局
1 package com.lcw.rabbit.myblog.parser; 2 3 import com.lcw.rabbit.myblog.entity.Author; 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.List; 13 14 /** 15 * 對博客做者(列表)xml數據的解析 16 * Created by Lichenwei 17 * Date: 2015-08-17 18 * Time: 13:32 19 */ 20 public class AuthorListXmlParser { 21 22 23 /** 24 * 用於解析博客做者(列表)的xml,返回Avatar的List集合對象 25 * 26 * @param inputStream 27 * @param encode 28 * @return 29 * @throws XmlPullParserException 30 * @throws IOException 31 */ 32 public static List<Author> getListAuthor(InputStream inputStream, String encode) throws XmlPullParserException, IOException { 33 34 List<Author> mAuthors = null; 35 Author mAuthor = null; 36 37 //獲取XmlPullParser實例 38 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 39 XmlPullParser parser = factory.newPullParser(); 40 parser.setInput(inputStream, encode); 41 //獲取解析事件 42 int eventType = parser.getEventType(); 43 //當xml文檔未到尾端時 44 while (eventType != XmlPullParser.END_DOCUMENT) { 45 switch (eventType) { 46 //解析根標籤的時候,實例化集合 47 case XmlPullParser.START_DOCUMENT: 48 mAuthors = new ArrayList<Author>(); 49 mAuthor = new Author(); 50 51 break; 52 case XmlPullParser.START_TAG: 53 //當解析到entry標籤的時候,實例化Avatar對象 54 if ("entry".equals(parser.getName())) { 55 mAuthor = new Author(); 56 } 57 if ("id".equals(parser.getName())) { 58 parser.next(); 59 mAuthor.setAuthorUrl(parser.getText()); 60 } else if ("title".equals(parser.getName())) { 61 parser.next(); 62 if (parser.getText().indexOf("博客園") == -1) { 63 mAuthor.setAuthorName(parser.getText()); 64 } 65 } else if ("avatar".equals(parser.getName())) { 66 parser.next(); 67 mAuthor.setAuthorPic(parser.getText()); 68 } else if ("blogapp".equals(parser.getName())) { 69 parser.next(); 70 mAuthor.setBlogApp(parser.getText()); 71 } else if ("postcount".equals(parser.getName())) { 72 parser.next(); 73 mAuthor.setBlogCount(parser.getText()); 74 } else if ("updated".equals(parser.getName())) { 75 parser.next(); 76 //區分日期格式 77 if (parser.getText().indexOf("+") != -1) { 78 mAuthor.setUpdated(parser.getText()); 79 } 80 81 } 82 break; 83 case XmlPullParser.END_TAG: 84 //當解析到entry標籤結束的時候添加入Avatar集合,清空Avatar對象 85 if ("entry".equals(parser.getName())) { 86 mAuthors.add(mAuthor); 87 mAuthor = null; 88 } 89 break; 90 91 } 92 //手動跳轉第一次遍歷 93 eventType = parser.next(); 94 } 95 96 97 return mAuthors; 98 99 } 100 101 }
這裏是搜索主頁面代碼,當咱們點擊搜索按鈕的時候,獲取輸入框的博客關鍵字,進行搜索,將獲得的數據更新數據源從新展現在RecyclerView。
關於搜索博客關鍵字的接口:http://wcf.open.cnblogs.com/blog/bloggers/search?t={TERM} {TERM}表明做者名(多關鍵字匹配),搜索到的XML數據信息恰好又和咱們前面的推薦博客內容格式一致,因此咱們能夠複用以前的解析工具類,而後同樣具有上拉刷新和下拉加載功能:
1 package com.lcw.rabbit.myblog; 2 3 import android.content.Intent; 4 import android.os.Bundle; 5 import android.support.v7.app.AppCompatActivity; 6 import android.support.v7.widget.LinearLayoutManager; 7 import android.support.v7.widget.RecyclerView; 8 import android.support.v7.widget.Toolbar; 9 import android.view.View; 10 import android.widget.EditText; 11 import android.widget.ImageButton; 12 import android.widget.Toast; 13 14 import com.afollestad.materialdialogs.MaterialDialog; 15 import com.android.volley.Request; 16 import com.android.volley.Response; 17 import com.android.volley.VolleyError; 18 import com.android.volley.toolbox.StringRequest; 19 import com.lcw.rabbit.myblog.adapter.AuthorListAdapter; 20 import com.lcw.rabbit.myblog.entity.Author; 21 import com.lcw.rabbit.myblog.entity.Blog; 22 import com.lcw.rabbit.myblog.parser.AuthorListXmlParser; 23 import com.lcw.rabbit.myblog.utils.VolleyRequestQueueManager; 24 import com.lcw.rabbit.myblog.view.MyProgressBar; 25 import com.mugen.Mugen; 26 import com.mugen.MugenCallbacks; 27 import com.mugen.attachers.BaseAttacher; 28 29 import org.xmlpull.v1.XmlPullParserException; 30 31 import java.io.ByteArrayInputStream; 32 import java.io.IOException; 33 import java.util.ArrayList; 34 import java.util.List; 35 36 /** 37 * 博客搜索頁 38 */ 39 public class SearchActivity extends AppCompatActivity { 40 41 //界面控件 42 private Toolbar mToolbar; 43 private EditText mEditText; 44 private ImageButton mImageButton; 45 private RecyclerView mRecyclerView; 46 private MaterialDialog materialDialog; 47 //無限滾動 48 private BaseAttacher mBaseAttacher; 49 private MyProgressBar myProgressBar; 50 51 //數據源 52 private AuthorListAdapter mAuthorListAdapter; 53 private List<Author> mAuthors; 54 55 //標誌變量 56 private boolean isLoading = false; 57 private int currentPage = 1; 58 59 60 @Override 61 protected void onCreate(Bundle savedInstanceState) { 62 super.onCreate(savedInstanceState); 63 setContentView(R.layout.activity_search); 64 initView(); 65 initData(); 66 initAction(); 67 } 68 69 /** 70 * 設置控件監聽 71 */ 72 private void initAction() { 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 getData((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 mImageButton.setOnClickListener(new View.OnClickListener() { 99 @Override 100 public void onClick(View v) { 101 materialDialog = new MaterialDialog.Builder(SearchActivity.this).content("內容加載中..").progress(true, 0).show(); 102 String name = mEditText.getText().toString(); 103 getDataByName(name.trim()); 104 } 105 }); 106 107 //設置RecyclerView點擊監聽 108 mAuthorListAdapter.setRecyclerViewListener(new AuthorListAdapter.RecyclerViewListener() { 109 @Override 110 public void setOnclickListener(View view, String value) { 111 //封裝Bolg對象傳遞 112 Blog blog = new Blog(); 113 blog.setBlogApp(mAuthors.get(Integer.parseInt(value)).getBlogApp()); 114 blog.setAuthorName(mAuthors.get(Integer.parseInt(value)).getAuthorName()); 115 Intent intent = new Intent(); 116 intent.setClass(SearchActivity.this, AuthorActivity.class); 117 Bundle bundle = new Bundle(); 118 bundle.putSerializable("blog", blog); 119 intent.putExtras(bundle); 120 startActivity(intent); 121 } 122 }); 123 } 124 125 /** 126 * 初始化控件 127 */ 128 private void initView() { 129 //ToolBar 130 mToolbar = (Toolbar) findViewById(R.id.activity_toolbar); 131 setSupportActionBar(mToolbar); 132 //須要放在setSupportActionBar後設置 133 mToolbar.setNavigationOnClickListener(new View.OnClickListener() { 134 @Override 135 public void onClick(View v) { 136 finish(); 137 } 138 }); 139 getSupportActionBar().setTitle("博客搜索"); 140 getSupportActionBar().setDisplayHomeAsUpEnabled(true); 141 142 //輸入搜索 143 mEditText = (EditText) findViewById(R.id.et_text); 144 mImageButton = (ImageButton) findViewById(R.id.ib_search); 145 //列表 146 mRecyclerView = (RecyclerView) findViewById(R.id.rv_view); 147 mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 148 //當高度肯定,提升效率 149 mRecyclerView.setHasFixedSize(true); 150 //友好提醒 151 myProgressBar = (MyProgressBar) findViewById(R.id.progressbar); 152 153 } 154 155 /** 156 * 初始化數據 157 */ 158 private void initData() { 159 //顯示下拉刷新樣式 160 mAuthors = new ArrayList<Author>(); 161 //設置空數據 162 mAuthorListAdapter = new AuthorListAdapter(this, mAuthors); 163 mRecyclerView.setAdapter(mAuthorListAdapter); 164 getData(1, 10); 165 } 166 167 /** 168 * 根據博主暱稱搜索博客 169 * 170 * @param name 171 */ 172 public void getDataByName(String name) { 173 String url = "http://wcf.open.cnblogs.com/blog/bloggers/search?t=" + name; 174 StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { 175 @Override 176 public void onResponse(String s) { 177 try { 178 ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes()); 179 List<Author> authors = AuthorListXmlParser.getListAuthor(inputStream, "utf-8"); 180 if (authors.size() != 0) { 181 //清空以前的數據預防重複加載 182 mAuthors.clear(); 183 for (Author author : authors) { 184 mAuthors.add(author); 185 } 186 187 if (mAuthorListAdapter == null) { 188 mAuthorListAdapter = new AuthorListAdapter(SearchActivity.this, mAuthors); 189 mRecyclerView.setAdapter(mAuthorListAdapter); 190 } else { 191 //通知adatper數據源更新 192 mAuthorListAdapter.refreshData(mAuthors); 193 } 194 195 materialDialog.dismiss(); 196 } else { 197 //若是匹配不到關鍵字 198 Toast.makeText(SearchActivity.this, "找不到相關用戶,請從新搜索", Toast.LENGTH_SHORT).show(); 199 materialDialog.dismiss(); 200 } 201 } catch (XmlPullParserException e) { 202 e.printStackTrace(); 203 } catch (IOException e) { 204 e.printStackTrace(); 205 } 206 } 207 }, new Response.ErrorListener() { 208 @Override 209 public void onErrorResponse(VolleyError volleyError) { 210 Toast.makeText(SearchActivity.this, volleyError.getMessage(), Toast.LENGTH_SHORT).show(); 211 } 212 }); 213 214 VolleyRequestQueueManager.addRequest(request, "getAuthorList"); 215 216 } 217 218 219 /** 220 * 獲取推薦數據 221 * 222 * @param page 223 * @param num 224 */ 225 public void getData(final int page, int num) { 226 this.currentPage = page; 227 String url = "http://wcf.open.cnblogs.com/blog/bloggers/recommend/" + page + "/" + num; 228 StringRequest request = new StringRequest(Request.Method.GET, url, new Response.Listener<String>() { 229 @Override 230 public void onResponse(String s) { 231 try { 232 ByteArrayInputStream inputStream = new ByteArrayInputStream(s.getBytes()); 233 List<Author> authors = AuthorListXmlParser.getListAuthor(inputStream, "utf-8"); 234 if (page == 1) { 235 //清空以前的數據預防重複加載 236 mAuthors.clear(); 237 } 238 for (Author author : authors) { 239 mAuthors.add(author); 240 } 241 242 if (mAuthorListAdapter == null) { 243 mAuthorListAdapter = new AuthorListAdapter(SearchActivity.this, mAuthors); 244 mRecyclerView.setAdapter(mAuthorListAdapter); 245 } else { 246 //通知adatper數據源更新 247 mAuthorListAdapter.refreshData(mAuthors); 248 } 249 250 isLoading = false; 251 mBaseAttacher.setLoadMoreEnabled(true); 252 myProgressBar.setVisibility(View.GONE); 253 254 } catch (XmlPullParserException e) { 255 e.printStackTrace(); 256 } catch (IOException e) { 257 e.printStackTrace(); 258 } 259 } 260 }, new Response.ErrorListener() { 261 @Override 262 public void onErrorResponse(VolleyError volleyError) { 263 Toast.makeText(SearchActivity.this, volleyError.getMessage(), Toast.LENGTH_SHORT).show(); 264 } 265 }); 266 267 VolleyRequestQueueManager.addRequest(request, "getAuthorList"); 268 269 270 } 271 272 }
這裏是博客列表的適配器類,和以前的博文列表同樣,咱們須要本身添加點擊監聽,再點擊Item項的時候將Blog對象傳遞:
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.view.LayoutInflater; 9 import android.view.View; 10 import android.view.ViewGroup; 11 import android.widget.ImageButton; 12 import android.widget.TextView; 13 14 import com.lcw.rabbit.myblog.R; 15 import com.lcw.rabbit.myblog.entity.Author; 16 import com.lcw.rabbit.myblog.utils.ImageCacheManager; 17 import com.lcw.rabbit.myblog.utils.TimeUtil; 18 import com.makeramen.roundedimageview.RoundedImageView; 19 20 import java.util.List; 21 22 /** 23 * 推薦博主列表適配器 24 * Created by Lichenwei 25 * Date: 2015-08-16 26 * Time: 22:34 27 */ 28 public class AuthorListAdapter extends RecyclerView.Adapter<AuthorListAdapter.RecyclerViewViewHolder> { 29 30 private Context mContext; 31 private List<Author> mAuthors; 32 33 public AuthorListAdapter(Context context, List<Author> authors) { 34 this.mContext = context; 35 this.mAuthors = authors; 36 } 37 38 /** 39 * 設置新的數據源,提醒adatper更新 40 * 41 * @param authors 42 */ 43 public void refreshData(List<Author> authors) { 44 this.mAuthors = authors; 45 this.notifyDataSetChanged(); 46 } 47 48 /** 49 * 自定義點擊回調接口 50 */ 51 public interface RecyclerViewListener { 52 void setOnclickListener(View view, String value); 53 } 54 55 private RecyclerViewListener mRecyclerViewListener; 56 57 /** 58 * 提供setter方法 59 * 60 * @param recyclerViewListener 61 */ 62 public void setRecyclerViewListener(RecyclerViewListener recyclerViewListener) { 63 this.mRecyclerViewListener = recyclerViewListener; 64 } 65 66 67 /** 68 * 建立ViewHolder 69 * 70 * @param viewGroup 71 * @param i 72 * @return 73 */ 74 @Override 75 public RecyclerViewViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { 76 View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.recyclerview_item_authorlist, viewGroup, false); 77 return new RecyclerViewViewHolder(view); 78 } 79 80 /** 81 * 根據資源ID返回Bitmap對象 82 * 83 * @param resId 84 * @return 85 */ 86 public Bitmap getBitmapFromRes(int resId) { 87 Resources res = mContext.getResources(); 88 return BitmapFactory.decodeResource(res, resId); 89 90 } 91 92 /** 93 * 綁定數據 94 * 95 * @param viewholder 96 * @param i 97 */ 98 @Override 99 public void onBindViewHolder(RecyclerViewViewHolder viewholder, int i) { 100 //設置頭像 101 if (mAuthors.get(i).getAuthorPic() != null && !"".equals(mAuthors.get(i).getAuthorPic())) { 102 ImageCacheManager.loadImage(mAuthors.get(i).getAuthorPic(), viewholder.mUserhead, getBitmapFromRes(R.mipmap.avatar_default), getBitmapFromRes(R.mipmap.avatar_default)); 103 } else { 104 viewholder.mUserhead.setImageResource(R.mipmap.avatar_default); 105 } 106 viewholder.mName.setText(mAuthors.get(i).getAuthorName()); 107 viewholder.mUrl.setText(mAuthors.get(i).getAuthorUrl()); 108 viewholder.mSum.setText(mAuthors.get(i).getBlogCount()); 109 viewholder.mTime.setText(mAuthors.get(i).getUpdated()); 110 //處理日期特殊格式 111 String date = TimeUtil.DateToChineseString(TimeUtil.ParseUTCDate(mAuthors.get(i).getUpdated())); 112 viewholder.mTime.setText(date); 113 114 //設置點擊監聽 115 viewholder.itemView.setTag(i); 116 viewholder.mMore.setTag(i); 117 viewholder.itemView.setOnClickListener(new ItemClick()); 118 viewholder.mMore.setOnClickListener(new ItemClick()); 119 } 120 121 @Override 122 public int getItemCount() { 123 return mAuthors.size(); 124 } 125 126 /** 127 * 自定義ViewHolder 128 */ 129 public static class RecyclerViewViewHolder extends RecyclerView.ViewHolder { 130 private RoundedImageView mUserhead; 131 private TextView mName; 132 private TextView mUrl; 133 private TextView mTime; 134 private TextView mSum; 135 private ImageButton mMore; 136 137 public RecyclerViewViewHolder(View view) { 138 super(view); 139 mUserhead = (RoundedImageView) view.findViewById(R.id.iv_userhead); 140 mName = (TextView) view.findViewById(R.id.tv_name); 141 mUrl = (TextView) view.findViewById(R.id.tv_url); 142 mTime = (TextView) view.findViewById(R.id.tv_time); 143 mSum = (TextView) view.findViewById(R.id.tv_sum); 144 mMore = (ImageButton) view.findViewById(R.id.ib_more); 145 146 } 147 148 } 149 150 151 /** 152 * 點擊事件實現類 153 */ 154 public class ItemClick implements View.OnClickListener { 155 @Override 156 public void onClick(View v) { 157 if (mRecyclerViewListener != null) { 158 mRecyclerViewListener.setOnclickListener(v, String.valueOf(v.getTag())); 159 } 160 } 161 } 162 }
二、關於博客首頁的實現:
頁面的總體結構仍是相似,上半部分是信息展現,下半部分是一個RecyclerView列表,列表項裏面的佈局和相關操做下拉刷新上拉加載,咱們均可以複用以前首頁的博文展現,這裏只不過是數據源的不一樣。
因爲咱們在搜索頁面點擊Item項的時候傳遞了Blog對象,咱們就能夠根據做者名來獲取關於博客做者的一些信息,這裏是接口:http://wcf.open.cnblogs.com/blog/u/{BLOGAPP}/posts/{PAGEINDEX}/{PAGESIZE} {BLOGAPP}表明做者的帳號,{PAGEINDEX}表明頁碼,{PAGESIZE}表明每頁的數據條數。
重複的東西這裏就再也不多說了,這裏講點新引入的東西,細心的朋友可能有發現當咱們更新數據(上拉刷新,下拉加載)的時候,列表底部有個彈出提示框,這個就是安卓5.0用來取代Toast的SnackBar:
1 //snackbar提醒 2 Snackbar snackbar = Snackbar.make(mToolbar,"當前更新"+mBlogs.size()+"條博客信息",Snackbar.LENGTH_LONG); 3 snackbar.show();
用法很簡單,相似於Toast,不過不同的是,它是具備交互效果的,也就是說咱們能夠在Snackbar上添加點擊事件,關於Snackbar的詳細用法,有興趣的朋友本身網上找找資料吧。
而後再來講下關於這個FAB(Floating Action Button)的移動效果,這裏我採用的是共享元素移動,因爲咱們的博文詳情頁和博主詳情頁都具備這個控件,因此咱們在切換Activity的時候能夠進行動畫設置,這裏makeSceneTransitionAnimation的第二個參數爲共享View,第三個參數爲標誌參數要與xml裏的transitionName保持一致。
1 android:transitionName="fab"
1 startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(AuthorActivity.this, mFloatingActionButton, "fab").toBundle());
好了,今天先寫到這裏,改天繼續更新,有什麼建議或疑問,能夠在文章評論給我留言。
做者:李晨瑋
出處:http://www.cnblogs.com/lichenwei/本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文連接。正在看本人博客的這位童鞋,我看你氣度不凡,談吐間隱隱有王者之氣,往後必有一番做爲!旁邊有「推薦」二字,你就順手把它點了吧,相得準,我分文不收;相不許,你也好回來找我!