最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

Android RecyclerView 實現(xiàn)瀑布流

2023-03-14 22:41 作者:程序員徐公  | 我要投稿

瀑布流也是個常用的顯示控件了,但是在使用時經(jīng)常遇到一些問題,比如滑動回頂部后出現(xiàn)空隙、item在滑動時亂跳等問題。

下面就來說說我怎么實現(xiàn)的瀑布流,并且怎么處理上面所說的這些問題的。

我使用了原生控件RecyclerView+StaggeredGridLayoutManager來實現(xiàn)的瀑布流,沒有用第三方開源框架。下面以2列的瀑布流為例子開始講解。

因為使用了StaggeredGridLayoutManager實現(xiàn)瀑布流,但是在設(shè)置后發(fā)現(xiàn)圖片在滑動加載過程中高度會發(fā)生變化,在網(wǎng)上搜索了很多資料后,總結(jié)解決辦法是在onBindViewHolder中綁定View時,給ImageView設(shè)置寬高,就能解決這個問題。

先看一下最終實現(xiàn)效果:

img

正常顯示的瀑布流.gif

提前說明下,我使用的是Glide3,讀者們可以自行修改為Glide4。

1.實現(xiàn)瀑布流

先說說實現(xiàn)思路:

  • 寫布局文件,分別有2個布局文件,Activity的布局文件和Adapter的布局文件

  • 寫適配器,瀑布流的適配器里需要設(shè)置ImageView的寬高。

  • 寫RecyclerView,給RecyclerView設(shè)置StaggeredGridLayoutManager并設(shè)置適配器。

  • 添加數(shù)據(jù)測試效果,根據(jù)效果反饋進(jìn)行修改

第一步:寫布局文件

Activity的布局文件只有一個RecyclerView就不貼了,貼一下Adapter的布局文件:

adapter_item_card.xml

<?xml?version="1.0"?encoding="utf-8"?>
<LinearLayout?xmlns:android="http://schemas.android.com/apk/res/android"
????xmlns:tools="http://schemas.android.com/tools"
????android:id="@+id/card"
????android:layout_width="match_parent"
????android:layout_height="wrap_content"
????android:layout_marginTop="10dp"
????android:background="@android:color/holo_green_dark"
????android:orientation="vertical">


????<ImageView
????????android:id="@+id/card_image"
????????android:layout_width="match_parent"
????????android:layout_height="wrap_content"
????????tools:src="@mipmap/ic_launcher"?/>


????<TextView
????????android:id="@+id/card_title"
????????android:layout_width="wrap_content"
????????android:layout_height="wrap_content"
????????android:layout_gravity="center_horizontal"
????????android:layout_marginTop="8dp"
????????android:layout_marginBottom="2dp"
????????tools:text="hello"?/>

</LinearLayout>

第二步:寫適配器

適配器中包含數(shù)據(jù)Card的集合,Card類包含如下幾個屬性:

????private?String?title;
????private?String?img_url;
????private?int?width;
????private?int?height;

在適配器中主要就是將數(shù)據(jù)綁定到view上,最關(guān)鍵的步驟是根據(jù)圖片的寬高算出圖片的寬高比,然后根據(jù)寬高比選擇正方形顯示,還是長方形顯示,最后通過setLayoutParams方法來設(shè)置圖片的寬高。

思路如下:

  • 計算圖片寬度

  • 根據(jù)圖片寬高比,確定圖片使用正方形或是4比3的長方形顯示

  • 使用setLayoutParams方法設(shè)置圖片寬高

  • 使用Glide加載圖片并用override重寫圖片寬高

適配器核心代碼如下:

private?final?double?STANDARD_SCALE?=?1.1;?//當(dāng)圖片寬高比例大于STANDARD_SCALE時,采用3:4比例,小于時,則采用1:1比例
private?final?float?SCALE?=?4?*?1.0f?/?3;???????//圖片縮放比例
private?List<Card>?cards?=?new?ArrayList<>();

@Override
public?void?onBindViewHolder(@NonNull?ViewHolder?holder,?int?position)?{
????Card?card?=?mCards.get(position);
????setCardView(holder,?card);
}

private?void?setCardView(ViewHolder?holder,?Card?card)?{
????//計算圖片寬高
????LinearLayout.LayoutParams?layoutParams?=?(LinearLayout.LayoutParams)?holder.image.getLayoutParams();
????//2列的瀑布流,屏幕寬度減去兩列間的間距space所的值再除以2,計算出單列的imageview的寬度,space的值在RecyclerView初始化時傳入
????float?itemWidth?=?(ScreenUtil.getScreenWidth(context)?-?space)?/?2;
????layoutParams.width?=?(int)?itemWidth;

????float?width?=?card.getWidth();
????float?height?=?card.getHeight();
????float?scale?=?height?/?width;
????if?(scale?>?STANDARD_SCALE)?{
????????//采用3:4顯示
????????layoutParams.height?=?(int)?(itemWidth?*?SCALE);
????}?else?{
????????//采用1:1顯示
????????layoutParams.height?=?(int)?itemWidth;
????}
????holder.image.setLayoutParams(layoutParams);
????Glide.with(context).load(card.getImg_url()).asBitmap().placeholder(R.mipmap.ic_launcher)
????????????.diskCacheStrategy(DiskCacheStrategy.RESULT).centerCrop().into(holder.image);
????holder.title.setText(card.getTitle());
}

寫好適配器后,就可以在MAinActivity中初始化RecyclerView和適配器了,代碼如下:

????????int?space?=?20;
????????StaggeredGridLayoutManager?layoutManager?=?new?StaggeredGridLayoutManager(2,?StaggeredGridLayoutManager.VERTICAL);
//????????layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE);???//設(shè)置后瀑布流不顯示了
????????mRecyclerView.setLayoutManager(layoutManager);
????????mRecyclerView.setItemAnimator(null);
????????mRecyclerView.addItemDecoration(new?StaggeredItemDecoration(space));//單位px
????????mAdapter?=?new?StaggeredGridAdapter(space);
????????mAdapter.setCards(mCards);
????????mRecyclerView.setAdapter(mAdapter);

在網(wǎng)上看到使用StaggeredGridLayoutManager的setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE)設(shè)置來處理瀑布流滑動到頂部空白的問題,結(jié)果發(fā)現(xiàn)添加這句代碼后,整個瀑布流都不顯示了,所以不能這樣處理。

在上面的代碼中我設(shè)置了space值,space是指兩列卡片之間的距離,根據(jù)需求設(shè)置,這里space用在了2個地方分別是:

mRecyclerView.addItemDecoration(new?StaggeredItemDecoration(space));
mAdapter?=?new?StaggeredGridAdapter(space);

前者用于設(shè)置兩列瀑布流之間的距離,后者是用來計算單列圖片的寬度。StaggeredItemDecoration類的代碼在此。

代碼寫好后,來看看瀑布流效果。

img

好像有點奇怪的地方,在滑動過程中前面圖片1、2、3的大小發(fā)生了變化。我當(dāng)時也是很疑惑,在網(wǎng)上搜索圖片大小改變的問題原因也沒有找到,好像與RecyclerView的圖片緩存機制有關(guān),有知道的胖友可以告知一下。

最后通過在Glide加載圖片時添加override設(shè)置圖片寬高解決了,關(guān)于override設(shè)置圖片可以看看這篇文章《Glide的override方法和View的setLayoutParams方法設(shè)置圖片寬高對比》。

Glide.with(context).load(card.getImg_url()).asBitmap().placeholder(R.mipmap.ic_launcher)
????????????????.diskCacheStrategy(DiskCacheStrategy.RESULT).override(layoutParams.width,?layoutParams.height).centerCrop().into(holder.image);

解決后的效果如下,可以看到在滑動過程中,圖片大小沒有再變化:

img

正常顯示的瀑布流.gif

2. 瀑布流頂部出現(xiàn)空隙、item亂跳等問題

照上面的處理已經(jīng)能解決頂部出現(xiàn)空隙、item亂跳的問題,但是建議在瀑布流更新時采用notifyItemRangeInserted()方法更新,可以避免一些不必要的問題。

if?(FIRST_PAGE_LAST_ID.equals(lastId))?{
????mAdapter.notifyDataSetChanged();//第一頁更新
}?else?{
????mAdapter.notifyItemRangeInserted(startPosition,?count);//第一頁以外使用notifyItemRangeInserted()更新
}

如果對你有幫助的話,點贊、評論、贊賞都是對我的鼓勵,也是支持我寫下去的動力,謝謝!


Android RecyclerView 實現(xiàn)瀑布流的評論 (共 條)

分享到微博請遵守國家法律
泌阳县| 楚雄市| 漾濞| 河津市| 喀什市| 昔阳县| 东乡族自治县| 邵阳县| 梅河口市| 承德市| 古丈县| 邮箱| 黔西县| 会理县| 宿松县| 云和县| 洪雅县| 四平市| 习水县| 英吉沙县| 酉阳| 云阳县| 犍为县| 海南省| 永靖县| 彭阳县| 宜兰县| 蒲江县| 页游| 阿鲁科尔沁旗| 儋州市| 江川县| 祁阳县| 县级市| 长乐市| 鱼台县| 怀来县| 米易县| 连平县| 霸州市| 汉川市|