精品视频在线免费观看_国产精品资源网_欧美日韩亚洲综合在线_自拍视频国产精品

原創生活

國內 商業 滾動

基金 金融 股票

期貨金融

科技 行業 房產

銀行 公司 消費

生活滾動

保險 海外 觀察

財經 生活 期貨

當前位置:滾動 >

輕松實現RecyclerView懸浮條,就是如此簡單!

文章來源:財金網  發布時間: 2019-04-23 10:38:51  責任編輯:cfenews.com
+|-

【原標題:輕松實現RecyclerView懸浮條,就是如此簡單!】財金網消息 在我們在刷Instagram的動態時,你是否注意到這樣一個小小的動效,就是當一條動態(以卡片形式呈現)向上滑動時,動態卡片的頭部會始終懸浮在列表最上方,直到下一張動態卡片的頭部將它頂掉并替換它懸浮著。言語可能說不清楚,就直接來看一下它的效果好了。

綜合我上面的文字描述加上這張Gif圖,我想大家應該知道這是個什么樣的效果了吧。那么不廢話了,接下來我就來說說一種很簡單的實現方法吧。

思路

雖然實現起來炒雞簡單,但還是花了我一個多小時的時間思考實現。先說說思考過程吧,那天中午,Instagram給我推了一條消息(哈,就是我最喜歡的偶像金泰妍更新了Ins),于是我就點進去看了,喜歡了之后就開始研究這個效果,我反復地上下滑這個列表,因為Ins的列表有滾動條,我就發現每次滾動條在那個懸浮條附近的時候就會特別短。看到這個現象,敏銳的你是不是察覺到了什么?沒錯,我感覺這個就像是FrameLayout的效果,一個FrameLayout里按順序有列表,懸浮條兩個View,懸浮條覆蓋在列表的上方,它在合適的時機更新自己的位置,在合適的時機更新自己的信息,然后看上去就像是一個懸浮的效果。

接下來我們思考的核心就轉移到了如何確定并找到這個合適的時機。

再仔細觀察上面的Gif圖,我們可以確定當第二個列表項的頭部距離列表頂端一個懸浮條的距離時,懸浮條隨著列表的滑動改變自身的位置,從而看起來像是被頂掉的效果。畫一張簡單位置示意圖

那么,數據更新的時機也很容易確定,就是在懸浮條恰好完全被頂掉的時候,更新自己的數據,并移動到列表頂部。

至于如何找到這個時機會在接下來的實現部分講解。

實現

建立布局

如上面所言,就是一個簡單的FrameLayout。

<FrameLayout

android:layout_width="match_parent"

android:layout_height="match_parent"

app:layout_behavior="@string/appbar_scrolling_view_behavior">

<android.support.v7.widget.RecyclerView

android:id="@+id/feed_list"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:background="@android:color/white"

android:scrollbars="vertical" />

……

 

 

注意這里FrameLayout的第二個child應該為你列表項要懸浮顯示的布局。

找到時機

根據我們的思路,我們首先要找到第二個列表項的頭部距離列表頂端一個懸浮條的距離時的那個時機,如果我們能找到這個時機,那么第二個時機也相當于找出來了。

這里我們使用的是RecyclerView來實現列表,我們都知道RecyclerView的列表布局是由LayoutManager來確定的,由于一般要實現懸浮條顯示效果的列表一般都為線性列表,即我們一般會使用LinearLayoutManager。通過LinearLayoutManager,我們可以很方便的獲取到RecyclerView中相應位置的View,這里我們需要獲取當前懸浮條數據來源的View和其下一個數據來源的View。這兩個View有什么用呢?懸浮條顯示的信息是來自第一個可見View的,而其下方的View正是第二個列表項,我們可以獲取到它的top值。好了接下來就真的很簡單了,我們只要給RecyclerView加一個ScrollListener,并在相應的回調里做之前我們想好的事就ok了,來看一下代碼

mFeedList.addOnScrollListener(new RecyclerView.OnScrollListener() {

@Override

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

super.onScrollStateChanged(recyclerView, newState);

mSuspensionHeight = mSuspensionBar.getHeight();

}

@Override

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

super.onScrolled(recyclerView, dx, dy);

View view = linearLayoutManager.findViewByPosition(mCurrentPosition + 1);

if (view != null) {

if (view.getTop() <= mSuspensionHeight) {

mSuspensionBar.setY(-(mSuspensionHeight - view.getTop()));

} else {

mSuspensionBar.setY(0);

}

}

if (mCurrentPosition != linearLayoutManager.findFirstVisibleItemPosition()) {

mCurrentPosition = linearLayoutManager.findFirstVisibleItemPosition();

mSuspensionBar.setY(0);

updateSuspensionBar();

}

}

});

Tips:其中mCurrentPosition為懸浮條信息來自的那個列表項在RecyclerView的位置。還有這里的ScrollListener可以添加多個,在RecyclerView中會檢查所有的ScrollListener并觸發。

One more thing…

接下來,我們還需要……開玩笑,哪來的One more thing,我們已經完成了?什么?這么快?這么一點代碼?恩,沒錯,就是只要這么一點代碼就好了,我們來看一下最后我們實現的效果(當然最終效果的好壞還是取決與你列表項的布局,比如在Ins里這個效果就很好看呢~)

結語

哈哈,是不是很簡單呢,最后再說一下封裝的事,本來我是想封裝一下的,由于每個人的列表布局都不一樣,數據更新方式也不一樣,就不封裝了,是的,我水平不行,雖然我不想承認~不過代碼真心特別少哦,源碼地址:https://github.com/wuapnjie/SuspensionBar

希望這篇文章可以對你有幫助,我也會繼續努力的。

補充

上面這種情況我們RecyclerView的Item是單一的,但是我們的列表Item通常有很多種,只有在滑到我們想要類型的Item時才需要更新我們的懸浮條信息。比如很常見的通訊錄,在我們滑到從A開頭聯系人滑到B開頭聯系人時,懸浮條的信息才從A變為B;再比如印象筆記的筆記列表,頂部的懸浮條是根據筆記的日期改變的。

那么,遇到這種情況我們應該怎么簡單修改代碼來實現我們需求呢?

其實很簡單,思路已經由上面確定了,只是我們要讓懸浮條移動的時機變化,變得更窄了,同時我們要更新的數據內容也發生了變化(這當然需要我們變換相應的布局)。

mFeedList.addOnScrollListener(new RecyclerView.OnScrollListener() {

@Override

public void onScrollStateChanged(RecyclerView recyclerView, int newState) {

super.onScrollStateChanged(recyclerView, newState);

mSuspensionHeight = mSuspensionBar.getHeight();

}

@Override

public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

super.onScrolled(recyclerView, dx, dy);

//我們只是簡單的收窄了我們讓懸浮條移動的條件,這里就是ItemType必須對應時才發生移動

if (adapter.getItemViewType(mCurrentPosition + 1) == MultiFeedAdapter.TYPE_TIME) {

View view = linearLayoutManager.findViewByPosition(mCurrentPosition + 1);

if (view != null) {

if (view.getTop() <= mSuspensionHeight) {

mSuspensionBar.setY(-(mSuspensionHeight - view.getTop()));

} else {

mSuspensionBar.setY(0);

}

}

}

if (mCurrentPosition != linearLayoutManager.findFirstVisibleItemPosition()) {

mCurrentPosition = linearLayoutManager.findFirstVisibleItemPosition();

mSuspensionBar.setY(0);

updateSuspensionBar();

}

}

});

上面的代碼我們只要注意注釋處,其他的和之前給出的相同。

總之,雖然大家的需求可能不同,但萬變不離其宗。只要掌握了思路,什么需求都不怕。

Github 上已增加相應代碼,最后看一下我們的效果,只在時間變化時才移動懸浮條

專題首頁|財金網首頁

原創
新聞

精彩
互動

獨家
觀察

京ICP備2021034106號-38   營業執照公示信息  財金網  版權所有  cfenews.com  投稿郵箱:362293157@qq.com  業務QQ:362293157立即發帖
主站蜘蛛池模板: 国产精品日韩精品| 国产精品青草久久久久福利99| 国产日产久久高清欧美一区| 欧美专区中文字幕| 久久久99免费视频| 涩涩日韩在线| 91精品国产综合久久久久久蜜臀| 久久综合久久网| 高清国语自产拍免费一区二区三区| 91久久精品国产| 亚洲高清在线观看一区| 日韩久久久久久久久久久久久| 日韩欧美99| 国产日韩欧美视频| 日本久久久a级免费| 国产欧美日韩综合精品| 国产精品久久久久影院日本| 亚洲v国产v| 国产精品永久在线| 国产精品麻豆免费版 | 国产超级av在线| 欧美精品aaa| 91精品国产精品| 国产精品一区在线观看| 欧美精品在线观看91| 国产精品久久久久7777| 欧美在线亚洲在线| 国产精品一区二区三| 免费久久99精品国产自| 日韩av中文字幕第一页| 俄罗斯精品一区二区| 国产精品无av码在线观看| 国产精品手机播放| 国产精品视频免费一区| 久99久在线| 久久成人av网站| 久久精品无码中文字幕| 国产精品久在线观看| 国产麻豆日韩| 国产精品视频xxxx| 久久久久福利视频|