Android瀑布流詳解

一、Android瀑布流布局

瀑布流布局,也稱為瀑布流式布局,是一種網頁設計布局。該布局會自動適應瀏覽器窗口大小,並將內容按照特定的方式進行展示,使得頁面更美觀優雅。在Android中,我們也可以使用瀑布流布局來實現相冊、商品展示等場景。

Android中最常用的瀑布流布局是StaggeredGridView,它提供了多列瀑布流展示功能,讓圖片或者其他控件更加美觀,流暢。使用它可以很方便地實現瀑布流布局。


compile 'com.etsy.android.grid:library:1.0.5'

然後在布局文件中使用StaggeredGridView即可:




二、Android瀑布流實現2列圖片展示

在實際開發中,我們經常需要將一些圖片展示在瀑布流布局中,以下是如何展示兩列圖片:


StaggeredGridView gridView = (StaggeredGridView) findViewById(R.id.grid_view);
gridView.setAdapter(new StaggeredAdapter(this, imageData));  // 設置適配器
gridView.setColumnCount(2);  // 設置為兩列

其中StaggeredAdapter是自定義適配器,可以根據需求自行實現。

三、Android瀑布流頂部空白移動

在瀑布流布局中,默認情況下每個item都是按照順序排列的,沒有任何間隔。而在實際開發中,我們通常需要給每個item留出一定的間隔,或者讓第一行的item頂部留出空白。對於這個問題,可以使用StaggeredGridView的一些屬性來解決。


app:item_margin="2dp"
app:first_vertical_spacing="2dp"

其中,item_margin是設置item之間的間距,first_vertical_spacing是設置第一行item頂部空出的距離。

四、Android瀑布流實現

實現瀑布流布局可以使用StaggeredGridView,但如果自定義實現呢?這裡提供一種自定義實現方式:


public class WaterfallLayout extends ViewGroup {

    private int mColumns = 2;  // 列數
    private int mItemGap = 10;  // item間距
    private int mTopBlank = 10;  // 頂部空白高度
    private List mColumnsHeight = new ArrayList();  // 每列的高度
    private List mItemList = new ArrayList();  // item控件list

    public WaterfallLayout(Context context) {
        super(context);
        init();
    }

    private void init() {
        mColumnsHeight.clear();
        for (int i = 0; i < mColumns; i++) {
            mColumnsHeight.add(mTopBlank);
        }
    }

    ...

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        for (int i = 0; i < mColumns; i++) {
            // 遍歷每一列上的item子控件,設置控件位置
            for (int j = 0; j < getChildCount(); j++) {
                View child = getChildAt(j);
                if (child.getVisibility() == View.GONE) {
                    continue;
                }
                LayoutParams layoutParams = child.getLayoutParams();
                int cHeight = child.getMeasuredHeight();
                if ((layoutParams instanceof MarginLayoutParams)) {
                    MarginLayoutParams params1 = (MarginLayoutParams) layoutParams;
                    cHeight += params1.topMargin + params1.bottomMargin;
                }
                if (mItemList.contains(child)) {
                    continue;
                }
                int column = getMinHeightColumn();
                int lC = getPaddingLeft() + column * (getMeasuredWidth() / mColumns) + column * mItemGap;
                int rC = lC + getMeasuredWidth() / mColumns;
                int tC = mColumnsHeight.get(column);
                int bC = tC + cHeight;
                child.layout(lC, tC, rC, bC);  // 設置位置
                mColumnsHeight.set(column, bC + mItemGap);
                mItemList.add(child);
            }
        }
    }
}

五、Android瀑布流間分割線

在瀑布流布局中,我們通常需要給每個item之間加上間隔線。可以在item布局文件中添加一個View來實現:





    
    



其中,View的高度和背景色可以根據需求自行調整。

六、Android瀑布流multitype

multitype是一種瀑布流擴展庫,支持多條目類型、動態添加刪除等功能。使用multitype,可以方便地實現多種類型的瀑布流布局。


repositories {
    maven { url "https://jitpack.io" }
}
dependencies {
    implementation 'com.github.Skykai521:MutiType:v1.0.1'
}

使用方法與RecyclerView類似,我們需要定義不同類型的Holder


@MutiTypeItemType(1)
public class TextItem implements Item {

    public String text;

    public TextItem(String text) {
        this.text = text;
    }

    @Override
    public int itemType() {
        return 1;
    }

    @Override
    public int itemId() {
        return text.hashCode();
    }

    @Override
    public boolean isItemSameAs(Item newItem) {
        return newItem instanceof TextItem && ((TextItem) newItem).text.equals(text);
    }

    @Override
    public boolean isContentSameAs(Item newItem) {
        return newItem instanceof TextItem && ((TextItem) newItem).text.equals(text);
    }
}

然後在Adapter中調用Bind和onCreate方法即可:


public class MyAdapter implements BindDelegate {

    public List items;

    public MyAdapter(List items) {
        this.items = items;
    }

    @Override
    public void onBindViewHolder(BindViewHolder holder, int position, List payloads) {
        Item item = items.get(position);
        if (holder.getItemViewType() == 1) {
            TextItem textItem = (TextItem) item;
            TextView textView = holder.itemView.findViewById(R.id.text_view);
            textView.setText(textItem.text);
        }
    }

    @Override
    public BindViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View root;
        if (viewType == 1) {
            root = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_item, parent, false);
        } else {
            root = LayoutInflater.from(parent.getContext()).inflate(R.layout.image_item, parent, false);
        }
        return new BindViewHolder(root);
    }

    @Override
    public int getItemCount() {
        return items == null ? 0 : items.size();
    }

    @Override
    public int getItemViewType(int position) {
        return items.get(position).itemType();
    }
}

七、Android瀑布流搭配paging3

在實際開發中,我們通常需要使用分頁展示數據。而paging3是Google推出的分頁加載的庫,可以讓我們更方便地實現數據分頁。下面是一個利用paging3實現分頁數據加載的例子:


private fun initRecyclerView() {
    val staggeredAdapter = StaggeredAdapter(viewModel)
    recyclerView.apply {
        setHasFixedSize(true)
        layoutManager = StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL)
        adapter = staggeredAdapter.withLoadStateHeaderAndFooter(
        header = PagingLoadStateAdapter(staggeredAdapter),
        footer = PagingLoadStateAdapter(staggeredAdapter)
        )
    }
    viewModel.pagerFlow.collectLatest { pagingData ->
        staggeredAdapter.submitData(pagingData)
    }
}

其中,StaggeredAdapter繼承自PagingDataAdapter,可以根據具體需求進行實現。

八、Android瀑布流布局滑動錯位

在使用瀑布流布局的時候,有時候會出現滑動錯位的現象。這個問題通常是由於item的高度不一致導致的。正確的做法是在父布局裏面重寫onMeasure方法,自動確定item的高度:


@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    int columnWidth = getMeasuredWidth() / mColumns;
    int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
    for (int i = 0; i < getChildCount(); i++) {
        View child = getChildAt(i);
        if (child.getVisibility() == View.GONE) {
            continue;
        }
        // 重新計算item高度
        LayoutParams layoutParams = child.getLayoutParams();
        int cWidth = columnWidth - layoutParams.leftMargin - layoutParams.rightMargin;
        child.measure(MeasureSpec.makeMeasureSpec(cWidth, MeasureSpec.EXACTLY), childHeightMeasureSpec);
    }
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}

九、Android瀑布流設置條目橫向間距

瀑布流布局默認的間距可能不符合我們的需求,我們可以使用StaggeredGridView的setHorizontalSpacing方法來調整橫向間距:


StaggeredGridView gridView = (StaggeredGridView) findViewById(R.id.grid_view);
gridView.setAdapter(new StaggeredAdapter(this, imageData));
gridView.setColumnCount(2);
gridView.setHorizontalSpacing(20);  // 設置橫向間距

結束語

Android瀑布流布局是一種非常實用的布局方式,可以使得頁面更加美觀、流暢。通過本文的介紹,希望讀者能夠更好地理解和應用瀑布流布局,並在實際開發中能夠運用自如。

原創文章,作者:OJHHM,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/360902.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
OJHHM的頭像OJHHM
上一篇 2025-02-24 00:33
下一篇 2025-02-24 00:33

相關推薦

  • Android ViewPager和ScrollView滑動衝突問題

    Android開發中,ViewPager和ScrollView是兩個常用的控件。但是當它們同時使用時,可能會發生滑動衝突的問題。本文將從多個方面介紹解決Android ViewPa…

    編程 2025-04-28
  • Android如何點擊其他區域收起軟鍵盤

    在Android應用中,當輸入框獲取焦點彈出軟鍵盤後,我們希望能夠點擊其他區域使軟鍵盤消失,以提升用戶體驗。本篇文章將說明如何實現這一功能。 一、獲取焦點並顯示軟鍵盤 在Andro…

    編程 2025-04-28
  • Android Studio HUD 實現指南

    本文將會以實例來詳細闡述如何在 Android Studio 中使用 HUD 功能實現菊花等待指示器的效果。 一、引入依賴庫 首先,我們需要在 build.gradle 文件中引入…

    編程 2025-04-27
  • Android和Vue3混合開發方案

    本文將介紹如何將Android和Vue3結合起來進行混合開發,以及其中的優勢和注意事項。 一、環境搭建 在進行混合開發之前,需要搭建好相應的開發環境。首先需要安裝 Android …

    編程 2025-04-27
  • Android Java Utils 可以如何提高你的開發效率

    Android Java Utils 是一款提供了一系列方便實用的工具類的 Java 庫,可以幫助開發者更加高效地進行 Android 開發,提高開發效率。本文將從以下幾個方面對 …

    編程 2025-04-27
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • MPU6050工作原理詳解

    一、什麼是MPU6050 MPU6050是一種六軸慣性傳感器,能夠同時測量加速度和角速度。它由三個傳感器組成:一個三軸加速度計和一個三軸陀螺儀。這個組合提供了非常精細的姿態解算,其…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25

發表回復

登錄後才能評論