GVKun编程网logo

在cordova-plugin-splashscreen中更改Splash Screen Spinner的颜色(scope怎么改颜色)

4

本篇文章给大家谈谈在cordova-plugin-splashscreen中更改SplashScreenSpinner的颜色,以及scope怎么改颜色的知识点,同时本文还将给你拓展Android12新

本篇文章给大家谈谈在cordova-plugin-splashscreen中更改Splash Screen Spinner的颜色,以及scope怎么改颜色的知识点,同时本文还将给你拓展Android 12 新 APP 启动画面 (SplashScreen API) 简介 && 源码分析、Android splash screen 启动画面 初级、Android SplashScreen、Android VideoView SplashScreen等相关知识,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

在cordova-plugin-splashscreen中更改Splash Screen Spinner的颜色(scope怎么改颜色)

在cordova-plugin-splashscreen中更改Splash Screen Spinner的颜色(scope怎么改颜色)

我即将用Ionic / Cordova完成我的第一个App.

是的,它很棒,但有时我想知道为什么事情如此复杂(所有这些插件和东西:))

我想知道我是否可以改变Splash-Screen-Spinner的颜色.

有任何想法吗?我搜索死源代码:颜色,微调……,但我没有找到提示.

我想这会对很多人有所帮助.

问候

解决方法

至少在Cordova 7.0和Cordova iOS 4.4.0中,没有必要更改启动画面插件的源代码.您只需将以下行添加到config.xml文件中,微调器将显示为白色而不是灰色.

<preference name="TopActivityIndicator" value="whiteLarge" />

注意:对于微调器,Apache Cordova文档有点令人困惑.关于TopActivityIndi​​cator的config.xml指南说明如下:

Controls the appearance of the small spinning icon in the status bar that indicates significant processor activity.

我相信该声明指的是以下微调器:

enter image description here

但是,至少在iOS和Cordova 7.0上,更改TopActivityIndi​​cator会影响应用程序打开时屏幕中间显示的微调器的外观.以下是whiteLarge设置的示例:

enter image description here

希望有所帮助.

Android 12 新 APP 启动画面 (SplashScreen API) 简介 && 源码分析

Android 12 新 APP 启动画面 (SplashScreen API) 简介 && 源码分析

OSC 请你来轰趴啦!1028 苏州源创会,一起寻宝 AI 时代

转:

Android 12 新 APP 启动画面 (SplashScreen API) 简介 && 源码分析

以往的启动画面

  • 默认情况下刚启动 APP 时会显示一会白色背景
  • 如果把这个启动背景设置为 null,则一闪而过的白色会变成黑色
  • 如果把启动 Activity 设置为背景透明【<item name=“android:windowIsTranslucent”>true 】或者禁用了启动画面【<item name=“android:windowDisablePreview”>true 】;虽然一闪而过的黑色或者白色没有了,但是因为背景透明了就会看到桌面,导致的结果就是感觉 APP 启动慢了
  • 通常我们会在主题里给它设置一张公司 Logo 图片【<item name=“android:windowSplashscreenContent”>@drawable/splash 】,这样就感觉 APP 启动快了

全新的 APP 启动画面

  • 统一的设计标准,不同 APP 展现出来的整体样式是一样的
  • 支持通过配置主题的方式更换中间的 Logo / 动画、背景色、图片的背景色、底部公司品牌 Logo 等
  • 支持延长显示的时间
  • 支持自定义关闭启动画面的动画

注意事项

  • 【<item name=“android:windowSplashscreenContent”>@drawable/splash< /item>】和【< item name=“android:windowDisablePreview”>true 】在 Android 12 设备上都失效 (已废弃),即使 targetSdkVersion 没有升级到 31 也是这样
  • Android 12 新启动画面,targetSdkVersion 不需要升级到 31,但是 compileSdkVersion 一定要升级到 31 才可以,否则编译时无法找到主题里这些新增的属性
  • 启动画面的图标 / 动画应该遵循 Adaptive Icon (自适应图标) 的规范,不然图片 / 动画可能会显示异常

使用方法

APP 在 Android12 上默认启动效果

Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

在主题中通过配置自定义启动画面

设置启动画面背景色

<!--设置启动画面背景色-->
<item name="android:windowSplashScreenBackground">#ff9900</item>

效果图:
Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

设置启动画面居中显示的图标或者动画

<!--设置启动画面居中显示的图标或者动画-->
<item name="android:windowSplashScreenAnimatedIcon">@drawable/ic_launcher_foreground</item>
<!--设置启动画面在关闭之前显示的时长,最长1000毫秒-->
<item name="android:windowSplashScreenAnimationDuration">1000</item>
  • windowSplashScreenAnimationDuration 指的是启动画面显示的时间,跟动画的时长无关,也就是如果动画时间超过这个时间,它不会等待动画结束,而是直接关闭;如果希望动画显示时间超过 1 秒,则需要参考后面【延迟关闭启动画面】部分

效果图:
Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

设置中间显示图标区域的背景色

用于解决图标和背景颜色接近显示不清问题

<!--设置中间显示图标区域的背景色,用于解决图标和背景颜色接近显示不清问题-->
<item name="android:windowSplashScreenIconBackgroundColor">#ff0000</item>

效果图:
Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

设置启动画面底部公司品牌图片

官方不推荐使用,可能是因为底部再加个图片不好看吧

<!--设置启动画面底部公司品牌图片,官方不推荐使用-->
<item name="android:windowSplashScreenBrandingImage">@drawable/ic_launcher_foreground</item>

效果图:
Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

延迟关闭启动画面

有时候希望启动画面能在数据准备好之后才关闭,或者动画时间超过 1 秒

class MainActivity() : AppCompatActivity() {
     
     
	var isDataReady = false
	override fun onCreate(savedInstanceState: Bundle?) {
     
     
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val contentView = findViewById<View>(android.R.id.content)
        contentView.viewTreeObserver.addOnPreDrawListener(object :
            ViewTreeObserver.OnPreDrawListener {
     
     
            override fun onPreDraw(): Boolean {
     
     
                if (isDataReady) {
     
     //判断是否可以关闭启动动画,可以则返回true
                    contentView.viewTreeObserver.removeOnPreDrawListener(this)
                }
                return isDataReady
            }
        })
        Thread.sleep(5000)//模拟耗时
        isDataReady = true
    }
}

效果图:
Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

定制退出动画

启动画面默认结束后是直接消失的,可能会显得有些突兀,全新的 SplashScreen 支持定制退出动画

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
     
     
    splashScreen.setOnExitAnimationListener {
     
      splashScreenView ->
        val slideUp = ObjectAnimator.ofFloat(
            splashScreenView,
            View.TRANSLATION_Y,
            0f,
            -splashScreenView.height.toFloat()
        )
        slideUp.interpolator = AnticipateInterpolator()
        slideUp.duration = 2000L
        slideUp.doOnEnd {
     
      splashScreenView.remove() }
        slideUp.start()
    }
}

效果图:
Android 12 新APP启动画面(SplashScreen API)简介&&源码分析

  • splashScreen 是 Activity 中的 getSplashScreen () 方法返回的

  • 官方说 SplashScreenView 在动画结束后要 remove 掉,实际测试发现不 remove 也是可以的,因为动画结束后启动画面已经被移动到看不到的地方了,不影响后续操作;但是通过查看 SplashScreenView 的 remove 方法源码,除了将 SplashScreenView 设为不可见外,还有图片等资源的回收操作,所以建议还是要调用它的 remove 方法以回收资源

    class SplashScreenView extends FrameLayout {
           
           
    	public void remove() {
           
           
    		if (mHasRemoved) {
           
           
    			return;
    		}
    		setVisibility(GONE);
    		if (mParceledIconBitmap != null) {
           
           
    			if (mIconView instanceof ImageView) {
           
           
    				((ImageView) mIconView).setImageDrawable(null);
    			} else if (mIconView != null) {
           
           
    				mIconView.setBackground(null);
    			}
    			mParceledIconBitmap.recycle();
    			mParceledIconBitmap = null;
    		}
    		if (mParceledBrandingBitmap != null) {
           
           
    			mBrandingImageView.setBackground(null);
    			mParceledBrandingBitmap.recycle();
    			mParceledBrandingBitmap = null;
    		}
    		if (mParceledIconBackgroundBitmap != null) {
           
           
    			if (mIconView != null) {
           
           
    				mIconView.setBackground(null);
    			}
    			mParceledIconBackgroundBitmap.recycle();
    			mParceledIconBackgroundBitmap = null;
    		}
    		if (mWindow != null) {
           
           
    			final DecorView decorView = (DecorView) mWindow.peekDecorView();
    			if (DEBUG) {
           
           
    				Log.d(TAG, "remove starting view");
    			}
    			if (decorView != null) {
           
           
    				decorView.removeView(this);
    			}
    			restoreSystemUIColors();
    			mWindow = null;
    		}
    		if (mHostActivity != null) {
           
           
    			mHostActivity.setSplashScreenView(null);
    			mHostActivity = null;
    		}
    		mHasRemoved = true;
    	}
    }
    

计算启动画面中间的动画剩余时长

上面我们说到可以自定义退出动画,也就是设置 splashScreen.setOnExitAnimationListener,这个接口会在将要显示 APP 主界面时回调;

  • 如果设备性能比较差,可能会出现中间那个图标动画已经结束,但是 APP 主界面却还没显示的情况,这个时候如果启动画面退出时还做一次动画,会导致 APP 进入主界面的时间更长,遇到这种情况应该取消退出动画,让用户及时看到主界面会更好一些;

  • 如果设备性能比较好,假如本来设置的启动画面中间图标动画时长 1000 毫秒,但是只执行了 500 毫秒的动画就可以开始显示 APP 主界面动画了,却因为固定的退出动画时长,导致需要等待更久的时间才能看到主界面

所以应该根据启动画面中间图标动画时长执行剩余时间来决定退出动画的时长,这样才能尽快让用户看到 APP 主界面,并保证好的体验效果

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
     
     
    splashScreen.setOnExitAnimationListener {
     
      splashScreenView ->
        val slideUp = ObjectAnimator.ofFloat(
            splashScreenView,
            View.TRANSLATION_Y,
            0f,
            -splashScreenView.height.toFloat()
        )
        slideUp.interpolator = AnticipateInterpolator()

		//计算合适的退出动画时长
        var targetDuration = 0L
        val animationDuration = splashScreenView.iconAnimationDuration//图标动画时长
        val animationStart = splashScreenView.iconAnimationStart//图标动画开始时间
        if (animationDuration != null && animationStart != null) {
     
     
            val remainingDuration = (
                    animationDuration.toMillis() - (System.currentTimeMillis() - animationStart.toEpochMilli())
                    ).coerceAtLeast(0L)//计算剩余时间,如果小于0则赋值0
            targetDuration = remainingDuration
        }
        slideUp.duration = targetDuration
        slideUp.doOnEnd {
     
      splashScreenView.remove() }
        slideUp.start()
    }
}
  • 需要注意官网示例代码中的 splashScreenView.getIconAnimationDurationMillis()splashScreenView.getIconAnimationStartMillis() 在实际测试中,SplashScreenView 中并没有发现这两个方法,取而代之的是 splashScreenView.getIconAnimationDuration()splashScreenView.getIconAnimationStart();而且这两个方法返回的对象并不是 long, 而是 DurationInstant,需要分别再次调用它们的 toMillis()toEpochMilli() 方法转换成毫秒 (long)
  • 官网示例代码中的 SystemClock.uptimeMillis() 在实际测试中发现也是不对的,SystemClock.uptimeMillis() 返回的是从手机开机时到现在的时间 (毫秒),但是 getIconAnimationStart() 返回的是却是当时手机系统显示的时间
  • 需要注意的是 animationDurationiconAnimationStart 只有当 配置的是动画时才不为 null,如果配置的只是普通图片,则会返回 null, 所以计算剩余时长时需要判断非空

源码分析

涉及到的主要类

  • SplashScreenView:启动画面所显示的 View,继承自 FrameLayout;对应系统布局文件是:splash_screen_view.xml

    //splash_screen_view.xml
    <android.window.SplashScreenView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_height="match_parent"
        android:layout_width="match_parent"
        android:orientation="vertical">
    
        <View android:id="@+id/splashscreen_icon_view"
              android:layout_height="wrap_content"
              android:layout_width="wrap_content"
              android:layout_gravity="center"
              android:contentDescription="@string/splash_screen_view_icon_description"/>
    
        <View android:id="@+id/splashscreen_branding_view"
              android:layout_height="wrap_content"
              android:layout_width="wrap_content"
              android:layout_gravity="center_horizontal|bottom"
              android:layout_marginBottom="60dp"
              android:contentDescription="@string/splash_screen_view_branding_description"/>
    
    </android.window.SplashScreenView>
    
    public final class SplashScreenView extends FrameLayout {
           
           
    	private int mInitBackgroundColor;//界面背景色
    	private View mIconView;//界面中间显示的图标
        private View mBrandingImageView;//底部品牌图标
        private Duration mIconAnimationDuration;//启动画面显示时长
        private Instant mIconAnimationStart;//中间动画开始执行的时间
    	public static class Builder {
           
           
    		private Drawable mIconDrawable;//界面中间显示的图标
            private Drawable mIconBackground;//界面中间显示的图标的背景色
            private Drawable mBrandingDrawable;//底部品牌图标
            private Instant mIconAnimationStart;//中间动画开始执行的时间
            private Duration mIconAnimationDuration;//启动画面显示时长
    		
    		public SplashScreenView build() {
           
           
    			...
    			final SplashScreenView view = (SplashScreenView)
                        layoutInflater.inflate(R.layout.splash_screen_view, null, false);
                view.mInitBackgroundColor = mBackgroundColor;
    			view.setBackgroundColor(mBackgroundColor);//设置背景色
    			
    			ImageView imageView = view.findViewById(R.id.splashscreen_icon_view);
    			imageView.setImageDrawable(mIconDrawable);设置界面中间图标/动画
    			imageView.setBackground(mIconBackground);//设置中间显示的图标的背景色
    			
    			view.mBrandingImageView = view.findViewById(R.id.splashscreen_branding_view);
    			view.mBrandingImageView.setBackground(mBrandingDrawable);//设置底部品牌图标
    			...
    			return view;
    		}
    	}
    }
    
  • SplashScreen:用于客户端与 SplashScreenView 交互的接口,比如:自定义启动画面退出时的动画

  • StartingSurfaceController:Android12 新增,用于管理创建 / 释放 starting window surface;这个类里面通过系统属性 persist.debug.shell_starting_surface 的值来决定是使用全新的 SplashScreenView 还是旧版的启动画面

    • persist.debug.shell_starting_surface 在 Android12 上默认为空,根据源码来看,如果为空,则默认值为 true;也就是说 Android12 上默认是启用新版启动画面的,通过 adb 命令:adb shell setprop persist.debug.shell_starting_surface false 并且重启系统后,可以禁用全新启动画面,所有 APP 启动画面将变回旧版
    public class StartingSurfaceController {
           
           
    	static final boolean DEBUG_ENABLE_SHELL_DRAWER =
                SystemProperties.getBoolean("persist.debug.shell_starting_surface", true);
    			
    	StartingSurface createSplashScreenStartingSurface(ActivityRecord activity, String packageName,
                int theme, CompatibilityInfo compatInfo, CharSequence nonLocalizedLabel, int labelRes,
                int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId) {
           
           
            if (!DEBUG_ENABLE_SHELL_DRAWER) {
           
           //使用旧版的启动画面
                return mService.mPolicy.addSplashScreen(activity.token, activity.mUserId, packageName,
                        theme, compatInfo, nonLocalizedLabel, labelRes, icon, logo, windowFlags,
                        overrideConfig, displayId);
            }
    		//使用全新SplashScreenView
            synchronized (mService.mGlobalLock) {
           
           
                final Task task = activity.getTask();
                if (task != null && mService.mAtmService.mTaskOrganizerController.addStartingWindow(
                        task, activity, theme, null /* taskSnapshot */)) {
           
           
                    return new ShellStartingSurface(task);
                }
            }
            return null;
        }
    }
    
  • StartingSurfaceDrawer:创建 SplashScreenView 和启动窗口的主要流程

    public class StartingSurfaceDrawer {
           
           
    	void addSplashScreenStartingWindow(StartingWindowInfo windowInfo, IBinder appToken,
                @StartingWindowType int suggestType) {
           
           
            ... ...
    		//创建启动窗口参数
            final WindowManager.LayoutParams params = new WindowManager.LayoutParams(
                    WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
            params.setFitInsetsSides(0);
            params.setFitInsetsTypes(0);
            params.format = PixelFormat.TRANSLUCENT;
    		... ... 
            final SplashScreenViewSupplier viewSupplier = new SplashScreenViewSupplier();
    		//创建根布局
            final FrameLayout rootLayout = new FrameLayout(context);
            rootLayout.setPadding(0, 0, 0, 0);
            rootLayout.setFitsSystemWindows(false);
            final Runnable setViewSynchronized = () -> {
           
           
                SplashScreenView contentView = viewSupplier.get();
    			//将创建好的SplashScreenView添加到根布局
                rootLayout.addView(contentView);
    
            };
    		... ... 
    		//创建SplashscreenView
            mSplashscreenContentDrawer.createContentView(context, suggestType, activityInfo, taskId,
                    viewSupplier::setView);
    		... ... 
    		final WindowManager wm = context.getSystemService(WindowManager.class);
    		//添加窗口
    		if (addWindow(taskId, appToken, rootLayout, wm, params, suggestType)) {
           
           
    			... ...
    		}
        }
    	protected boolean addWindow(int taskId, IBinder appToken, View view, WindowManager wm,
                WindowManager.LayoutParams params, @StartingWindowType int suggestType) {
           
           
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "addRootView");
    		... ... 
            wm.addView(view, params);
            ... ... 
        }
    }
    
  • SplashscreenContentDrawer:创建 SplashscreenView 的实现类

    public class SplashscreenContentDrawer {
           
           
    	void createContentView(Context context, @StartingWindowType int suggestType, ActivityInfo info,
                int taskId, Consumer<SplashScreenView> splashScreenViewConsumer) {
           
           
    			...
    			//创建SplashScreenView
                SplashScreenView contentView;
                    contentView = makeSplashScreenContentView(context, info, suggestType);
    			...
    			//通知SplashScreenView创建完毕
                splashScreenViewConsumer.accept(contentView);
            });
        }
    	private SplashScreenView makeSplashScreenContentView(Context context, ActivityInfo ai,
                @StartingWindowType int suggestType) {
           
           
    		... 
    		//读取配置的窗口属性
            getWindowAttrs(context, mTmpAttrs);
    		...
    		//开始创建SplashScreenView
            return new StartingWindowViewBuilder(context, ai)
                    .setWindowBGColor(themeBGColor)
                    .overlayDrawable(legacyDrawable)
                    .chooseStyle(suggestType)
                    .build();
        }
    	private static void getWindowAttrs(Context context, SplashScreenWindowAttrs attrs) {
           
           
    		//读取在themes.xml中配置的属性
            final TypedArray typedArray = context.obtainStyledAttributes(
                    com.android.internal.R.styleable.Window);
            attrs.mWindowBgResId = typedArray.getResourceId(R.styleable.Window_windowBackground, 0);
            attrs.mWindowBgColor = safeReturnAttrDefault((def) -> typedArray.getColor(
                    R.styleable.Window_windowSplashScreenBackground, def),
                    Color.TRANSPARENT);
            attrs.mSplashScreenIcon = safeReturnAttrDefault((def) -> typedArray.getDrawable(
                    R.styleable.Window_windowSplashScreenAnimatedIcon), null);
            attrs.mAnimationDuration = safeReturnAttrDefault((def) -> typedArray.getInt(
                    R.styleable.Window_windowSplashScreenAnimationDuration, def), 0);
            attrs.mBrandingImage = safeReturnAttrDefault((def) -> typedArray.getDrawable(
                    R.styleable.Window_windowSplashScreenBrandingImage), null);
            attrs.mIconBgColor = safeReturnAttrDefault((def) -> typedArray.getColor(
                    R.styleable.Window_windowSplashScreenIconBackgroundColor, def),
                    Color.TRANSPARENT);
            typedArray.recycle();
        }
    	private class StartingWindowViewBuilder {
           
           
    		SplashScreenView build() {
           
           
                Drawable iconDrawable;
                final int animationDuration;
    			...
    			//设置中间的图标/动画
                if (mTmpAttrs.mSplashScreenIcon != null) {
           
           
                    // Using the windowSplashScreenAnimatedIcon attribute
                    iconDrawable = mTmpAttrs.mSplashScreenIcon;
                    animationDuration = mTmpAttrs.mAnimationDuration;
    
                    // There is no background below the icon, so scale the icon up
                    if (mTmpAttrs.mIconBgColor == Color.TRANSPARENT
                            || mTmpAttrs.mIconBgColor == mThemeColor) {
           
           
                        mFinalIconSize *= NO_BACKGROUND_SCALE;
                    }
                    createIconDrawable(iconDrawable, false);
                } 
    			...
                return fillViewWithIcon(mFinalIconSize, mFinalIconDrawables, animationDuration);
            }
    		private SplashScreenView fillViewWithIcon(int iconSize, @Nullable Drawable[] iconDrawable,
                    int animationDuration) {
           
           
                final SplashScreenView.Builder builder = new SplashScreenView.Builder(mContext)
                        .setBackgroundColor(mThemeColor)
                        .setOverlayDrawable(mOverlayDrawable)
                        .setIconSize(iconSize)
                        .setIconBackground(background)
                        .setCenterViewDrawable(foreground)
                        .setAnimationDurationMillis(animationDuration);
    			//设置底部的品牌图标
                if (mSuggestType == STARTING_WINDOW_TYPE_SPLASH_SCREEN
                        && mTmpAttrs.mBrandingImage != null) {
           
           
                    builder.setBrandingDrawable(mTmpAttrs.mBrandingImage, mBrandingImageWidth,
                            mBrandingImageHeight);
                }
                return splashScreenView;
            }
    	}
    }
    

大体类方法调用过程

  • ActivityRecord.showStartingWindow -> addStartingWindow -> scheduleAddStartingWindow ->
  • AddStartingWindow.run
  • SplashScreenStartingData.createStartingSurface ->
  • StartingSurfaceController.createSplashScreenStartingSurface ->
  • TaskOrganizerController.addStartingWindow
  • TaskOrganizerController.TaskOrganizerState.addStartingWindow
  • TaskOrganizerController.TaskOrganizerCallbacks.addStartingWindow
  • TaskOrganizer.addStartingWindow
  • StartingWindowController.addStartingWindow
  • StartingSurfaceDrawer.addSplashScreenStartingWindow
  • SplashscreenContentDrawer.createContentView -> makeSplashScreenContentView ->
  • getWindowAttrs -> StartingWindowViewBuilder.build -> fillViewWithIcon
  • SplashScreenView.Builder
  • StartingSurfaceDrawer.addWindow

自定义退出动画源码分析

  • 通过 Activity 获取用于与 SplashscreenView 交互的 SplashScreen 接口;可以看出 SplashScreen 接口的实现类是 SplashScreen 的内部类 SplashScreenImpl
class Activity{
     
     
	public final @NonNull SplashScreen getSplashScreen() {
     
     
        return getOrCreateSplashScreen();
    }

    private SplashScreen getOrCreateSplashScreen() {
     
     
        synchronized (this) {
     
     
            if (mSplashScreen == null) {
     
     
                mSplashScreen = new SplashScreen.SplashScreenImpl(this);
            }
            return mSplashScreen;
        }
    }
}
  • 设置退出动画监听;可以看到真正的实现类是 SplashScreenManagerGlobal;
class SplashScreenImpl implements SplashScreen {
     
     
	private OnExitAnimationListener mExitAnimationListener;
	private final SplashScreenManagerGlobal mGlobal;

	public SplashScreenImpl(Context context) {
     
     
		mGlobal = SplashScreenManagerGlobal.getInstance();
	}

	@Override
	public void setOnExitAnimationListener(//设置监听
			@NonNull SplashScreen.OnExitAnimationListener listener) {
     
     
		synchronized (mGlobal.mGlobalLock) {
     
     
			if (listener != null) {
     
     
				mExitAnimationListener = listener;
				mGlobal.addImpl(this);
			}
		}
	}

	@Override
	public void clearOnExitAnimationListener() {
     
     //取消监听
		synchronized (mGlobal.mGlobalLock) {
     
     
			mExitAnimationListener = null;
			mGlobal.removeImpl(this);
		}
	}
	... ...
}
  • SplashScreenManagerGlobal:它也是 SplashScreen 的内部类,单例模式,初始化时会向 ActivityThread 注册自己,当启动画面将要退出时回调它的 handOverSplashScreenView 方法

    • 注册的监听全部保存在 SplashScreenManagerGlobal 的 ArrayList 列表中
    class SplashScreenManagerGlobal {
           
           
    	private final Object mGlobalLock = new Object();
    	private final ArrayList<SplashScreenImpl> mImpls = new ArrayList<>();
    
    	private SplashScreenManagerGlobal() {
           
           
    		//向ActivityThread注册自身,用于回调handOverSplashScreenView方法
    		ActivityThread.currentActivityThread().registerSplashScreenManager(this);
    	}
    
    	public static SplashScreenManagerGlobal getInstance() {
           
           
    		return sInstance.get();
    	}
    
    	private static final Singleton<SplashScreenManagerGlobal> sInstance =
    			new Singleton<SplashScreenManagerGlobal>() {
           
           
    				@Override
    				protected 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(@NonNull IBinder token,
    			@NonNull SplashScreenView splashScreenView) {
           
           
    		... ...
    		//处理跳过启动画面逻辑,分发退出监听
    		dispatchOnExitAnimation(token, splashScreenView);
    	}
    
    	private void dispatchOnExitAnimation(IBinder token, SplashScreenView view) {
           
           
    		synchronized (mGlobalLock) {
           
           
    			final SplashScreenImpl impl = findImpl(token);
    			impl.mExitAnimationListener.onSplashScreenExit(view);
    		}
    	}
    }
    
  • ActivityThread 在哪里回调 SplashScreenManagerGlobal.handOverSplashScreenView 方法?

    class ActivityThread{
           
           
    	private SplashScreen.SplashScreenManagerGlobal mSplashScreenGlobal;
    	
    	public void registerSplashScreenManager(
                @NonNull SplashScreen.SplashScreenManagerGlobal manager) {
           
           
            synchronized (this) {
           
           
                mSplashScreenGlobal = manager;
            }
        }
    	
    	@Override
        public void handOverSplashScreenView(@NonNull ActivityClientRecord r) {
           
           
            final SplashScreenView v = r.activity.getSplashScreenView();
            if (v == null) {
           
           
                return;
            }
            synchronized (this) {
           
           
                if (mSplashScreenGlobal != null) {
           
           
                    mSplashScreenGlobal.handOverSplashScreenView(r.token, v);
                }
            }
        }
    }
    
  • ActivityThread.handOverSplashScreenView 大体调用过程:

    • ActivityClientController.splashScreenAttached ->
    • ActivityRecord.splashScreenAttachedLocked -> onSplashScreenAttachComplete
    • ClientLifecycleManager.scheduleTransaction ->
    • TransferSplashScreenViewStateItem.execute(mRequest==HANDOVER_TO)
    • ActivityThread.handOverSplashScreenView ->
    • SplashScreenGlobal.handOverSplashScreenView -> dispatchOnExitAnimation ->
    • ExitAnimationListener.onSplashScreenExit

转:

Android 12 新 APP 启动画面 (SplashScreen API) 简介 && 源码分析


--Posted from Rpc

Android splash screen 启动画面 初级

Android splash screen 启动画面 初级

  1. 新建Android XML file 的welcome布局文件 -----启动画面界面

<?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="match_parent"
    android:orientation="vertical"
    android:background="@drawable/welcome_pic" > 
</LinearLayout>

    在res中新建文件夹drawable----将welcome_pic放在文件夹中,就可以引用了 

   2.   新建启动画面的activity,运行完后跳转到主界面

    新建class,welcome----添加以下代码

public class welcome extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.welcome); 
        //通过时间控制函数Timer 跳转
        new Timer().schedule(new TimerTask(){
                        @Override
			public void run() {
				startActivity(new Intent(welcome.this,MainActivity.class));
				finish(); 
			} 
        }, 3000);//单位是毫秒
    }
}

    3.  AndroidManiFest.xml设置 让启动界面先运行

    启动时,先进去welcome的activity,

<activity 
            android:name="com.pearl.splash_screen.welcome"
            android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"
            >
            <intent-filter >
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER"  />
            </intent-filter>
        </activity>

    再设置跳转后的主界面

        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
        </activity>

It''s done

github下载: https://github.com/pearl2015/UI.git   splash screen


Android SplashScreen

Android SplashScreen

我正在开发一个应用程序,它基本上会在应用程序本身的开始处下载大量数据,并将其显示在ListActivity中。我打算做的是显示一个启动屏幕,直到加载数据。

到现在为止,我所有的尝试都是徒劳的。我尝试了anddev.org提到的方法,但是我的问题是主要的Activity应该开始,但是在我填充ListActivity之前,初始屏幕应该是可见的。简而言之,我必须执行以下步骤:

  1. 开始我的主要活动。
  2. 显示启动画面。
  3. 继续在后台运行该过程。
  4. 处理完成后退出启动画面,并显示主列表。

希望你了解它的样子。

Android VideoView SplashScreen

Android VideoView SplashScreen

这是我的splash. java,我使用我的videoView作为contentView.有没有什么方法可以将视频集中在videoView的内容中?

或者更好的事情是什么?

package com.android;

import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.net.Uri;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.widget.VideoView;

public class Splash extends Activity
{
    VideoView vidHolder;
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        try
        {
            vidHolder = new VideoView(this);
            setContentView(vidHolder);
            Uri video = Uri.parse("android.resource://" + getPackageName() + "/" + R.raw.splash);
            vidHolder.setVideoURI(video);
            vidHolder.setonCompletionListener(new OnCompletionListener()
            {
                public void onCompletion(MediaPlayer mp) {
                    jump();
            }});
            vidHolder.start();

        } catch(Exception ex) {
            jump();
        }
    }

    private void jump()
    {
        if(isFinishing())
            return;
        startActivity(new Intent(this,MainActivity.class));
        finish();
    }
}

解决方法

使用布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
  <VideoView android:id="@+id/myvideo"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_centerInParent="true"/>
</RelativeLayout>

注意:你没有要求它,但你的代码来自其他地方的一个例子,它将在视频之前和之后显示臭名昭着的黑色闪光.你需要添加vidHolder.setZOrderOnTop(true);避免这种情况(在#setVideoUri之后).

今天的关于在cordova-plugin-splashscreen中更改Splash Screen Spinner的颜色scope怎么改颜色的分享已经结束,谢谢您的关注,如果想了解更多关于Android 12 新 APP 启动画面 (SplashScreen API) 简介 && 源码分析、Android splash screen 启动画面 初级、Android SplashScreen、Android VideoView SplashScreen的相关知识,请在本站进行查询。

本文标签: