Android Project Actual netease News Page (RecyclerView)

  • 2021-01-18 06:38:22
  • OfStack

The example of this paper to achieve a netease news imitation page, the top is the rotation of the picture, the following is the RecyclerView display news list, the specific content is as follows

Error method


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout ...>
 <ViewPager ... />

 <android.support.v7.widget.RecyclerView .../>

</LinearLayout>

In this way, ViewPager is laid out on top of RecyclerView. If no special processing is done, ViewPager will be fixed when sliding down RecyclerView to load more content.

The correct effect is that as ViewPager slides down to load more, it slides off the page, freeing up space for other content to be displayed.
1. Solution

There are two ways to do this

ViewPager as the 0th item of RecyclerView, that is, Header (this method is used in this paper) Using ScrollView, rewrite some methods to solve sliding conflicts

Total xml layout


<?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>

Very simple, 1 RecyclerView will do

viewholder_article_header.xml layout for header ViewPager


<?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  Popular articles picture display -->
 <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>

ViewPager and LinearLayout in FrameLayout are overlaid, and there is a small dot at the bottom of the image that slides to the first image.

viewholder_article_item.xml layout


<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=" Notice on the lecture "Appreciation of Classical Music Works and Humanistic Aesthetics" "
    android:textColor="@color/primary_text" />
   <!--  news   Release time   source   Read the number -->
   <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=" Academy of sciences " />

    <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 time " />

   </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=" The main content of the lecture: based on the classical music works in the history of Chinese and western music, through the composer and the background of the creation of the works, the knowledge of music culture history and the common sense of music appreciation ..." />

  </LinearLayout>
 </LinearLayout>

</android.support.v7.widget.CardView>

This article Android Material Design learning RecyclerView instead of ListView sscc to achieve without ViewPager, using RecyclerView display news list function.

Adapter for RecyclerView


/**
 *  Adapters for news lists 
 * 01-14  The head is  ViewPager Here is the list news 
 * 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;

 // Head fixation is   image 
 private static final int NUM_IMAGE = 4;

 //Handler  The value of the parameter used 
 private static final int UPTATE_VIEWPAGER = 0;

 // News list 
 private List<ItemArticle> articleList;

 // Set the current   The number of pictures   To be selected 
 private int currentIndex = 0;

 //context
 private Context context;

 private LayoutInflater mLayoutInflater;

 private ImageView[] mCircleImages;// The bottom is just a dot on the current page 


 public ArticleAdapter(Context context, List<ItemArticle> articleList) {
  this.context = context;

  // The head viewpager The picture fixed is 7 The rest, Chang, is the list of data 
  this.articleList = articleList;
  mLayoutInflater = LayoutInflater.from(context);
 }

 @Override
 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
  // Theoretically should put the most likely return  TYPE  On the front 
  View view = null;

  if (viewType == TYPE_ITEM) {
   view = mLayoutInflater.inflate(
     R.layout.viewholder_article_item, parent, false);
   return new ItemArticleViewHolder(view);
  }
  // The head back  ViewPager  Realize the rotation of images 
  if (viewType == TYPE_HEADER) {
   view = mLayoutInflater.inflate(
     R.layout.viewholder_article_header, parent, false);
   return new HeaderArticleViewHolder(view);
  }

  return null;
//  // Exceptions can be thrown. There is no counterpart View type 
//  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) {
   // The transformation of 
   ItemArticleViewHolder newHolder = (ItemArticleViewHolder) holder;
   // Pay attention to RecyclerView The first 0 Item is  ViewPager  Occupy the 0 1 2 3 The picture 
   // So the following list shows  RecyclerView  The first 1 Item, from the first 4 A start 
   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());
   // Notice that the number of readings is  int  Type, which needs to be converted to  String  type 
   newHolder.rcvArticleReadtimes.setText(article.getReadTimes() + " time ");
   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);
  //?? There's some confusion here, Adapter  It has nested Settings in it  Adapter  Is it elegant? 
  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  When moving from the last page to the first page, the page-turning animation effect is not displayed. 
       vp.setCurrentItem(msg.arg1, false);
      }
      break;
    }
   }
  };

  // Here are the styles to set the animation switch 
  vp.setPageTransformer(true, new RotateUpTransformer());

  // Create the navigation bar at the bottom indicating the location 
  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;
   // Add the indicated origin image to the bottom view 
   llBottom.addView(mCircleImages[i]);

  }

  vp.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
   // Slide left and right to select the dot image on the current page 
   @Override
   public void onPageSelected(int position) {
    // 1 Set a few pictures, a few dots, but note from 0 The start of the 
    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);
     }
    }

    // Set the global variable, currentIndex For the selected icon  index
    currentIndex = position;
   }

   @Override
   public void onPageScrolled(int i, float v, int i1) {

   }

   @Override
   public void onPageScrollStateChanged(int state) {

    // The implementation switches to the end and returns to the first 1 zhang 
    switch (state) {
     //  Gestures sliding 
     case ViewPager.SCROLL_STATE_DRAGGING:
      break;

     //  Interface switching 
     case ViewPager.SCROLL_STATE_SETTLING:
      break;

     case ViewPager.SCROLL_STATE_IDLE://  Slide to the end, that is, the completion of switching or loading 
      //  The present is last 1 Zhang, swipe from right to left to switch to number one 1 zhang 
      if (vp.getCurrentItem() == vp.getAdapter()
        .getCount() - 1) {
       vp.setCurrentItem(0, false);
      }
      //  The current to the first 1 Zhang, swipe from left to right to switch to last 1 zhang 
      else if (vp.getCurrentItem() == 0) {
       vp.setCurrentItem(vp.getAdapter()
         .getCount() - 1, false);
      }
      break;

     default:
      break;
    }
   }
  });


  // Set the automatic rotation picture, 5s After execution, the period is 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() {
  // Because many 1 It's a head, so it's a head +1, But the head  ViewPager  Account for the 7 a 
  // So it's actually less 6 a 
  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 {

  // Top news pictures on rotation 
  @InjectView(R.id.vp_hottest)
  ViewPager vpHottest;
  // Rotate the dot below the picture 
  @InjectView(R.id.ll_hottest_indicator)
  LinearLayout llHottestIndicator;

  // College Broadcast Information 
  @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 is the ViewHolder for the news item shown in the list, which corresponds to viewholder_article_item.xml above.

HeaderArticleViewHolder is the ViewHolder of the header ViewPager, corresponding to viewholder_article_header.xml

Note

The ViewPager above this article rotates 4 images, so getItemCount() needs to be duplicated List headers = articleList.subList(0, NUM_IMAGE ); Get the data for the header image ItemArticle article = articleList.get(position + NUM_IMAGE - 1); Get the data for the following news item getItemViewType(int position) is a header ViewPager based on position onCreateViewHolder(ViewGroup parent, int viewType) generates header images or ViewHolder for the following news item based on viewType

2. Confusion and a follow-up plan

In addition to using ViewPager as the first item of RecyclerView, there is another method using ScrollView that you can study.

The above is all the content of this article, I hope to help you learn.


Related articles: