RecyclerView Item 的懸浮效果(吸附效果)的實現
在參考文章中,實現的是如下效果:
實現的基本原理就是在一個 FrameLayout 中,設定一個 RV,然後在設定一個和 ItemView 一樣佈局結構以及樣式的懸浮條,然後懸浮條根據條件動態設定位置。
而該文章中博主也說明了這種效果的實現方案,但那是在 RV 的 Item 只有一個層級的情況下,即所有的 ItemView 都是同一型別的,而我是在使用了 drakeet 大佬的 MultiType,實現了 資料扁平化處理
:
我需要讓下圖的 RV 也實現那種效果:
雖然存在 Post 和 Comment 兩種型別的 ItemView,但是由於扁平化的處理,兩種 ItemView 都處於同一層次結構,而不是巢狀的關係。即兩種 ItemView 都 RV 的直接 ItemView,並且其中某些 Post 型別的 ItemView 可能會不存在附屬的 Comment ItemView。這種情況下,如果完全按照參考文章的那種實現方法的話,則會得不到預期的效果,下圖為預期效果圖:
當然,主要的思想根據原參考文章的類似,但是在一些細節方面就需要做一下修改,這本例的實現中,RV 的兩種 ItemView 都是一個簡答的 TextView,只不過是在 Adapter 中動態設定樣式而已,因此懸浮條也是一個簡單的 TextView,且高度、樣式都要與 Post ItemView 的樣式一樣。
然後下面是核心程式碼,說明也依附在程式碼註釋上了,其中 mCurrentPosition
初始值為 0,因為在本次演示中不存在 HraderView,如果存在的話,則 mCurrentPosition
初始值應為第一個 Post ItemView 的 position
:
rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
LinearLayoutManager linearLayoutManager = (LinearLayoutManager) rv.getLayoutManager();
int mSuspensionHeight;
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// mSuspensionBar.getHeight()的高度的獲取如果是在 onCreate() 或者是
// 在 RecyclerView.OnScrollListener 被初始化的時候去獲取,獲得的結果
// 會為 0,因此此時 mSuspensionBar 還沒有初始化完成
mSuspensionHeight = mSuspensionBar.getHeight();
int firstVisPos = linearLayoutManager.findFirstVisibleItemPosition();
Object firstVisibleItem = items.get(firstVisPos);
Object nextItem = items.get(firstVisPos + 1);
View nextView = linearLayoutManager.findViewByPosition(firstVisPos + 1);
//下滑情況下
if (dy > 0) {
//只有第一個可見的 Item 的下一個 Item 的型別
//為 Post型別時才需要動態設定效果
if (nextItem instanceof Post) {
if (nextView.getTop() <= mSuspensionHeight) {
//被頂掉的效果
mSuspensionBar.setY(-(mSuspensionHeight - nextView.getTop()));
} else {
//否則就直接回到 Y = 0 的位置
mSuspensionBar.setY(0);
}
}
//判斷是否需要更新懸浮條
if (mCurrentPosition != firstVisPos && firstVisibleItem instanceof Post) {
mCurrentPosition = firstVisPos;
//根據 mCurrentPosition 的值,更新 mSuspensionBar
updateSuspensionBar();
mSuspensionBar.setY(0);
}
} else {//上滑情況
// 1、nextItem -> Post and firstVisibleItem -> Comment mCurrentPosition = ((Comment) firstVisibleItem).getParentPostPosition()
// 2、nextItem -> Post and firstVisibleItem -> Post mCurrentPosition = firstVisPos
// 3、nextItem -> Comment and firstVisibleItem -> Comment mSuspensionBar 不動
// 4、nextItem -> Comment and firstVisibleItem -> Post mSuspensionBar 不動
if (nextItem instanceof Post) {
mCurrentPosition = firstVisibleItem instanceof Post ? firstVisPos : ((Comment) firstVisibleItem).getParentPostPosition();
updateSuspensionBar();
if (nextView.getTop() <= mSuspensionHeight) {
//被頂掉的效果
mSuspensionBar.setY(-(mSuspensionHeight - nextView.getTop()));
} else {
mSuspensionBar.setY(0);
}
}
}
}
});
如果對於上面的程式碼有所疑惑,其實可以將 mSuspensionBar 的背景設定為不同的顏色,同時設定一下透明度,就可以看到其原本的運作狀態了,如下圖,其中 mSuspensionBar.setY(0)
時當效果尤為明顯:
其中,較為特殊的就是上滑的情況了,在上面的程式碼註釋中也有說明,上滑時總共有四種情況:
1、nextItem -> Post and firstVisibleItem -> Comment mCurrentPosition = ((Comment) firstVisibleItem).getParentPostPosition()
2、nextItem -> Post and firstVisibleItem -> Post mCurrentPosition = firstVisPos
3、nextItem -> Comment and firstVisibleItem -> Comment mSuspensionBar 不動
4、nextItem -> Comment and firstVisibleItem -> Post mSuspensionBar 不動
其中 ->
符號表示該 Item 對應的具體型別,只有頭兩種情況下,mSuspensionBar
才需要根據具體的情況設定動態效果,剩下的兩種情況下只要固定不動就可以了。
還需要說明的是,當 nextItem -> Post and firstVisibleItem -> Comment
時,正常情況是無法知道第一個可見 Item (即 firstVisibleItem
)所附屬於的 Post 的 position
,因此需要在初始化這些 Comment Item 的時候就設定好其附屬於的 Post 的 position
,然後動態獲取。
就像下面的程式碼,會在初始化 Comment 元素時為其設定所附屬的 Post 的 position
:
//模擬資料
List<Post> list = new ArrayList<>();
int index = 0;
int parentPostPos;
Random random = new Random();
for (int i = 0; i < 10; i++) {
Post post = new Post("pos = " + index);
parentPostPos = index;
list.add(post);
index++;
int k = random.nextInt(5);
post.comments = new ArrayList<>();
for (int j = 0; j < k; j++) {
Comment comment = new Comment("pos = " + index, parentPostPos);
post.comments.add(comment);
index++;
}
}
最後,再推薦一篇實現本文效果的文章:
在該篇文章中的實現,是利用了 recyclerView.addItemDecoration()
來自定義 ItemDecoration 實現的效果,這種方式實現了與業務的解耦,但在具體實現上相比上面的實現更加複雜一點,而且在遇到第三方的涉及 RV 的框架時,就可能需要根據具體的框架去進行相應的修改了,如在使用 MultiType
時,就不是那麼好契合了。
相關推薦
RecyclerView Item 的懸浮效果(吸附效果)的實現
在參考文章中,實現的是如下效果: 實現的基本原理就是在一個 FrameLayout 中,設定一個 RV,然後在設定一個和 ItemView 一樣佈局結構以及樣式的懸浮條,然後懸浮條根據條件動態設定位置。 而該文章中博主也說明了這種效果的實現方
recyclerview給item新增選中效果(多選)
大體實現思路: 使用相對佈局,在recyclerview的item整體佈局底層新增一個CheckBox,在adapter中引用一個Map標記選中CheckBox,然後在bandview中給CheckBox setOnCheckedChangeListener改變CheckB
微信小程式tab導航+滾動頂部吸附效果(開發例項)
<!-- scroll導航欄 --> <view class='scrollBox2 fix-news' wx:if="{{fixTop<scrollTop}}"&g
原生js三種選項卡效果(輪播)
col val 還在 log pla absolut 自動播放 div pac 第三種:定時輪播切換(我這邊定時是2s) <!DOCTYPE html> <html> <head> <meta charset="utf-8"
原生js三種選項卡效果(點擊)
eight void log utf 觸發 nts lin type position 第一種:選項卡單擊點擊切換 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /&g
微信小程序左右滑動切換圖片酷炫效果(附效果)
bin select ans for image pac psi border als 開門見山,先上效果吧!感覺可以的用的上的再往下看。 心動嗎?那就繼續往下看! 先上頁面結構吧,也就是wxml文件,其實可以理解成微信自己封裝過的html,這個不多說了,不懂
Unity實現震屏效果(螢幕抖動)
通過設定相機的Viewport Rect 來實現,將下面的指令碼掛在相機上,設定enabled=true就可實現螢幕震動效果。 using System.Collections; using System.Collections.Generic; usin
npm run build 打包後,如何執行在本地檢視效果(Nginx服務)
這段時間,有點時間,研究了一下vue 打包的很慢的問題。但是當我 npm run build 打包後,在本地檢視效果的時候,活生生被我老大鄙視了,因為我打開了XAMPP。他說:你怎麼不用Nginx啊?用這個一堆的路徑問題!!!!!! 然後我就去研究了N
npm run build 打包後,如何運行在本地查看效果(Nginx服務)
get 工具 下載 inf 使用 執行 是我 map lan 這段時間,有點時間,研究了一下vue 打包的很慢的問題。但是當我 npm run build 打包後,在本地查看效果的時候,活生生被我老大鄙視了,因為我打開了XAMPP。他說:你怎麽不用Nginx
jquery 實現動畫效果(各種方法)
asc func 綜合 oat 代碼 jquer 一秒 遞歸 pan 1.show()和hide()和toggle()(這是show和hide的一個綜合,一個按鈕就實現顯示和隱藏) 效果: 代碼: <button type="button" class="show"
微信小程式實現跑馬燈效果(完整程式碼)
在微信小程式 裡實現跑馬燈效果,類似滾動字幕或者滾動廣告之類的,使用簡單的CSS樣式控制,沒用到JS,效果如下圖: Wxml程式碼: <!--跑馬燈 Linyufan.com--> <view class="marquee_container" st
svg 環形進度條加讀取進度效果(讀數效果)-- 移動端 rem 適配
專案需求做一個環形進度條的效果需要有一個讀數的效果,在網上查閱相關資料後整理了下 gif 效果如下,錄製的不是很流暢多停留下時間看下 都是動態的效果 程式碼如下 <!DOCTYPE html> <html lang="en">
移動端阻止瀏覽器中預設元素滑動回彈效果(橡皮筋效果)
在js檔案中加如下程式碼: document.addEventListener('touchstart',function(e){ e.preventDefault(); //
jquery-fly實現新增購物車拋物線效果(angular版)
<!DOCTYPE html> <html ng-app="myApp"> <head> <meta charset="UTF-8"> <meta http-equiv="Pragma" content="no-cache"
實現一個垂直跑馬燈的效果(垂直公告)
實現一個簡單的跑馬燈的效果,類似於App裡面的通知:恭喜XXX獲得了什麼什麼的效果。 首先先匯入兩個工具類 import android.app.Activity; import android.content.Context; import and
詳解vue2.0 使用動態元件實現 Tab 標籤頁切換效果(vue-cli)
在 vue 中,實現 Tab 切換主要有三種方式:使用動態元件,使用 vue-router 路由,使用第三方外掛。因為這次完成的功能只是簡單切換元件,再則覺得使用路由切換需要改變地址略微麻煩,所以使用的是動態元件實現,如果是在大型應用上,可能使用 vue-router 會方便
用input輸入框實現好看的複選框效果(css+jq)
做畢設果然是道阻且長QAQ,在用到一個複選框的時候由於嫌棄複選框實在太醜了,就自己做了一個。其中沒有用到任何圖片,用css和jQuery實現。 廢話不多說直接看最後效果: html元素的設計如下
MIUI 拖動視差效果(阻尼效果/橡皮筋效果)
Parallax 專案地址:xiaoyanger0825/Parallax 簡介:MIUI 拖動視差效果(阻尼效果/橡皮筋效果) 更多:作者 提 Bug 官網 標籤:
res-----不同圖片實現動畫效果(幀動畫)
1、準備幾張圖片(可命名為a1-a6) 2、在drawable資料夾下新建xml,內容如下 <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.androi
沉浸式的簡單實現效果(很簡單)
在Activity中實現這個方法,就可以實現沉浸式,但是必須在5.0以上的系統中實現 public void onWindowFocusChanged(boolean hasFocus) {//沉浸式 super.onWindowFocusChanged(hasFocus