Android 微信讀書本週推薦傳送帶列表實現
ofollow,noindex">微信讀書 本週推送的類似傳送帶View的具體實現
實現效果

image
使用
<com.icool.carousel_lib.CarouselLayout android:id="@+id/carousel" android:layout_width="match_parent" android:layout_height="match_parent" app:carousel_angle="-30" app:carousel_spacing="20dp" app:carousel_speed="1" />
只需要通過設定Adapter就OK了
public void setAdapter(RecyclerView.Adapter adapter1, RecyclerView.Adapter adapter2, RecyclerView.Adapter adapter3) { mRv1.setAdapter(adapter1); mRv2.setAdapter(adapter2); mRv3.setAdapter(adapter3); }
屬性說明
屬性值 | 說明 | 值 |
---|---|---|
carousel_angle | 傾斜角度 | 預設-30° |
carousel_spacing | 列表之間的間隙,通常設定為recyclerView的item間距大小一致 | dp |
carousel_speed | 速度,值越大傳送越快,不小於0 | 預設1 |
setGapSpacing setAngle setSpeed
需求分析
- 直觀有 三條傳送帶式列表
- 一個正向移動 兩個反向移動
- 有一個傾斜角度
- 可以迴圈展示
具體分析
- 根據樣式 可以確定的是需要自定義ViewGroup來實現
- 結合列表的正向反向移動 可以確定:
RecyclerView
+LinearLayoutManager
可以做到 - 不停滾動藉助
Scroller
來實現 - 傾斜角度 可以通過
setRatation()
方法來旋轉一個角度 - 迴圈展示 通過設定
RecyclerView.Adapter
的itemCount
為Inter.MAX_VALUE
具體實現
自定義 CarouselLayout
繼承自 ViewGroup
新增一個子View LinearLayout
, setOrientation(LinearLayout.VERTICAL);
依次新增三個 RecyclerView
,設定其 marginTop
為 gapSpacing
的值
mContainer = new LinearLayout(getContext()); mContainer.setOrientation(LinearLayout.VERTICAL); addView(mContainer, generateDefaultLayoutParams()); mRv1 = new CarouselRecyclerView(getContext()); mRv2 = new CarouselRecyclerView(getContext()); mRv3 = new CarouselRecyclerView(getContext()); mContainer.addView(mRv1); mContainer.addView(mRv2); mContainer.addView(mRv3); setSpacing();//此方法設定margin,詳見程式碼 mRv1.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false)); mRv2.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, true)); mRv3.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.HORIZONTAL, false));
旋轉一個角度
設定 LinearLayout
的rotation
mContainer.setRotation(mAngle);//旋轉角度
設定 LinearLayout
的大小來保證切斜後仍可以佔滿全屏
由於在ViewGroup中最大的距離就是對角線,所以 設定 子View的寬高都為對角線的長度
//對角線長度 mDiagonalLine = (int) Math.sqrt(getMeasuredWidth() * getMeasuredWidth() + getMeasuredHeight() * getMeasuredHeight()); ViewGroup.LayoutParams params = mContainer.getLayoutParams(); params.width = mDiagonalLine; params.height = mDiagonalLine; mContainer.setLayoutParams(params);
移動起來
藉助Scroller類來不斷 呼叫 computeScroll
方法實現滾動
@Override public void computeScroll() { super.computeScroll(); mRv1.scrollBy(mSpeed, 0);//speed 對應移動畫素值 mRv2.scrollBy(-mSpeed, 0); mRv3.scrollBy(mSpeed, 0); if (mScroller.isFinished()) { start(); } }
其他
- 因為列表使用
RecyclerView
實現,所以我們手動還可以滑動它。
如果不想手動滑動的話,重寫RecyclerView
的onTouchEvent
方法,return false;
- 無限迴圈
設定Adapter的時候
@Override public int getItemCount() { return Integer.MAX_VALUE; }
然後在 onBindViewHolder
方法取item的時候 進行取餘操作
String url = mSources[position % mSources.length];
後記
這個效果在微信閱讀上是WebView實現的,我們的UI直接抄了過來。所以只能用Android程式碼實現一下。
如果有更好的實現方式,或者需要改進的地方,希望可以一起探討。