最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android如何使用RecyclerView打造首頁輪播圖

 更新時(shí)間:2021年04月21日 09:15:12   作者:24K純帥豆  
這篇文章主要為大家詳細(xì)介紹了Android如何使用RecyclerView打造首頁輪播圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了Android使用RecyclerView打造首頁輪播圖的具體代碼,供大家參考,具體內(nèi)容如下

先看看效果圖:

停在中間自動(dòng)翻頁

序言:最近接到一個(gè)任務(wù),做一個(gè)類似上面自動(dòng)翻頁的功能??梢钥吹?,這一屏中有三張圖片顯示出來了,有兩張沒有顯示完全,看到設(shè)計(jì)圖的時(shí)候第一反應(yīng)是可以用viewpager來實(shí)現(xiàn),但是任務(wù)卻跟你開了一個(gè)天大的玩笑,要求是以最左邊的圖片為基準(zhǔn),也就是說,左邊的圖片也得顯示完全,就像下圖所示,后來仔細(xì)想想viewpager好像沒有這樣的功能,也有可能是我不知道,我也沒有找到這樣的文章或者信息,希望知道的簡(jiǎn)友私戳交流一下,感激不盡,好了,言歸正傳

停在左邊

在開始之前呢,首先介紹一個(gè)Google最新(其實(shí)在24.2.0版本的時(shí)候就已經(jīng)發(fā)布了)發(fā)布的一個(gè)東西SnapHelper,這玩意兒是對(duì)RecyclerView功能的一個(gè)拓展,有興趣的同學(xué)可以去看看它的源碼,SnapHelper的實(shí)現(xiàn)原理是監(jiān)聽RecyclerView.OnFlingListener中的onFling接口,可以使RecyclerView實(shí)現(xiàn)類似ViewPager的功能,無論怎么滑動(dòng)最終停留在某頁正中間,那它和ViewPager的區(qū)別是什么呢?就是ViewPager不能一次連續(xù)滑動(dòng)多張圖片,而且不能定制(停在左邊,還是停在右邊)。下面我們一起來看看吧!

首先導(dǎo)入所需要的包,最低版本是v7-24.2.0,低了就沒有這個(gè)類了:

compile 'com.android.support:appcompat-v7:24.2.0'
compile 'com.android.support:recyclerview-v7:24.2.0'

這里系統(tǒng)自帶有一個(gè)類LinearSnapHelper,LinearSnapHelper繼承自SnapHelper,這個(gè)默認(rèn)是讓視圖停在中間的,你只需要將RecyclerView和LinearSnapHelper綁定在一起就行了:

LinearSnapHelper mLinearSnapHelper = new LinearSnapHelper();
mLinearSnapHelper.attachToRecyclerView(mRecyclerview);

效果如下:

當(dāng)然了,SnapHelper的功能絕不僅僅在此,你還可以定制化,讓他停在左邊,或者右邊,而你不需要重新繼承SnapHelper,直接繼承LinearSnapHelper就可以了,這里面有很多寫好的方法,然后你再重寫里面的兩個(gè)方法:
* (1)、calculateDistanceToFinalSnap:當(dāng)拖拽或滑動(dòng)結(jié)束時(shí)會(huì)回調(diào)該方法,返回一個(gè)out = int[2],out[0]x軸,out[1] y軸 ,這個(gè)值就是需要修正的你需要的位置的偏移量。 *
* (2)、findSnapView:這個(gè)方法用來獲取特定的視圖,當(dāng)返回null時(shí),表示沒有獲取到任何視圖 。*

完整的代碼:

public class LeftSnapHelper extends LinearSnapHelper {

 private OrientationHelper mHorizontalHelper;

 /**
 * 當(dāng)拖拽或滑動(dòng)結(jié)束時(shí)會(huì)回調(diào)該方法,該方法返回的是一個(gè)長度為2的數(shù)組,out[0]表示橫軸,x[1]表示縱軸,這兩個(gè)值就是你需要修正的位置的偏移量
 *
 * @param layoutManager
 * @param targetView
 * @return
 */
 @Override
 public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
 //注:由于是橫向滾動(dòng),在這里我們只考慮橫軸的值
 int[] out = new int[2];
 if (layoutManager.canScrollHorizontally()) {
  out[0] = distanceToStart(targetView, getHorizontalHelper(layoutManager));
 } else {
  out[0] = 0;
 }
 return out;
 }

 /**
 * 這個(gè)方法是計(jì)算偏移量
 *
 * @param targetView
 * @param helper
 * @return
 */
 private int distanceToStart(View targetView, OrientationHelper helper) {
 return helper.getDecoratedStart(targetView) - helper.getStartAfterPadding();
 }

 @Override
 public View findSnapView(RecyclerView.LayoutManager layoutManager) {
 return findStartView(layoutManager, getHorizontalHelper(layoutManager));
 }

 /**
 * 找到第一個(gè)顯示的view
 * @param layoutManager
 * @param helper
 * @return
 */
 private View findStartView(RecyclerView.LayoutManager layoutManager,
    OrientationHelper helper) {
 if (layoutManager instanceof LinearLayoutManager) {
  int firstChild = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
  int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
  if (firstChild == RecyclerView.NO_POSITION) {
  return null;
  }

  //這是為了解決當(dāng)翻到最后一頁的時(shí)候,最后一個(gè)Item不能完整顯示的問題
  if (lastChild == layoutManager.getItemCount() - 1) {
  return layoutManager.findViewByPosition(lastChild);
  }
  View child = layoutManager.findViewByPosition(firstChild);

  //得到此時(shí)需要左對(duì)齊顯示的條目
  if (helper.getDecoratedEnd(child) >= helper.getDecoratedMeasurement(child) / 2
   && helper.getDecoratedEnd(child) > 0) {
  return child;
  } else {
  return layoutManager.findViewByPosition(firstChild + 1);
  }
 }
 return super.findSnapView(layoutManager);
 }

 /**
 * 獲取視圖的方向
 *
 * @param layoutManager
 * @return
 */
 private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
 if (mHorizontalHelper == null) {
  mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
 }
 return mHorizontalHelper;
 }
}

當(dāng)然了,你也可以讓它停在右邊:只需要在上面的基礎(chǔ)上修改findSnapView方法即可:

public class RightSnapHelper extends LinearSnapHelper {

 private OrientationHelper mHorizontalHelper;

 /**
 * 當(dāng)拖拽或滑動(dòng)結(jié)束時(shí)會(huì)回調(diào)該方法,該方法返回的是一個(gè)長度為2的數(shù)組,out[0]表示橫軸,x[1]表示縱軸,這兩個(gè)值就是你需要修正的位置的偏移量
 *
 * @param layoutManager
 * @param targetView
 * @return
 */
 @Override
 public int[] calculateDistanceToFinalSnap(RecyclerView.LayoutManager layoutManager, View targetView) {
 //注:由于是橫向滾動(dòng),在這里我們只考慮橫軸的值
 int[] out = new int[2];
 if (layoutManager.canScrollHorizontally()) {
  out[0] = distanceToEnd(targetView, getHorizontalHelper(layoutManager));
 } else {
  out[0] = 0;
 }
 return out;
 }

 /**
 * 這個(gè)方法是計(jì)算偏移量
 *
 * @param targetView
 * @param helper
 * @return
 */
 private int distanceToEnd(View targetView, OrientationHelper helper) {
 return helper.getDecoratedEnd(targetView) - helper.getEndAfterPadding();
 }

 @Override
 public View findSnapView(RecyclerView.LayoutManager layoutManager) {
 return findEndView(layoutManager, getHorizontalHelper(layoutManager));
 }

 /**
 * 找到第一個(gè)顯示的view
 *
 * @param layoutManager
 * @param helper
 * @return
 */
 private View findEndView(RecyclerView.LayoutManager layoutManager, OrientationHelper helper) {
 if (layoutManager instanceof LinearLayoutManager) {
  int lastChild = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
  if (lastChild == RecyclerView.NO_POSITION) {
  return null;
  }

  View child = layoutManager.findViewByPosition(lastChild);

  //得到此時(shí)需要右對(duì)齊顯示的條目
  if (helper.getDecoratedStart(child) >= helper.getDecoratedMeasurement(child) / 2
   && helper.getDecoratedStart(child) > 0) {
  return child;
  } else {
  return layoutManager.findViewByPosition(lastChild - 1);
  }
 }
 return super.findSnapView(layoutManager);
 }

 /**
 * 獲取視圖的方向
 *
 * @param layoutManager
 * @return
 */
 private OrientationHelper getHorizontalHelper(@NonNull RecyclerView.LayoutManager layoutManager) {
 if (mHorizontalHelper == null) {
  mHorizontalHelper = OrientationHelper.createHorizontalHelper(layoutManager);
 }
 return mHorizontalHelper;
 }
}

效果:

停在中間自動(dòng)翻頁

停在右邊

那如何讓它能無限的滑動(dòng)呢?

這個(gè)當(dāng)然是要在Adapter里面“做手腳”了,讓獲取Item總數(shù)的方法返回Integer.MAX_VALUE就可以了:

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

然后在onBindViewHolder中獲取list中的值時(shí)相應(yīng)的取余就好了:

@Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
 Glide.with(mContext).load(mList.get(position % mList.size())
  .getImageUrl()).placeholder(R.mipmap.ic_launcher)
  .into(holder.ivImage);
 holder.tvName.setText(mList.get(position % mList.size()).getName());
}

好了,做到這里就完成了80%了,接下來我們要讓它能夠自動(dòng)滾動(dòng),如何能自動(dòng)滾動(dòng)呢?這里可以參考一下ViewPager中自動(dòng)滾動(dòng)的效果,這里L(fēng)Z使用的是Timer來實(shí)現(xiàn),Timer有一個(gè)每隔多長時(shí)間執(zhí)行一次的功能,在這里正好:

private int cnt = 2; //表示當(dāng)前最右邊顯示的item的position
private boolean isSlidingByHand = false; //表示是否是手在滑動(dòng)
private boolean isSlidingAuto = true; //表示是否自動(dòng)滑動(dòng)

timer.schedule(new TimerTask() {
 @Override
 public void run() {
  if (isSlidingAuto) {
  myHandler.sendEmptyMessage(CHANGE_ITEM);
  }
 }
 }, 1000, 3000);

考慮到這里有兩種滑動(dòng),一種是用戶手動(dòng)的滑動(dòng),另一種是我們的Timer來出發(fā)滑動(dòng),我們還得對(duì)RecyclerView設(shè)置監(jiān)聽,來簡(jiǎn)單判斷一下是用戶觸發(fā)的還是Timer觸發(fā)的:

alRecyclerview.addOnScrollListener(new RecyclerView.OnScrollListener() {
 @Override
 public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
  LinearLayoutManager manager = (LinearLayoutManager) recyclerView.getLayoutManager();
  int firstVisibleItemPosition = manager.findFirstVisibleItemPosition();
  switch (newState) {
  case SCROLL_STATE_IDLE: //(靜止沒有滾動(dòng))
   if (isSlidingByHand) {
   Message msg = myHandler.obtainMessage();
   msg.arg1 = firstVisibleItemPosition;
   msg.what = CHANGE_ITEM;
   myHandler.sendMessage(msg);
   }
   break;
  case SCROLL_STATE_DRAGGING: //(正在被外部拖拽,一般為用戶正在用手指滾動(dòng))
   isSlidingByHand = true;
   isSlidingAuto = false;
   break;
  case SCROLL_STATE_SETTLING: //(自動(dòng)滾動(dòng))
   if (isSlidingByHand) {
   isSlidingAuto = false;
   } else {
   isSlidingAuto = true;
   }
   break;
  }
 }
 });

最后的處理結(jié)果當(dāng)然是交給Handler來了:

private static class MyHandler extends Handler {
 //采用弱引用的方式,防止內(nèi)存泄漏
 WeakReference<CenterActivity> weakReference;

 public MyHandler(CenterActivity mActivity) {
 this.weakReference = new WeakReference<>(mActivity);
 }

 @Override
 public void handleMessage(Message msg) {
 final CenterActivity mActivity = weakReference.get();
 Log.d(TAG, "handleMessage: " + "handler is running");
 if (mActivity.isSlidingByHand) {
  mActivity.cnt = msg.arg1;
  mActivity.isSlidingByHand = false;
  mActivity.isSlidingAuto = true;
  mActivity.cnt+=2;
  //讓RecyclerView平滑的滾動(dòng)
  mActivity.alRecyclerview.smoothScrollToPosition(++mActivity.cnt);
 } else {
  mActivity.alRecyclerview.smoothScrollToPosition(++mActivity.cnt);
 }
 }
}

這樣差不多就好了,但是還有一個(gè)問題不知道各位有沒有關(guān)注到,滾動(dòng)的時(shí)候并沒有那么平滑,找了好久不知道是什么原因,希望知道的朋友底下評(píng)論告知一聲。

參考文章:
OrientationHelper API
Android24.2.0支持庫中的SnapHelper學(xué)習(xí)和使用

感謝以上資料的幫助。

源碼我已上傳至Github,想了解的朋友可以自行下載,當(dāng)然,如果有更好的想法,也可以一起交流。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • ImageView簡(jiǎn)單加載網(wǎng)絡(luò)圖片實(shí)例代碼

    ImageView簡(jiǎn)單加載網(wǎng)絡(luò)圖片實(shí)例代碼

    使用ImageView實(shí)現(xiàn)簡(jiǎn)單加載網(wǎng)絡(luò)圖片的功能,示例代碼如下,感興趣的朋友可以參考下哈,希望對(duì)大家有所幫助
    2013-06-06
  • Flutter實(shí)現(xiàn)抽屜動(dòng)畫

    Flutter實(shí)現(xiàn)抽屜動(dòng)畫

    這篇文章主要為大家詳細(xì)介紹了Flutter實(shí)現(xiàn)抽屜動(dòng)畫,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Android中Retrofit的簡(jiǎn)要介紹

    Android中Retrofit的簡(jiǎn)要介紹

    今天小編就為大家分享一篇關(guān)于Android中Retrofit的簡(jiǎn)要介紹,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-04-04
  • Flutter軟鍵盤的原理淺析

    Flutter軟鍵盤的原理淺析

    大家應(yīng)該都知道目前Flutter官方是沒有自定義鍵盤的解決方案,下面這篇文章主要給大家介紹了關(guān)于Flutter軟鍵盤原理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • ffmpeg實(shí)現(xiàn)去水印以及切分視頻demo

    ffmpeg實(shí)現(xiàn)去水印以及切分視頻demo

    這篇文章主要為大家介紹了ffmpeg實(shí)現(xiàn)去水印以及切分視頻demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-11-11
  • Android實(shí)現(xiàn)界面左右滑動(dòng)切換功能

    Android實(shí)現(xiàn)界面左右滑動(dòng)切換功能

    相信大家一定都使用過手機(jī)QQ和微信之類的軟件,當(dāng)我們使用時(shí)不難發(fā)現(xiàn)其界面的切換不僅可以通過點(diǎn)擊頁標(biāo)簽來實(shí)現(xiàn),還可以通過左右滑動(dòng)來實(shí)現(xiàn)的,下面小編給大家介紹下如何實(shí)現(xiàn)這個(gè)功能
    2016-12-12
  • Android如何跳轉(zhuǎn)到應(yīng)用商店的APP詳情頁面

    Android如何跳轉(zhuǎn)到應(yīng)用商店的APP詳情頁面

    最近做項(xiàng)目遇到這樣的需求,要求從App內(nèi)部點(diǎn)擊按鈕或鏈接,跳轉(zhuǎn)到應(yīng)用商店的某個(gè)APP的詳情頁面,怎么實(shí)現(xiàn)此功能呢?下面小編給大家分享Android如何跳轉(zhuǎn)到應(yīng)用商店的APP詳情頁面,需要的朋友參考下
    2017-01-01
  • Android登陸界面用戶名檢測(cè)功能

    Android登陸界面用戶名檢測(cè)功能

    這篇文章主要為大家詳細(xì)介紹了Android登陸界面用戶名檢測(cè)功能的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-03-03
  • Android studio設(shè)置指定的簽名文件教程

    Android studio設(shè)置指定的簽名文件教程

    這篇文章主要介紹了Android studio設(shè)置指定的簽名文件教程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-03-03
  • Android實(shí)現(xiàn)截屏并保存操作功能

    Android實(shí)現(xiàn)截屏并保存操作功能

    這篇文章主要介紹了Android實(shí)現(xiàn)截屏操作功能,即Android中截取當(dāng)前屏幕的功能,感興趣的小伙伴們可以參考一下
    2015-12-12

最新評(píng)論

平谷区| 蓬溪县| 康定县| 克拉玛依市| 涿鹿县| 太白县| 朔州市| 外汇| 宝山区| 襄汾县| 盐源县| 天峨县| 原平市| 息烽县| 桐乡市| 太仆寺旗| 尖扎县| 冷水江市| 虹口区| 兴国县| 安康市| 五常市| 玉林市| 介休市| 友谊县| 武冈市| 方城县| 林周县| 安龙县| 南江县| 星座| 兴义市| 福贡县| 武胜县| 奉节县| 永平县| 汕尾市| 余干县| 汝州市| 穆棱市| 乐业县|