2.Android高仿網易雲音樂-引導界面和廣告界面實現

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

高仿Android網易雲音樂廣告界面就是顯示圖片和視頻,所以可以放一個圖片控制項,視頻控制項,然後跳過按鈕,提示按鈕,WiFi預載入提示都是放到最上層容器。 ...


效果圖


效果圖依次為圖片廣告,視頻廣告,引導界面。

系列文章目錄導航

目錄

1.實現分析

廣告界面就是顯示圖片和視頻,所以可以放一個圖片控制項,視頻控制項,然後跳過按鈕,提示按鈕,WiFi預載入提示都是放到最上層容器。

2.廣告界面佈局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".component.ad.activity.AdActivity">
    <!--圖片廣告-->
    <ImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop" />

    <!--視頻播放器
    VideoView預設沒法設置視頻填充整個控制項,所以不用他-->
    <com.tencent.rtmp.ui.TXCloudVideoView
        android:id="@+id/video"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone" />
    <!--/播放器-->

    <!--廣告控制層-->
    <RelativeLayout
        android:id="@+id/ad_control"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/preload"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="@dimen/padding_meddle"
            android:layout_marginTop="@dimen/d50"
            android:layout_marginBottom="@dimen/d50"
            android:background="@drawable/shape_button_transparent_radius_small"
            android:gravity="center"
            android:padding="@dimen/d5"
            android:text="@string/wifi_preload"
            android:textColor="?attr/colorLightWhite"
            android:textSize="@dimen/text_small"
            android:visibility="gone" />

        <!--跳過廣告按鈕-->
        <TextView
            android:id="@+id/skip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginTop="@dimen/d50"
            android:layout_marginRight="@dimen/padding_large"
            android:layout_marginBottom="@dimen/d50"
            android:background="@drawable/shape_button_transparent_radius_small"
            android:gravity="center"
            android:padding="@dimen/padding_meddle"
            android:textColor="?attr/colorLightWhite"
            android:textSize="@dimen/text_meddle"
            app:cornerRadius="@dimen/d30"
            tools:text="@string/skip_ad_count" />
            <!--打開廣告按鈕-->
            <TextView
                android:id="@+id/primary"
                android:layout_width="match_parent"
                android:layout_height="@dimen/d60"
                android:background="@drawable/shape_button_transparent_radius_large"
                android:gravity="center"
                android:text="@string/ad_click_tip"
                android:textColor="?attr/colorLightWhite"
                android:textSize="@dimen/text_large"
                app:cornerRadius="@dimen/d30" />
        </com.facebook.shimmer.ShimmerFrameLayout>
    </RelativeLayout>
</RelativeLayout>

3.顯示廣告

廣告數據是在首頁提前緩存到本地了,目的是本地顯示更快,因為廣告界面本來就幾秒鐘,還要去網路請求數據,就很浪費時間。

@Override
protected void initDatum() {
    super.initDatum();

    //獲取廣告信息
    data = sp.getSplashAd();
    if (data == null) {
        next();
        return;
    }

    //顯示廣告信息
    show();
}

private void show() {
    File targetFile = FileUtil.adFile(getHostActivity(), data.getIcon());
    if (!targetFile.exists()) {
        //記錄日誌,因為正常來說,只要保存了,文件不能丟失
        next();
        return;
    }

    SuperViewUtil.show(binding.adControl);

    switch (data.getStyle()) {
        case Constant.VALUE0:
            showImageAd(targetFile);
            break;
        case Constant.VALUE10:
            showVideoAd(targetFile);
            break;
    }
}

/**
 * 顯示視頻廣告
 *
 * @param data
 */
private void showVideoAd(File data) {
    SuperViewUtil.show(binding.video);
    SuperViewUtil.show(binding.preload);

    //在要用到的時候在初始化,更節省資源,當然播放器控制項也可以在這裡動態創建
    //設置播放監聽器

    //創建 player 對象
    player = new TXVodPlayer(getHostActivity());

    //靜音,當然也可以在界面上添加靜音切換按鈕
    player.setMute(true);

    //關鍵 player 對象與界面 view
    player.setPlayerView(binding.video);

    //設置播放監聽器
    player.setVodListener(this);

    //鋪滿
    binding.video.setRenderMode(TXLiveConstants.RENDER_MODE_FULL_FILL_SCREEN);

    //開啟硬體加速
    player.enableHardwareDecode(true);

    player.startPlay(data.getAbsolutePath());
}

/**
 * 顯示圖片廣告
 *
 * @param data
 */
private void showImageAd(File data) {
    ImageUtil.showLocalImage(getHostActivity(), binding.image, data.getAbsolutePath());

    startCountDown(5000);
}

跳過廣告

跳過廣告就是取消倒計時,直接進入下一個界面。

//跳過廣告按鈕
binding.skip.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //取消倒計時
        cancelCountDown();

        next();
    }
});

點擊廣告

點擊廣告就是取消倒計時,進入主界面,然後再顯示廣告界面。


引導界面佈局

//點擊廣告按鈕
binding.primary.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        //取消倒計時
        cancelCountDown();

        action = Constant.ACTION_AD;

        next();
    }
});

引導界面邏輯

頂部左右滾動ViewPager容器,也可以使用ViewPager2,中間就是指示器,底部就是按鈕。

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

    <!--左右滾動控制項-->
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />

    ...

    <!--按鈕容器-->
    <LinearLayout
        android:layout_marginBottom="@dimen/d30"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <!--占位控制項-->
        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="1" />

        <!--登錄註冊按鈕-->
        <com.google.android.material.button.MaterialButton
            android:id="@+id/login_or_register"
            style="@style/SuperButton.Primary"
            android:layout_width="wrap_content"
            android:minWidth="@dimen/d130"
            android:text="@string/login_or_register" />

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

        <!--立即體驗按鈕-->
        <com.google.android.material.button.MaterialButton
            android:id="@+id/experience_now"
            style="@style/Widget.MaterialComponents.Button.UnelevatedButton"
            android:layout_width="wrap_content"
            android:layout_height="@dimen/d55"
            android:layout_centerVertical="true"
            android:layout_marginHorizontal="@dimen/d5"
            android:layout_toRightOf="@+id/select_image"
            android:backgroundTint="?attr/colorLightWhite"
            android:minWidth="@dimen/button_width_large"
            android:text="@string/experience_now"
            android:textColor="@color/black80"
            android:textSize="@dimen/text_small"
            ixuea:strokeColor="?attr/colorPrimary"
            ixuea:strokeWidth="@dimen/d1" />

        <include layout="@layout/fill" />
    </LinearLayout>
</LinearLayout>

下載廣告

不論是圖片,還是視頻都按照文件方式下,當然下載前還要判斷是WiFi,以及沒有下載才下載。

private void downloadAd(Ad data) {
    if (SuperNetworkUtil.isWifiConnected(getHostActivity())) {
        sp.setSplashAd(data);

        //判斷文件是否存在,如果存在就不下載
        File targetFile = FileUtil.adFile(getHostActivity(), data.getIcon());
        if (targetFile.exists()) {
            return;
        }

        new Thread(
                new Runnable() {
                    @Override
                    public void run() {

                        try {
                            //FutureTarget會阻塞
                            //所以需要在子線程調用
                            FutureTarget<File> target = Glide.with(getHostActivity().getApplicationContext())
                                    .asFile()
                                    .load(ResourceUtil.resourceUri(data.getIcon()))
                                    .submit();

                            //獲取下載的文件
                            File file = target.get();

                            //將文件拷貝到我們需要的位置
                            FileUtils.moveFile(file, targetFile);

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
        ).start();
    }
}

總結

不論是那個界面,都沒有很難,但就像我們說的,寫代碼就像藝術,要寫好細節還挺麻煩,例如:下載廣告是否應該登錄網路空閑時才下載,避免影響正常網路請求,同時下載下來後,要添加一定的機制,防止很容易的跳過廣告等;如果要產生收益,大公司就是有自己的廣告平臺,中小型項目可以使用聚合SDK更方便。


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

-Advertisement-
Play Games
更多相關文章
  • 新一期鏡像站體驗官任務發佈,希望熱愛科技、熱愛開源一起共建更加美好的鏡像站,投稿一經採納即可獲得優酷VIP卡一張(最多一張),被採納配置信息超過3個便可得天貓精靈音箱一個。 因為熱愛,所以行動 作為程式員肯定要和開源軟體打交道,很多情況需要用到相關的代碼庫,而依賴和軟體包的下載是最耗時最浪費精力的事 ...
  • OmniPlayer Pro全能播放器Mac版是Mac平臺上的一款幾乎適用於所有格式的多媒體播放器。Omni全能播放器Mac版是一款支持macOS上幾乎所有音頻和視頻格式的多媒體播放器。 詳情:OmniPlayer Pro for Mac(全能多媒體播放器) 特點介紹 主要功能: * 支持多種音視頻 ...
  • (文章目錄) 前言 相信大多數人都有自己搭建博客網站的想法,本文就手把手一步一步的進行,最終結果類似如下樣式: 一、網站軟體的選擇 軟體選擇成熟而免費的WordPress,WordPress是一款能讓您建立出色網站、博客或應用程式的開源軟體。 可充分利用超過55,000個插件擴展WordPress, ...
  • MySQL 的許可權管理(非重點) mysql用戶分類角度: 1.管理用戶: root,具有最高許可權,具有創建用戶的許可權,可以為其他用戶授權 2.普通用戶: 普通由root用戶創建,許可權由root分配 mysql用戶分類角度(訪問主機不同) 本地用戶-- 只能在安裝mysql的機器上訪問mysql數據 ...
  • 01 | 基礎架構:一條SQL查詢語句是如何執行的? Server 層 所有跨存儲引擎的功能都在這一層實現,比如存儲過程、觸發器、視圖等。 存儲引擎層負責數據的存儲和提取。其架構模式是插件式的,在 create table 語句中使用 engine=memory, 來指定使用記憶體引擎創建表 連接器 ...
  • 數據持久化 數據持久化就是將記憶體中的數據模型轉換為存儲模型,以及將存儲模型轉換為記憶體中的數據模型的統稱。數據模型可以是任何數據結構或對象模型,存儲模型可以是關係模型、XML、二進位流等。 瞬時狀態 保存在記憶體的程式數據,程式退出,數據就消失了 持久狀態 保存在磁碟上的程式數據,程式退出後依然存在 數 ...
  • 7月14日晚間,周傑倫最新專輯《最偉大的作品》在QQ音樂正式上線,立即成為全網最大的熱點事件。作為一張“六年等一回”的新專輯,《最偉大的作品》於7月8日開啟預售,截止到7月18日,已在QQ音樂售出超500萬張。 當全國人民沉浸在音樂的狂歡中,對於QQ音樂團隊來卻有著更多的涵義:海**量的數據意味著更 ...
  • 華為開發者聯盟、艾瑞咨詢和AppGrowing聯合發佈《2022年移動應用運營增長洞察白皮書》,本白皮書意在展現國內移動應用運營增長的現狀、廣告投放趨勢,分析和探討移動應用的運營思路變化和相關的運營服務革新,為開發者提供最新市場洞察,並針對用戶增長的各個階段的挑戰呈現解決方法,助力移動應用獲得用戶和 ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...