日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android12 Jetpack SplashScreen API总结

發布時間:2024/4/15 Android 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android12 Jetpack SplashScreen API总结 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.


官方Android 12的Splash Screen文檔地址
官方Splash Screen兼容庫,支持所有版本系統

本篇文章主要圍繞下面三個問題來介紹:

  • 我們能從Android 12 SplashScreen API里面學到什么?
  • 新出的SplashScreen兼容庫又是什么?能做成什么樣子?
  • 小甲同學:我想看Android12 SplashScreen源碼,可以嗎?
  • SplashScreen使用

    首先我們需要把 compileSdktargetSdk(可選) 升級到31 。

    Android12版本

    (A).主題和外觀配置

    <!--文章末尾我們會把包含所有示例的鏈接地址提供出來,如有需要:請翻到文章末尾--><!-- values-v31/themes.xml --> <!--單一顏色填充「啟動畫面」窗口背景--> <item name="android:windowSplashScreenBackground">@color/...</item><!--「啟動畫面」中心的圖標,可以配置AnimationDrawable 和 AnimatedVectorDrawable類型的drawable--> <item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item><!--「啟動畫面」中心圖標動畫的持續時間,這個屬性不會對屏幕顯示的實際時間產生任何影響--> <item name="android:windowSplashScreenAnimationDuration">1000</item><!--「啟動畫面」中心圖標后面設置背景--> <item name="android:windowSplashScreenIconBackgroundColor">@color/...</item><!--「啟動畫面」底部顯示的品牌圖標--> <item name="android:windowSplashScreenBrandingImage">@drawable/...</item>

    (B).延長啟動畫面

    val content: View = findViewById(android.R.id.content)content.viewTreeObserver.addOnPreDrawListener(object : ViewTreeObserver.OnPreDrawListener {override fun onPreDraw(): Boolean {// 模擬一些數據的初始化,再取消掛起return if (viewModel.isReady) {// 取消掛起,恢復頁面內容繪制content.viewTreeObserver.removeOnPreDrawListener(this)true} else {// 掛起,內容還沒有準備好false}}})

    (C ).關閉啟畫面的動畫

    // 自己定制關閉的動畫 splashScreen.setOnExitAnimationListener { splashScreenView ->val slideUp = ObjectAnimator.ofFloat(// 你們自己控制,自己隨便寫什么動畫,這里我們測試讓圖標移動splashScreenView.iconView,View.TRANSLATION_Y,0f,-splashScreenView.height.toFloat())slideUp.interpolator = AnticipateInterpolator()slideUp.duration = 200LslideUp.doOnEnd { splashScreenView.remove() }slideUp.start()}

    (D).遇到的問題

    • android:windowSplashScreenBrandingImage 定義的圖片尺寸要求是多少?總覺得有點拉伸;
    • 使用AnimationDrawable 或者 AnimatedVectorDrawable,來設置中心圖標,會出現“中心圖標”消失的情況,靜態圖標不會有這種問題出現;
    • Android12父主題設置android:windowBackground被覆蓋,看不到效果

    問題1: 在源碼里面也沒有看到具體的值或者比例大小,怎么辦呢?

    小技巧: 使用一個超大的正方形的圖標設置進去測試了一下,拉伸不要緊,我們要的是比例, 然后測量了一下比例為:2.5 : 1,所以設計品牌名圖標的時候,可以設置為400 * 160這樣的比例為2.5:1的圖標

    問題2: 針對中心圖標會閃現消失的問題做測試,
    測試一:靜態Icon,測試二:動態Icon

    靜態中心圖標 - 正常 ……飄過……

    下面我們來測試 動態中心圖標,為了方便測試出效果,我們覆蓋住圖標后面的背景色,方便對比,最后發現:測試結果不太理想,效果不行

    <!--AnimationDrawable寫法--> <!--沒有真機測試,這個寫法,效果看起來也挺奇怪的,可能是模擬器且是預覽版的問題吧--> <animation-list xmlns:android="http://schemas.android.com/apk/res/android"android:oneshot="true"><item android:drawable="@mipmap/ic_launcher" android:duration="600" /><item android:drawable="@drawable/api12_logo" android:duration="200" /><item android:drawable="@mipmap/ic_launcher" android:duration="200" /> </animation-list>

    動態中心圖標,不正常

    我們再來看一下官方文檔中的順滑效果

    下面我們使用AnimatedVectorDrawable來制作動態圖標,
    為了觀察出效果:我們打開模擬器的開發者選項,找到Animator時長縮放設置為:動畫時長x10,自己看效果,此處略……

    笑臉眼睛動畫的矢量圖文件 👇👇,點擊查看在線制作矢量圖動畫

    <!--僅測試玩耍,感興趣的可以自己去制作一個--> <?xml version="1.0" encoding="utf-8"?> <animated-vectorxmlns:android="http://schemas.android.com/apk/res/android"xmlns:aapt="http://schemas.android.com/aapt"><aapt:attr name="android:drawable"><vectorandroid:name="vector"android:width="24dp"android:height="24dp"android:viewportWidth="24"android:viewportHeight="24"><group android:name="group"><pathandroid:name="path_4"android:pathData="M 11.99 2 C 6.47 2 2 6.48 2 12 C 2 17.52 6.47 22 11.99 22 C 17.52 22 22 17.52 22 12 C 22 6.48 17.52 2 11.99 2 Z M 12 20 C 7.58 20 4 16.42 4 12 C 4 7.58 7.58 4 12 4 C 16.42 4 20 7.58 20 12 C 20 16.42 16.42 20 12 20 Z M 12 17.5 C 14.33 17.5 16.32 16.05 17.12 14 L 15.45 14 C 14.76 15.19 13.48 16 12 16 C 10.52 16 9.25 15.19 8.55 14 L 6.88 14 C 7.68 16.05 9.67 17.5 12 17.5 Z"android:fillColor="#FFFFFF"/></group><group android:name="group_1"><pathandroid:name="path_1"android:pathData="M 8.5 9.5 M 7 9.5 C 7 9.102 7.158 8.721 7.439 8.439 C 7.721 8.158 8.102 8 8.5 8 C 8.898 8 9.279 8.158 9.561 8.439 C 9.842 8.721 10 9.102 10 9.5 C 10 9.898 9.842 10.279 9.561 10.561 C 9.279 10.842 8.898 11 8.5 11 C 8.102 11 7.721 10.842 7.439 10.561 C 7.158 10.279 7 9.898 7 9.5"android:fillColor="#FFFFFF"/><pathandroid:name="path_3"android:pathData="M 8.5 9.5 M 7 9.5 C 7 9.102 7.158 8.721 7.439 8.439 C 7.721 8.158 8.102 8 8.5 8 C 8.898 8 9.279 8.158 9.561 8.439 C 9.842 8.721 10 9.102 10 9.5 C 10 9.898 9.842 10.279 9.561 10.561 C 9.279 10.842 8.898 11 8.5 11 C 8.102 11 7.721 10.842 7.439 10.561 C 7.158 10.279 7 9.898 7 9.5"android:fillColor="#FFFFFF"/></group><group android:name="group_2"><pathandroid:name="path"android:pathData="M 15.5 9.5 M 14 9.5 C 14 9.102 14.158 8.721 14.439 8.439 C 14.721 8.158 15.102 8 15.5 8 C 15.898 8 16.279 8.158 16.561 8.439 C 16.842 8.721 17 9.102 17 9.5 C 17 9.898 16.842 10.279 16.561 10.561 C 16.279 10.842 15.898 11 15.5 11 C 15.102 11 14.721 10.842 14.439 10.561 C 14.158 10.279 14 9.898 14 9.5"android:fillColor="#FFFFFF"/><pathandroid:name="path_2"android:pathData="M 15.5 9.5 M 14 9.5 C 14 9.102 14.158 8.721 14.439 8.439 C 14.721 8.158 15.102 8 15.5 8 C 15.898 8 16.279 8.158 16.561 8.439 C 16.842 8.721 17 9.102 17 9.5 C 17 9.898 16.842 10.279 16.561 10.561 C 16.279 10.842 15.898 11 15.5 11 C 15.102 11 14.721 10.842 14.439 10.561 C 14.158 10.279 14 9.898 14 9.5"android:fillColor="#FFFFFF"/></group></vector></aapt:attr><target android:name="group_1"><aapt:attr name="android:animation"><objectAnimatorandroid:propertyName="translateX"android:duration="1000"android:valueFrom="0"android:valueTo="7"android:valueType="floatType"android:interpolator="@android:interpolator/fast_out_slow_in"/></aapt:attr></target><target android:name="group_2"><aapt:attr name="android:animation"><objectAnimatorandroid:propertyName="translateX"android:duration="1000"android:valueFrom="0"android:valueTo="-7"android:valueType="floatType"android:interpolator="@android:interpolator/fast_out_slow_in"/></aapt:attr></target> </animated-vector>

    后來我們又用了AnimationDrawable測試了一下慢放效果也不行,你仔細想一下:圖片輪播放效果能好嗎?
    所以:AnimationDrawable不推薦,我們這里推薦使用:AnimatedVectorDrawable為矢量圖添加動畫效果。

    問題3: Android12父主題設置android:windowBackground被覆蓋,看不到效果
    不要緊,只要我們的UI設計師(美工)按照如下尺寸規范來設計,使用靜態中心圖標,一樣可以實現同樣效果:

    • 中心圖標: 圖標內容區域內邊距2/3,防止元素被切
    • 品牌名圖標: 設計的尺寸比例為:2.5:1

    SplashScreen兼容庫

    點擊查看官方Splash Screen兼容庫文檔

    (A).依賴庫
    點擊查看Core庫里面的最新版本

    // 可在所有Android版本上使用的兼容庫 implementation 'androidx.core:core-splashscreen:1.0.0-alpha02'

    (B).主題和外觀配置

    • 定義Activity應該使用的主題
    <style name="Theme.App" parent="Theme.MaterialComponents.xxxxx.DarkActionBar"><item name="android:windowBackground">@color/...</item><item name="android:statusBarColor">@android:color/transparent</item><item name="android:windowLightStatusBar" tools:targetApi="m">......</item><item name="android:navigationBarColor">@android:color/transparent</item></style>
    • 創建父主題給啟動畫面使用
    <style name="Theme.App.Starting" parent="Theme.SplashScreen.IconBackground"><item name="android:windowBackground">@drawable/...</item><item name="windowSplashScreenBackground">@color/...</item><item name="windowSplashScreenAnimationDuration">200</item><item name="postSplashScreenTheme">@style/Theme.App</item> </style>
    • AndroidManifest.xml配置Activity的主題
    <manifest><application android:theme="@style/Theme.App.Starting"><!-- application和activity,兩個選一個配置: @style/Theme.App.Starting --><activity android:theme="@style/Theme.App.Starting"> ...

    (C ).初始化SplashScreen

    override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val splashScreen = installSplashScreen()setContent { ...... }splashScreen.setKeepVisibleCondition {!mainViewModel.mockDataLoading()}splashScreen.setOnExitAnimationListener(this)}

    (D).中心圖標大小修改

    <item name="splashScreenIconSize">@dimen/....</item>

    (E).遇到的問題
    兼容庫目前存在的問題

  • 沒有android:windowSplashScreenBrandingImage這個屬性
  • 配置了中心圖標,會裁剪成圓形
  • 低版本系統不配置windowSplashScreenAnimatedIcon會出現默認的Icon
  • Android12父主題設置android:windowBackground被覆蓋,看不到效果
  • 問題1: 是因為兼容庫的layout文件目錄下面的splash_screen_view.xml沒有“品牌名的視圖”,大家點擊查看一下,兩個布局的xml內容就知道了:
    frameworks下面的Android12的splash_screen_view.xml
    core-splashscreen下面的兼容庫的splash_screen_view.xml

    但是我們在Android12即values-v31的themes.xml里面依然可以配置android:windowSplashScreenBrandingImage這個屬性,因為Android12的SplashScreen是集成在frameworks里面的;

    問題2: 是因為兼容庫里面使用了MaskedDrawable包裝了Icon,會裁剪成圓形,圖標內容設計要保留2/3的內邊距,否則會出現內容被裁剪掉的問題;
    如何修復這個裁剪圓形問題呢?

    把源碼拷貝出來,總共就3個源代碼文件,自己復制出來修改刪除也可以的
    或者,圖標設計準則為:內容保留內邊距為2/3,防止元素被裁剪

    問題3: 寫一個透明的drawable.xml然后替換就行了,類似如下方式

    <?xml version="1.0" encoding="utf-8"?> <shape android:shape="rectangle" xmlns:android="http://schemas.android.com/apk/res/android"><solid android:color="@android:color/transparent"/><size android:width="0dp" android:height="0dp"/> </shape>

    問題4: Android12父主題設置android:windowBackground被覆蓋,看不到效果
    不要緊,只要我們的UI設計師(美工)按照如下尺寸規范來設計,使用靜態中心圖標,一樣可以實現同樣效果:

    • 中心圖標: 圖標內容區域內邊距2/3,防止元素被切
    • 品牌名圖標: 設計的尺寸比例為:2.5:1

    (F).制作一個啟動頁

    • 模仿快手App的啟動頁

    只需要配置父主題的android:windowBackground

    Android5.0 ~ Android11 效果

    由于我們在文章上面介紹到Android12上,無法為SplashScreen設置父主題的android:windowBackground,但我們依然可以通過配置靜態中心圖標來做到一樣的效果的,請看下面的效果:

    Android12 效果

    如果你的UI設計師,給你矢量圖,那么你就可以讓中心圖標在Android12系統上動起來了😆另外,可以建議UI設計師:統一所有系統上,啟動頁“中心”圖標,居中展示,不然會有點怪

    • 動態圖標啟動頁

    如果設計成動態啟動圖標,這個需要考慮2個因素:

    一、 低版本系統表現效果不一致,有些系統里面,動態圖標只在啟動頁關閉的時候才顯示(親測Android平板5.1.1系統就是這樣的);
    二、如何兼容低版本系統,是先展示底部品牌名,最后只能等動態圖標顯示咯?

    如果喜歡折騰的同學,可以多測試測試,我在使用Android10.0測試動態圖標的時候,效果看著還可以,具體系統下限在哪?
    這個看你們產品設計定位了,還有測試妹妹是否同意你們用,效果是否符合你們的產品;

    建議的做法是:

    • Android 5.0 ~ Android 11.0系統,都統一使用android:windowBackground配置啟動頁背景
    • Android12.0 如果UI設計師給你做了矢量圖,你可以做動態的中心圖標,不給你,使用靜態圖標也可以的,參考上面:模擬快手App啟動頁

    為了在模擬器上能正常顯示出效果,我們在模擬器的開發者選項,找到Animator時
    長縮放設置為:動畫時長x10,放慢10倍,缺真機測試😂😂😂😂😂

    Android12 動態啟動頁圖標


    源碼分析

    我們這里只分析Android12 SplashScreen,兼容庫沒有太多內容不足500行,感興趣的同學可以自己閱讀一下

    我們在XXXActivity里面第一次用到了splashScreen.setOnExitAnimationListener,從這里開始往源頭開始找,在下面的方法初始化了SplashScreen

    //android.app.Activity private SplashScreen getOrCreateSplashScreen() {synchronized (this) {if (mSplashScreen == null) {mSplashScreen = new SplashScreen.SplashScreenImpl(this);}return mSplashScreen;} }

    我們來看SplashScreenImpl實現類

    //android.app.Activityclass SplashScreenImpl implements SplashScreen {......//把SplashScreenImpl添加到這個單例類里面private final SplashScreenManagerGlobal mGlobal;public SplashScreenImpl(Context context) {mGlobal = SplashScreenManagerGlobal.getInstance();}@Overridepublic void setOnExitAnimationListener(@NonNull SplashScreen.OnExitAnimationListener listener) {......mGlobal.addImpl(this); // 用于后面執行啟動畫面將退出的回調}......public void setSplashScreenTheme(@StyleRes int themeId) {......try {//設置啟動畫面的主題AppGlobals.getPackageManager().setSplashScreenTheme(......);} catch (RemoteException e) {Log.w(TAG, "Couldn't persist the starting theme", e);}} }// 啟動畫面管理器 class SplashScreenManagerGlobal {......// 管理多個閃屏實現private final ArrayList<SplashScreenImpl> mImpls = new ArrayList<>();private SplashScreenManagerGlobal() {// 向此進程注冊啟動畫面管理器ActivityThread.currentActivityThread().registerSplashScreenManager(this);}......private static final Singleton<SplashScreenManagerGlobal> sInstance =new Singleton<SplashScreenManagerGlobal>() {@Overrideprotected SplashScreenManagerGlobal create() {return new SplashScreenManagerGlobal();}};private void addImpl(SplashScreenImpl impl) {synchronized (mGlobalLock) {mImpls.add(impl);}}private void removeImpl(SplashScreenImpl impl) {synchronized (mGlobalLock) {mImpls.remove(impl);}}......public void handOverSplashScreenView(IBinder token,SplashScreenView splashScreenView) {//調用的是 => splashScreenView.transferSurface();transferSurface(splashScreenView);//回調 => impl.mExitAnimationListener.onSplashScreenExit(view);dispatchOnExitAnimation(token, splashScreenView);}...... }

    我們看到初始化SplashScreenManagerGlobal的時候,向此進程注冊啟動畫面管理器

    //android.app.ActivityThreadpublic void registerSplashScreenManager(SplashScreen.SplashScreenManagerGlobal manager) {synchronized (this) {mSplashScreenGlobal = manager;} }

    如何把SplashScreen添加到當前的窗口的呢?
    ActivityThread繼承ClientTransactionHandler,里面有一個這樣的抽象方法:

    //android.app.ClientTransactionHandler public abstract void handleAttachSplashScreenView(@NonNull ActivityClientRecord r,@NonNull SplashScreenViewParcelable parcelable);

    ActivityThread肯定會實現這個方法,那么是誰調用了它呢?由于篇幅問題,就不一行一行代碼的去介紹分析了,感興趣的同學,可以自己深入研究,我們下面貼出來調用的流程圖

    誰調用了handleAttachSplashScreenView(),它的調用鏈流程圖如下:

    好了,看完流程圖,我們再看一下ActivityThread#handleAttachSplashScreenView

    //android.app.ActivityThread@Override public void handleAttachSplashScreenView(@NonNull ActivityClientRecord r, @Nullable SplashScreenView.SplashScreenViewParcelable parcelable) {final DecorView decorView = (DecorView) r.window.peekDecorView();if (parcelable != null && decorView != null) {createSplashScreen(r, decorView, parcelable);}...... }private void createSplashScreen(ActivityClientRecord r, DecorView decorView,SplashScreenView.SplashScreenViewParcelable parcelable) {// 初始化SplashScreenView構建器final SplashScreenView.Builder builder = new SplashScreenView.Builder(r.activity);// 從parcelable中獲取配置數據,并通過build()初始化SplashScreenView,設置數據final SplashScreenView view = builder.createFromParcel(parcelable).build();// 把SplashScreenView添加到DecorView中decorView.addView(view);// 設置SystemUI顏色view.attachHostActivityAndSetSystemUIColors(r.activity, r.window);// 刷新視圖view.requestLayout();...... }

    核心的部分源碼已經分析差不多了,剩下的一些源碼,感興趣的同學可以自己查看閱讀


    總結

    • compileSdk升級到31
    • 產品中統一使用兼容庫SplashScreen
    implementation 'androidx.core:core-splashscreen:最新版本'
    • 演示示例中資源目錄
    drawable —— 定義低版本的drawable資源 drawable-v23 —— 定義6.0以上的資源 drawable-v31 —— 定義Android12及以上的資源 values —— 定義默認資源 values-night —— 定義默認深色模式資源 values-v23 —— 定義6.0以上系統資源 values-v31 —— 定義Android12及以上的資源 values-night-v31 —— 定義Android12及以上的深色模式資源
    • 啟動頁圖標設計準則

    中心圖標大圖,內容需要保留2/3的內邊距,否則圖標會被裁剪掉,另外:圖標尺寸大小可以修改;
    底部品牌名圖標:尺寸比例需要為 2.5:1
    兼容庫SplashScreen低版本不支持設置底部品牌圖標,
    Android12需要在values-v31目錄手動添加如下屬性,才可以顯示品牌名圖標;

    <!--兼容庫沒有這個屬性,我們需要在values-v31單獨配置一下--> <item name="android:windowSplashScreenBrandingImage">@drawable/...</item>
    • Android12以下系統可以使用android:windowBackground為父主題設置窗口背景,切記不要在Android12及以上系統設置父主題的窗口背景(因為沒有效果😅😅)
    • Android12系統以下系統,使用android:windowBackground的話,一定要給windowSplashScreenAnimatedIcon設置一個透明的drawable,否則會出現機器人圖標
    • windowSplashScreenBackground 這個屬性的顏色一定要注意,配置有問題的話,啟動頁過渡到主頁面的時候,會有這個顏色閃出來,建議和Activity的android:windowBackground配置成一樣的顏色
    • 在啟動畫面上面,添加一個“廣告或者推廣頁面”,代碼和效果如下:
    override fun onSplashScreenExit(splashScreenViewProvider: SplashScreenViewProvider) {if(splashScreenViewProvider.view is ViewGroup){// 在這里添加一個啟動頁廣告或者推廣頁面val composeView = ComposeView(this@SplashScreenCompatActivity).apply {setContent {SplashAdScreen(onCloseAd = {splashScreenViewProvider.remove()})}}(splashScreenViewProvider.view as ViewGroup).addView(composeView)return} }


    實踐 - 啟動頁添加廣告或者推廣頁


    參考地址

    • 在線流程圖制作
    • 官方文檔 Splash screens
    • Google官網介紹矢量圖
    • 在線svg編輯器
    • 在線制作矢量圖動畫
    • 在線合并多個GIF制作

    所有示例源碼GitHub:

    https://github.com/Pangu-Immortal

    https://github.com/Pangu-Immortal/SplashScreens


    總結

    以上是生活随笔為你收集整理的Android12 Jetpack SplashScreen API总结的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。