3.Android高仿網易雲音樂-首頁複雜發現界面佈局和功能/RecyclerView複雜佈局

来源:https://www.cnblogs.com/woblog/archive/2022/07/24/16513959.html
-Advertisement-
Play Games

Android高仿網易雲音樂-首頁複雜發現界面佈局和功能,效果圖依次為發現界面頂部,包含首頁輪播圖,水平滾動的按鈕,推薦歌單;然後是發現界面推薦單曲,點擊單曲就是直接進入播放界面。 ...


0.效果圖

效果圖依次為發現界面頂部,包含首頁輪播圖,水平滾動的按鈕,推薦歌單;然後是發現界面推薦單曲,點擊單曲就是直接進入播放界面;最後是全局播放控制條上點擊播放列表按鈕顯示的播放列表彈窗。

1.整體分析

整體使用RecycerView實現,每個不同的塊是一個Item,例如:輪播圖是一個Item,按鈕也是,推薦歌單和下麵的歌單是,推薦單曲,還有最後的自定義首頁那塊也是一樣。

提示:之所以把推薦歌單下麵的歌單和推薦歌單標題放一個Item,主要是首頁要實現自定義順序功能,更方便管理。

2.輪播圖

2.1 佈局

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_height="wrap_content"
    android:layout_margin="@dimen/padding_outer">

    <com.youth.banner.Banner
        android:id="@+id/banner"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="H,0.389"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

2.2 顯示數據

//banner
BannerData data = (BannerData) d;

Banner bannerView = holder.getView(R.id.banner);

BannerImageAdapter<Ad> bannerImageAdapter = new BannerImageAdapter<Ad>(data.getData()) {

    @Override
    public void onBindView(BannerImageHolder holder, Ad data, int position, int size) {
        ImageUtil.show(getContext(), (ImageView) holder.itemView, data.getIcon());
    }
};

bannerView.setAdapter(bannerImageAdapter);

bannerView.setOnBannerListener(onBannerListener);

bannerView.setBannerRound(DensityUtil.dip2px(getContext(), 10));

//添加生命周期觀察者
bannerView.addBannerLifecycleObserver(fragment);

bannerView.setIndicator(new CircleIndicator(getContext()));

按鈕

3.1 佈局

<?xml version="1.0" encoding="utf-8"?>
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingVertical="@dimen/padding_outer"
    android:scrollbars="none">

    <LinearLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingHorizontal="@dimen/padding_meddle">

    </LinearLayout>
</HorizontalScrollView>

3.2 顯示數據

LinearLayout container = holder.getView(R.id.container);
if (container.getChildCount() > 0) {
    //已經添加了
    return;
}

//橫向顯示5個半
float containerWidth = ScreenUtil.getScreenWith(container.getContext()) - DensityUtil.dip2px(container.getContext(), 10 * 2);
int itemWidth = (int) (containerWidth / 5.5);
DiscoveryButtonBinding binding;
LinearLayout.LayoutParams layoutParams;
for (IconTitleButtonData it : data.getData()) {
    binding = DiscoveryButtonBinding.inflate(LayoutInflater.from(getContext()));
    binding.icon.setImageResource(it.getIcon());
    binding.title.setText(it.getTitle());

    if (it.getIcon() == R.drawable.day_recommend) {
        SuperViewUtil.show(binding.more);

        //顯示日期
        binding.more.setText(String.valueOf(SuperDateUtil.currentDay()));
    }

    //設置點擊事件
    binding.getRoot().setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });

    layoutParams = new LinearLayout.LayoutParams(itemWidth, ViewGroup.LayoutParams.WRAP_CONTENT);
    container.addView(binding.getRoot(), layoutParams);
}

4.推薦歌單

4.1 佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <include layout="@layout/item_discovery_title" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingHorizontal="@dimen/padding_outer"
        android:paddingBottom="@dimen/d5" />
</LinearLayout>

4.2 顯示數據

private void bindSheetData(BaseViewHolder holder, SheetData data) {
    //設置標題,將標題放到每個具體的item上,好處是方便整體排序
    holder.setText(R.id.title, R.string.recommend_sheet);

    //顯示更多容器
    holder.setVisible(R.id.more, true);
    holder.getView(R.id.more).setOnClickListener(v -> {

    });

    RecyclerView listView = holder.getView(R.id.list);
    if (listView.getAdapter() == null) {
        //設置顯示3列
        GridLayoutManager layoutManager = new GridLayoutManager(listView.getContext(), 3);
        listView.setLayoutManager(layoutManager);

        sheetAdapter = new SheetAdapter(R.layout.item_sheet);

        //item點擊
        sheetAdapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(@NonNull BaseQuickAdapter<?, ?> adapter, @NonNull View view, int position) {
                if (discoveryAdapterListener != null) {
                    discoveryAdapterListener.onSheetClick((Sheet) adapter.getItem(position));
                }
            }
        });
        listView.setAdapter(sheetAdapter);

        GridDividerItemDecoration itemDecoration = new GridDividerItemDecoration(getContext(), (int) DensityUtil.dip2px(getContext(), 5F));
        listView.addItemDecoration(itemDecoration);
    }

    sheetAdapter.setNewInstance(data.getData());
}

5. 底部

5.1 佈局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginVertical="@dimen/padding_outer"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <androidx.appcompat.widget.LinearLayoutCompat
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center_vertical">

        <TextView
            android:id="@+id/refresh_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:drawableLeft="@drawable/refresh"
            android:gravity="center_vertical"
            android:text="@string/click_refresh"
            android:textColor="@color/link"
            android:textSize="@dimen/text_small" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/padding_small"
            android:text="@string/change_content"
            android:textColor="@color/black80"
            android:textSize="@dimen/text_small" />
    </androidx.appcompat.widget.LinearLayoutCompat>

    <com.google.android.material.button.MaterialButton
        android:id="@+id/custom"
        style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
        android:layout_width="wrap_content"
        android:layout_height="@dimen/d30"
        android:layout_marginTop="@dimen/padding_outer"
        android:backgroundTint="?attr/colorSurface"
        android:insetTop="0dp"
        android:insetBottom="0dp"
        android:text="@string/custom_discovery"
        android:textColor="@color/black80"
        android:textSize="@dimen/text_small"
        app:cornerRadius="@dimen/d15"
        app:elevation="0dp"
        app:strokeColor="@color/black80"
        app:strokeWidth="@dimen/d0_5" />
</LinearLayout>

5.2 顯示數據

holder.getView(R.id.refresh_button).setOnClickListener(v -> discoveryAdapterListener.onRefreshClick());
holder.getView(R.id.custom).setOnClickListener(v -> discoveryAdapterListener.onCustomDiscoveryClick());

6.迷你控制條

他是一個自定義Fragment,哪裡要顯示就放到哪裡就行了。

7.播放列表彈窗

/**
 * 播放列表對話框
 */
public class MusicPlayListDialogFragment extends BaseViewModelBottomSheetDialogFragment<FragmentDialogAudioPlayListBinding> {

    ...

    @Override
    protected void initListeners() {
        super.initListeners();
        //刪除所有按鈕點擊
        binding.deleteAll.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //關閉對話框
                dismiss();

                //刪除全部音樂
                getMusicListManager().deleteAll();
            }
        });

        //item中子控制項點擊
        //刪除按鈕點擊
        adapter.addChildClickViewIds(R.id.delete);

        adapter.setOnItemChildClickListener(new OnItemChildClickListener() {
            @Override
            public void onItemChildClick(BaseQuickAdapter adapter, View view, int position) {
                //由於這裡只有一個按鈕點擊
                //所以可以不判斷
                if (R.id.delete == view.getId()) {
                    //刪除按鈕點擊
                    removeItem(position);
                }
            }
        });

        //迴圈模式點擊
        binding.loopModel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //更改迴圈模式
                getMusicListManager().changeLoopModel();

                //顯示迴圈模式
                showLoopModel();

            }
        });

        //設置item點擊事件
        adapter.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(BaseQuickAdapter adapter, View view, int position) {
                //關閉dialog
                //可以根據具體的業務邏輯來決定是否關閉
                dismiss();

                //播放點擊的這首音樂
                getMusicListManager().play(getMusicListManager().getDatum().get(position));
            }
        });

    }

    private void removeItem(int position) {
        adapter.removeAt(position);

        //從列表管理器中刪除
        getMusicListManager().delete(position);

        showCount();
    }

    /**
     * 顯示迴圈模式
     */
    private void showLoopModel() {
        PlayListUtil.showLoopModel(getMusicListManager().getLoopModel(), binding.loopModel);
    }

    private void showCount() {
        binding.count.setText(String.format("(%d)", getMusicListManager().getDatum().size()));
    }
}

感謝你的閱讀,更多文章請關註我們,點擊,評論,轉發支持。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HE琥珀虛顏破解自由安裝程式教程(001) 前言 自從狗尾草跑路後,HE琥珀就沒法用了,當前APP還沒法破解,但是筆者找到了HE琥珀存在的一些漏洞,可以實現安裝自己的APP。 所需工具 | 所需工具 | | | | : | | 1. | OTG線 | | 2. | 鍵鼠 | | 3. | 電腦等智能 ...
  • 4K TokKit是一款跨平臺的桌面應用程式,用於大規模TikTok視頻下載。它使您能夠備份TikTok帳戶,保存來自其他TikTok配置文件和哈希標記的視頻。此應用程式非常適合那些想要創建最喜愛的短片段的數字畫廊、一次抓取多個TikTok視頻以及自動從各種TikTok創建者和主題下載新內容的人。 ...
  • Httpd 1.httpd簡介 httpd是Apache超文本傳輸協議(HTTP)伺服器的主程式。被設計為一個獨立運行的後臺進程,它會建立一個處理請求的子進程或線程的池。 通常,httpd不應該被直接調用,而應該在類Unix系統中由apachectl調用,在Windows中作為服務運行。 2.htt ...
  • MySQL實戰45講 12 為什麼我的MySQL會“抖”一下? 你的 SQL 語句為什麼變“慢”了 什麼情況會引發資料庫的 flush 過程 InnoDB 刷臟頁的控制策略 ...
  • 聚合函數 聚合函數是對一組數據進行彙總輸出的函數。 輸入:一組數據集合 輸出:單個值 舉例:返回一組數據的最大值、平均數、最小、方差等操作。 常見函數舉例: 1,AVG函數:返回一組數據的平均值 2,SUM函數:返回一組數據的總和 3,MAX、MIN函數:返回一組數據的最大、最小值 4,COUNT函 ...
  • 分享嘉賓:劉冰冰 亞馬遜雲科技 編輯整理:張了了 聚水潭 出品平臺:DataFunTalk **導讀:**資料庫經過了幾十年的發展,目前已經是一項非常成熟的技術,然而隨著當今互聯網的極速增長,我們進入到雲時代,企業亟需構建現代化的應用,因此資料庫有了更大的挑戰。今天結合當前時代的發展和趨勢,分享未來 ...
  • 1.初識資料庫 資料庫(DB,database) 概念:數據倉庫,安裝在操作系統上的一款軟體 作用:存儲管理數據 分類: 關係型資料庫(SQL): MySQL,Oracle,Sql Server,DB2,SQLlite 通過表和表之間,行和列之間的關係進行數據的存儲 非關係型資料庫(NoSQL no ...
  • Android 入門 Gradle 安裝配置 Linux下安裝gradle 構建文件和創建任務 預設構建文件為 build.gradle, 構建是可使用 -b 替代 --build gradle -b <fileName> .gradle 文件夾存放的是 Gradle 的構建信息 Gradle 採用 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...