0
点赞
收藏
分享

微信扫一扫

RecyclerView实现广告轮播图


平时都是用RecyclerView实现列表,RecyclerView的强大毋庸置疑,今天就用它来实现广告轮播图。 

   

  效果如下 

RecyclerView实现广告轮播图_recyclerview

  首先,在activity_main.xml里定义布局 
  

<RelativeLayout
...
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="144dp">

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

</RelativeLayout>

  然后定义列表的item布局—-item_image.xml:

<LinearLayout
...
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<ImageView
android:id="@+id/item_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"/>

</LinearLayout>

  然后是Adapter,在Adapter初始化时要传入图片列表list:

public class BannerAdapter extends RecyclerView.Adapter<BannerAdapter.ViewHolder> {

private List<Integer> list;
private Context context;

public BannerAdapter(Context context,List<Integer> list){
this.list=list;
this.context=context;
}

@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view= LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image,parent,false);
return new ViewHolder(view);
}

@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Glide.with(context).load(list.get(position%list.size())).into(holder.imageView);
}

@Override
public int getItemCount() {
return Integer.MAX_VALUE;
}

class ViewHolder extends RecyclerView.ViewHolder
private ImageView imageView;

public

   
  上面代码里需要注意的地方有两处。 
   
  第一处是getItemCount() 返回的是Integer.MAX_VALUE。这是因为广告轮播图是无限轮播,getItemCount() 返回的是Adapter中的总项目数,这样才能使RecyclerView能一直滚动。 
   
  第二处是onBindViewHolder()中的 position%list.size() ,表示position对图片列表list取余,这样list.get(position%list.size())才能按顺序循环展示图片。

   
  MainActivity.java代码如下:

public class MainActivity extends AppCompatActivity
private List<Integer> list = new ArrayList<>(4);

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

//存入图片
list.add(R.drawable.b1);
list.add(R.drawable.b2);
list.add(R.drawable.b3);
list.add(R.drawable.b4);


BannerAdapter adapter = new BannerAdapter(this, list);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycler);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setAdapter(adapter);
recyclerView.scrollToPosition(list.size()*10);

}
}

   需要注意的是LinearLayoutManager 第二个参数表示布局方向,平时默认是垂直的,也就是我们常见的列表样式。这里轮播广告要用为LinearLayoutManager.HORIZONTAL,水平方向。 
   还有一点需要注意,recyclerView.scrollToPosition(list.size()*10)这句使RecyclerView一开始位于 list.size()*10 处,避免了一开始position为0不能前滑的尴尬。 
   
  由于广告是一页一页的划过去,所以我们还需要用到一个类,SnapHelper的子类PagerSnapHelper,用起来很简单,两句话。直接追加到上面的recyclerView.setAdapter(adapter) 后面。

public class MainActivity extends AppCompatActivity
...

@Override
protected void onCreate(Bundle savedInstanceState) {

...
recyclerView.setAdapter(adapter);

PagerSnapHelper snapHelper = new

  然后加入自动轮播,此处使用ScheduledExecutorService 来完成。

1);
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
recyclerView.smoothScrollToPosition(layoutManager.findFirstVisibleItemPosition() + 1);
}
}, 2000, 2000, TimeUnit.MILLISECONDS);

这段代码表示2秒后每过2秒运行一次run()里的程序 。layoutManager.findFirstVisibleItemPosition() 表示得到当前RecyclerView第一个能看到的item的位置。由于广告是每次展示一张,所以得到的就是当前图片的position。recyclerView.smoothScrollToPosition(int position)表示滑动到某个position。所以上面的代码就表示每过2秒滑动到下个position,以此来完成自动轮播。

  还有一点还要改进,程序运行起来后会发现自动轮播切换图片时速度太快了,这个怎么解决呢? 

  点开LinearLayoutManager的源码,查找smoothScrollToPosition()方法。 

  

RecyclerView实现广告轮播图_android_02

 

这里滑动用到了LinearSmoothScroller,继续点击去,里面有一个calculateSpeedPerPixel()方法。 

RecyclerView实现广告轮播图_android_03


  官方注释:计算滚动速度。如果返回值是2毫秒,这表示着滚动1000像素需要2秒。 

所以我们继承LinearLayoutManager,重写smoothScrollToPosition()方法,并将里面的修改LinearSmoothScroller的这个方法返回值修改。

  新建SmoothLinearLayoutManager.java 文件,代码如下: 
  

public class SmoothLinearLayoutManager extends LinearLayoutManager

public SmoothLinearLayoutManager(Context context) {
super(context);
}

public SmoothLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}

@Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state, int position) {
LinearSmoothScroller linearSmoothScroller =
new LinearSmoothScroller(recyclerView.getContext()) {
protected float calculateSpeedPerPixel(DisplayMetrics displayMetrics) {
return 0.2f; //返回0.2

  
   
  程序写到这里,广告轮播图已初具雏形了,最后还差个指示器。 
   
  显示指示器上的红点需要得到当前展示的广告轮播图片的position。RecyclerView有个addOnScrollListener()方法,可以监听当前滑动状态。所以代码如下: 
  

new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
int i = layoutManager.findFirstVisibleItemPosition() % list.size();
//得到指示器红点的位置

onScrollStateChangedd的 newState 参数有三种状态SCROLL_STATE_IDLE、SCROLL_STATE_DRAGGING和SCROLL_STATE_SETTLING,分布表示静止状态,拖拽状态和手指离开后的惯性滚动状态。所以这里当RecyclerView的状态为SCROLL_STATE_IDLE时得到当前图片的position,然后与图片列表取余就得到指示器红点的位置。

举报

相关推荐

0 条评论