編輯:關於Android編程
本文實例實現一個仿網易新聞的頁面,上面是輪播的圖片,下面是 RecyclerView 顯示新聞列表,具體內容如下
錯誤方法
<?xml version="1.0" encoding="utf-8"?> <LinearLayout ...> <ViewPager ... /> <android.support.v7.widget.RecyclerView .../> </LinearLayout>
這樣布局 ViewPager 在 RecyclerView 的上面,如果不做特殊處理,當下滑 RecyclerView 加載更多內容的時候,ViewPager會固定不動。
正確的效果是下滑加載更多的時候,ViewPager 會滑出頁面,釋放空間供其他內容展示。
一、解決思路
方法有兩種
總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_latest" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout>
很簡單,一個RecyclerView就行了
頭部 ViewPager 的viewholder_article_header.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"> <!--ViewPager 熱門文章圖片展示--> <FrameLayout android:layout_width="match_parent" android:layout_height="200dp" android:background="@color/gray_light"> <android.support.v4.view.ViewPager android:id="@+id/vp_hottest" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/colorPrimary" /> <LinearLayout android:id="@+id/ll_hottest_indicator" android:layout_width="wrap_content" android:layout_height="20dp" android:layout_gravity="bottom|right" android:layout_marginBottom="5dp" android:layout_marginRight="10dp" android:layout_marginTop="5dp" android:gravity="center" android:orientation="horizontal" /> </FrameLayout> </LinearLayout>
FrameLayout裡面的ViewPager和LinearLayout是覆蓋顯示的,實現在圖片的下方有個小圓點標記滑動到了第一張圖片。
新聞項 viewholder_article_item.xml 布局
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" 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" app:cardCornerRadius="5dp" app:cardElevation="5dp" app:contentPadding="2dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <com.facebook.drawee.view.SimpleDraweeView android:id="@+id/rcv_article_photo" android:layout_width="100dp" android:layout_height="100dp" 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="0dp" android:layout_weight="1" android:layout_marginLeft="10dp" android:layout_marginTop="5dp" android:ellipsize="end" android:maxLines="2" android:text="講座主要內容:以中、西方音樂歷史中經典音樂作品為基礎,通過作曲家及作品創作背景、相關音樂文化史知識及音樂欣賞常識..." /> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView>
這篇文章 Android Material Design學習之RecyclerView代替 ListView sscc實現了不加 ViewPager,利用 RecyclerView 展示新聞列表的功能。
RecyclerView 的適配器
/** * 新聞列表的適配器 * 01-14 頭部是 ViewPager,下面是列表新聞 * Created by tomchen on 1/11/16. */ public class ArticleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private static final int TYPE_HEADER = 0; private static final int TYPE_ITEM = 1; //頭部固定為 張圖片 private static final int NUM_IMAGE = 4; //Handler 用到的參數值 private static final int UPTATE_VIEWPAGER = 0; //新聞列表 private List<ItemArticle> articleList; //設置當前 第幾個圖片 被選中 private int currentIndex = 0; //context private Context context; private LayoutInflater mLayoutInflater; private ImageView[] mCircleImages;//底部只是當前頁面的小圓點 public ArticleAdapter(Context context, List<ItemArticle> articleList) { this.context = context; //頭部viewpager圖片固定是7張,剩下的是列表的數據 this.articleList = articleList; mLayoutInflater = LayoutInflater.from(context); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //理論上應該把最可能返回的 TYPE 放在前面 View view = null; if (viewType == TYPE_ITEM) { view = mLayoutInflater.inflate( R.layout.viewholder_article_item, parent, false); return new ItemArticleViewHolder(view); } //頭部返回 ViewPager 實現的輪播圖片 if (viewType == TYPE_HEADER) { view = mLayoutInflater.inflate( R.layout.viewholder_article_header, parent, false); return new HeaderArticleViewHolder(view); } return null; // //可以拋出異常,沒有對應的View類型 // throw new RuntimeException("there is no type that matches the type " + viewType + " + make sure your using types correctly"); } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder instanceof ItemArticleViewHolder) { //轉型 ItemArticleViewHolder newHolder = (ItemArticleViewHolder) holder; //注意RecyclerView第0項是 ViewPager 占據了0 1 2 3圖片 //那麼下面的列表展示是 RecyclerView 的第1項,從第4項開始 ItemArticle article = articleList.get(position + NUM_IMAGE - 1); newHolder.rcvArticlePhoto.setImageURI(Uri.parse(article.getImageUrl())); newHolder.rcvArticleTitle.setText(article.getTitle()); newHolder.rcvArticleDate.setText(article.getPublishDate()); newHolder.rcvArticleSource.setText(article.getSource()); //注意這個閱讀次數是 int 類型,需要轉化為 String 類型 newHolder.rcvArticleReadtimes.setText(article.getReadTimes() + "次"); newHolder.rcvArticlePreview.setText(article.getPreview()); } else if (holder instanceof HeaderArticleViewHolder) { HeaderArticleViewHolder newHolder = (HeaderArticleViewHolder) holder; List<ItemArticle> headers = articleList.subList(0, NUM_IMAGE ); HeaderImageAdapter imageAdapter = new HeaderImageAdapter(context, headers); setUpViewPager(newHolder.vpHottest, newHolder.llHottestIndicator, headers); } } private void setUpViewPager(final ViewPager vp, LinearLayout llBottom, final List<ItemArticle> headerArticles) { HeaderImageAdapter imageAdapter = new HeaderImageAdapter(context, headerArticles); //??這兒有些疑惑,Adapter 裡面嵌套設置 Adapter 是否優雅? vp.setAdapter(imageAdapter); final Handler mHandler = new Handler() { public void handleMessage(Message msg) { switch (msg.what) { case UPTATE_VIEWPAGER: if (msg.arg1 != 0) { vp.setCurrentItem(msg.arg1); } else { //false 當從末頁調到首頁是,不顯示翻頁動畫效果, vp.setCurrentItem(msg.arg1, false); } break; } } }; //下面是設置動畫切換的樣式 vp.setPageTransformer(true, new RotateUpTransformer()); //創建底部指示位置的導航欄 final ImageView[] mCircleImages = new ImageView[headerArticles.size()]; for (int i = 0; i < mCircleImages.length; i++) { ImageView imageView = new ImageView(context); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(10, 10); params.setMargins(5, 0, 5, 0); imageView.setLayoutParams(params); if (i == 0) { imageView.setBackgroundResource(R.drawable.indicator_select); } else { imageView.setBackgroundResource(R.drawable.indicator_not_select); } mCircleImages[i] = imageView; //把指示作用的原點圖片加入底部的視圖中 llBottom.addView(mCircleImages[i]); } vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { //圖片左右滑動時候,將當前頁的圓點圖片設為選中狀態 @Override public void onPageSelected(int position) { // 一定幾個圖片,幾個圓點,但注意是從0開始的 int total = mCircleImages.length; for (int j = 0; j < total; j++) { if (j == position) { mCircleImages[j].setBackgroundResource(R.drawable.indicator_select); } else { mCircleImages[j].setBackgroundResource(R.drawable.indicator_not_select); } } //設置全局變量,currentIndex為選中圖標的 index currentIndex = position; } @Override public void onPageScrolled(int i, float v, int i1) { } @Override public void onPageScrollStateChanged(int state) { //實現切換到末尾後返回到第一張 switch (state) { // 手勢滑動 case ViewPager.SCROLL_STATE_DRAGGING: break; // 界面切換中 case ViewPager.SCROLL_STATE_SETTLING: break; case ViewPager.SCROLL_STATE_IDLE:// 滑動結束,即切換完畢或者加載完畢 // 當前為最後一張,此時從右向左滑,則切換到第一張 if (vp.getCurrentItem() == vp.getAdapter() .getCount() - 1) { vp.setCurrentItem(0, false); } // 當前為第一張,此時從左向右滑,則切換到最後一張 else if (vp.getCurrentItem() == 0) { vp.setCurrentItem(vp.getAdapter() .getCount() - 1, false); } break; default: break; } } }); //設置自動輪播圖片,5s後執行,周期是5s Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Message message = new Message(); message.what = UPTATE_VIEWPAGER; if (currentIndex == headerArticles.size() - 1) { currentIndex = -1; } message.arg1 = currentIndex + 1; mHandler.sendMessage(message); } }, 6000, 6000); } @Override public int getItemCount() { //因為多了一個頭部,所以是+1,但是頭部 ViewPager 占了7個 //所以實際是少了6個 return articleList.size() + 1 - NUM_IMAGE; } @Override public int getItemViewType(int position) { if (position == 0) return TYPE_HEADER; else return TYPE_ITEM; } class HeaderArticleViewHolder extends RecyclerView.ViewHolder { //輪播的最熱新聞圖片 @InjectView(R.id.vp_hottest) ViewPager vpHottest; //輪播圖片下面的小圓點 @InjectView(R.id.ll_hottest_indicator) LinearLayout llHottestIndicator; //學院廣播信息 @InjectView(R.id.tv_college_broadcast) TextView tvCollegeBroadcast; public HeaderArticleViewHolder(View itemView) { super(itemView); ButterKnife.inject(this, itemView); } } class ItemArticleViewHolder 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 ItemArticleViewHolder(View itemView) { super(itemView); ButterKnife.inject(this, itemView); } } }
ItemArticleViewHolder是列表展示的新聞項的 ViewHolder,對應了上面的 viewholder_article_item.xml。
HeaderArticleViewHolder 是頭部 ViewPager 的 ViewHolder, 對應viewholder_article_header.xml
Note
二、疑惑及後續計劃
除了將 ViewPager 作為 RecyclerView 第一項,還有一張方法就是利用ScrollView,大家可以進行研究。
以上就是本文的全部內容,希望對大家的學習有所幫助。
一、工具干什麼都得一個好工具對吧。1.apkIDE反編譯呢,我這裡使用的是apkIDE(apk改之理),工具的話自己百度吧。個人不喜歡留一些不需要的東西在網盤裡,難得整理
今天有人問我,android系統不同分辨率,不同大小的手機,字體大小怎麼去適應呢?其實字體的適應和圖片的適應是一個道理的。 一、 原理如下: 假設需要適應320x240,
我們總是出門後才發現忘了關電腦,或是忘了從電腦中拷貝重要數據,難道還得跑回家一趟?嘿嘿,想在外網環境下遠程控制PC,其實沒有那麼復雜。如果某位童鞋擔心遇到上
之前參加了一個課程,裡面有一節講到了用視頻作為啟動界面。講師用的是自定義VideoView,重寫onMeasure方法,因為原生的VideoView在那情況下不能實現全屏