美文网首页android应用框架简化开发
windowIsTranslucent和windowBackgr

windowIsTranslucent和windowBackgr

作者: lmz14 | 来源:发表于2018-07-01 20:09 被阅读84次

      在Activity A切换到Activity B时,有时会遇到黑屏或者白屏的闪屏问题,经常我们会给Activity B设置一个透明主题来解决,即通过设置属性android:windowIsTranslucent=true或者android:windowBackground=@color/transparent。那么这两个属性有区别呢?下面从它们对Activity生命周期的影响来对比说明。

    android:windowIsTranslucent 窗口是否设置为半透明
    android:windowBackground 整个窗口的背景,包括边框和内部

    Activity A :MainActivity.java

    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        private Button btnTransActivity;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.e(Contants.TAG,"MainActivity onCreate");
            setContentView(R.layout.activity_main);
            initView();
            initListener();
        }
    
        @Override
        protected void onRestart() {
            super.onRestart();
            Log.e(Contants.TAG,"MainActivity onRestart");
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.e(Contants.TAG,"MainActivity onStart");
        }
    
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.e(Contants.TAG,"MainActivity onResume");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.e(Contants.TAG,"MainActivity onPause");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.e(Contants.TAG,"MainActivity onStop");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.e(Contants.TAG,"MainActivity onDestroy");
        }
    
        private void initView() {
            btnTransActivity = findViewById(R.id.btnTransActivity);
        }
    
        private void initListener() {
            btnTransActivity.setOnClickListener(this);
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId()){
                case R.id.btnTransActivity:
                    Intent intent = new Intent(MainActivity.this,TransparentThemeActivity.class);
                    startActivity(intent);
                    break;
                default:
                    break;
            }
        }
    }
    

    Activity B:TransparentThemeActivity

    public class TransparentThemeActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Log.e(Contants.TAG,"TransparentThemeActivity onCreate");
            setContentView(R.layout.activity_transparent_theme);
        }
    
        @Override
        protected void onRestart() {
            super.onRestart();
            Log.e(Contants.TAG,"TransparentThemeActivity onRestart");
        }
    
        @Override
        protected void onStart() {
            super.onStart();
            Log.e(Contants.TAG,"TransparentThemeActivity onStart");
        }
    
    
        @Override
        protected void onResume() {
            super.onResume();
            Log.e(Contants.TAG,"TransparentThemeActivity onResume");
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            Log.e(Contants.TAG,"TransparentThemeActivity onPause");
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            Log.e(Contants.TAG,"TransparentThemeActivity onStop");
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            Log.e(Contants.TAG,"TransparentThemeActivity onDestroy");
        }
    }
    

    Activity B的theme

    <!--主题1-->
    <style name="TransparentTheme1" parent="Theme.AppCompat.NoActionBar">
            <item name="android:windowNoTitle">true</item>
            <item name="android:windowIsTranslucent">true</item>
    </style>
    
    <!--主题2-->
    <style name="TransparentTheme2" parent="Theme.AppCompat.NoActionBar">
            <item name="android:windowBackground">@color/transparent</item>
            <item name="android:windowNoTitle">true</item>
    </style>
    

    后台可见状态:onStart
    用户可见状态:onResume

    1、Activit A切换到B
    (1)android:windowIsTranslucent = true

    07-01 17:22:42.768 13454-13454/com.lmz.viewdemo E/activity: MainActivity onCreate
    07-01 17:22:42.836 13454-13454/com.lmz.viewdemo E/activity: MainActivity onStart
    07-01 17:22:42.839 13454-13454/com.lmz.viewdemo E/activity: MainActivity onResume
    07-01 17:22:48.925 13454-13454/com.lmz.viewdemo E/activity: MainActivity onPause
    07-01 17:22:48.953 13454-13454/com.lmz.viewdemo E/activity: TransparentThemeActivity onCreate
    07-01 17:22:48.975 13454-13454/com.lmz.viewdemo E/activity: TransparentThemeActivity onStart
    07-01 17:22:48.979 13454-13454/com.lmz.viewdemo E/activity: TransparentThemeActivity onResume
    

      从打印的log中可以发现Activity A(MainActivity)切换到B时,只执行到了onPause方法,并没有执行onStop方法,所以在Activity B对用户可见时,下面的Activity A是处于部分可见的状态。

    (2)android:windowBackground=@color/transparent

    07-01 18:33:26.480 15730-15730/com.lmz.viewdemo E/activity: MainActivity onCreate
    07-01 18:33:26.542 15730-15730/com.lmz.viewdemo E/activity: MainActivity onStart
    07-01 18:33:26.544 15730-15730/com.lmz.viewdemo E/activity: MainActivity onResume
    07-01 18:33:43.268 15730-15730/com.lmz.viewdemo E/activity: MainActivity onPause
    07-01 18:33:43.294 15730-15730/com.lmz.viewdemo E/activity: TransparentThemeActivity onCreate
    07-01 18:33:43.312 15730-15730/com.lmz.viewdemo E/activity: TransparentThemeActivity onStart
    07-01 18:33:43.315 15730-15730/com.lmz.viewdemo E/activity: TransparentThemeActivity onResume
    07-01 18:33:43.698 15730-15730/com.lmz.viewdemo E/activity: MainActivity onStop
    

      activity A和B的生命周期执行顺序正常。

    2、在Activity B页面,点击back键返回到A页面

    (1)android:windowIsTranslucent = true

    07-01 18:44:22.894 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onPause
    07-01 18:44:22.907 16995-16995/com.lmz.viewdemo E/activity: MainActivity onResume
    07-01 18:44:22.935 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onStop
    07-01 18:44:22.936 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onDestroy
    

      从1的activity切换操作中可知Activity A(MainActivity)并未调用onStop方法,只调用了onPause,所以点击back键,Activity A要从onPause状态到对用户可见,只需要调用onResume方法(可上google官网查看activity生命周期图)。

    (2)android:windowBackground=@color/transparent

    07-01 18:42:34.013 15730-15730/com.lmz.viewdemo E/activity: TransparentThemeActivity onPause
    07-01 18:42:34.019 15730-15730/com.lmz.viewdemo E/activity: MainActivity onRestart
    07-01 18:42:34.019 15730-15730/com.lmz.viewdemo E/activity: MainActivity onStart
    07-01 18:42:34.020 15730-15730/com.lmz.viewdemo E/activity: MainActivity onResume
    07-01 18:42:34.329 15730-15730/com.lmz.viewdemo E/activity: TransparentThemeActivity onStop
    07-01 18:42:34.329 15730-15730/com.lmz.viewdemo E/activity: TransparentThemeActivity onDestroy
    

      点击back键,Activity A从onStop状态到用户可见状态,需要调用onRestart、onStart、onResume方法,所以,点击back键也不会影响到activity的生命周期

    3、停留在B页面,将应用从前台切到后台
    (1)android:windowIsTranslucent = true

    07-01 18:48:51.428 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onPause
    07-01 18:48:51.483 16995-16995/com.lmz.viewdemo E/activity: MainActivity onStop
    07-01 18:48:51.486 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onStop
    

      从日志中可以看到,Activity A和Activity B都完全不可见(onStop)。而在A切到B时,A只调用了onPause方法,所以切到后台时,A到完全不可见,也调用onStop方法。

    (2)android:windowBackground=@color/transparent

    07-01 18:51:15.099 18093-18093/com.lmz.viewdemo E/activity: TransparentThemeActivity onPause
    07-01 18:51:15.151 18093-18093/com.lmz.viewdemo E/activity: TransparentThemeActivity onStop
    

      在A切换到B时,A已经完全不可见了,所以切到后台时,只有Activity B从可见到完全不可见,会调用onPause、onStop方法。

    4、将应用切回前台
    (1)android:windowIsTranslucent = true

    07-01 18:49:19.897 16995-16995/com.lmz.viewdemo E/activity: MainActivity onRestart
    07-01 18:49:19.901 16995-16995/com.lmz.viewdemo E/activity: MainActivity onStart
    07-01 18:49:19.904 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onRestart
    07-01 18:49:19.906 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onStart
    07-01 18:49:19.907 16995-16995/com.lmz.viewdemo E/activity: TransparentThemeActivity onResume
    

      从日志中可以看到,Activity A和B都从不可见状态(onStop)到可见的状态,只有B是到用户可见状态(onResume)。

    (2)android:windowBackground=@color/transparent

    07-01 18:51:40.964 18093-18093/com.lmz.viewdemo E/activity: TransparentThemeActivity onRestart
    07-01 18:51:40.964 18093-18093/com.lmz.viewdemo E/activity: TransparentThemeActivity onStart
    07-01 18:51:40.965 18093-18093/com.lmz.viewdemo E/activity: TransparentThemeActivity onResume
    

      只有activity B从不可见状态到用户可见的状态。

    小结:
    1、android:windowBackground不影响Activity的生命周期,即启动设置了该属性的Activity的生命周期不会受到影响。
    2、android:windowIsTranslucent = true会影响到Activity的生命周期,比如启动一个设置了该属性的Activity,若该activity对用户可见时,启动它的activity(即它下层的activity)并未完全不可见(即调用到了onPause,不会调用onStop方法),具体可见上面的操作对Activity生命周期的影响。

    优化:在实际开发中,发现对于Activity切换出现黑屏或者白屏处理中,若使用android:windowBackground对于7.0系统以上的手机还是会有闪屏的现象,若使用android:windowIsTranslucent = true就不会有闪屏现象,但是有两种情况需要进行优化:
    1、需要在应用从前台切到后台时,执行操作。
    判断是否切换后台的时机就需要放到onPause中去,若是切换后台,则执行操作。

    2、需要在应用从后台切到前台时,执行操作。
    若Activity A的上一层Activity B是透明主题,并且当前Activity B对用户完全可见的,此时Activity A处于onPause状态。
    (1)停留在Activity B页面,应用从前台切换到后台时,Activity A也会执行onStop方法, 在onStop方法中判断应用是否切换到后台,是,将全局变量AppUtils.isBackGroundStart置为true,否则置为false。
    (2)应用从后台切回前台时,当前只会有一个Activity会执行onResume方法(停留在Activity B页面时切到后台,所以切回前台时,只有Activity B会执行onResume), 此时可以通过全局变量isBackGroundStart判断应用是否是从后台切到前台的,执行需要在这个时机完成的操作后将isBackGroundStart置为false。

    AppUtils.java

    public static boolean isBackGroundStart = false;//是否从后台开启
       /**
         * 
         * 若Activity A的上一层Activity B是透明主题,并且当前Activity B对用户完全可见的,此时Activity A处于onPause状态。
         * 1、停留在Activity B页面,应用从前台切换到后台时,Activity A也会执行onStop方法,
         * 在onStop方法中判断应用是否切换到后台,是,将全局变量AppUtils.isBackGroundStart置为true,否则置为false。
         * 2、应用从后台切回前台时,当前只会有一个Activity会执行onResume方法(停留在Activity B页面时切到后台,所以切回前台时,只有Activity B会执行onResume),
         *  此时可以通过全局变量isBackGroundStart判断应用是否是从后台切到前台的,执行需要在这个时机完成的操作后将isBackGroundStart置为false。
         * !!!注意:这里的透明主题是指使用android:windowIsTranslucent = true设置窗口半透明
         * @param context
         * @return
         */
        public static boolean isBackground(Context context) {
            ActivityManager ActivityManager = (ActivityManager) context
                    .getSystemService(ACTIVITY_SERVICE);
            List<android.app.ActivityManager.RunningAppProcessInfo> appProcesses = ActivityManager
                    .getRunningAppProcesses();
            isBackGroundStart = false;
            if (TextUtil.isValidate(appProcesses)) {
                for (android.app.ActivityManager.RunningAppProcessInfo appProcess : appProcesses) {
                    if (appProcess != null && appProcess.processName.equals(context.getPackageName())) {
                    /*
                    BACKGROUND=400 EMPTY=500 FOREGROUND=100
                    GONE=1000 PERCEPTIBLE=130 SERVICE=300 ISIBLE=200
                     */
                        if (appProcess.importance != android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
                            //后台
                            isBackGroundStart = true;
                            return true;
                        } else {
                            //前台
                            return false;
                        }
                    }
                }
            }
            return false;
        }
    

    ActivityA.java

    public class ActivityA extends AppCompatActivity{
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_a);
        }
    
       @Override
        protected void onResume() {
            super.onResume();
            if (AppUtils.isBackGroundStart){
                //TODO 执行操作
    
                AppUtils.isBackGroundStart = false;
            }
        }
    
       @Override
        protected void onPause() {
            super.onPause();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            AppUtils.isBackground(ActivityA.this);
        }
    }
    

    ActivityB.java

    public class ActivityB extends AppCompatActivity{
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_b);
        }
    
       @Override
        protected void onResume() {
            super.onResume();
            if (AppUtils.isBackGroundStart){
                //TODO 执行操作
    
                AppUtils.isBackGroundStart = false;
            }
        }
    
       @Override
        protected void onPause() {
            super.onPause();
        }
    
        @Override
        protected void onStop() {
            super.onStop();
            AppUtils.isBackground(ActivityB.this);
        }
    }
    

    相关文章

      网友评论

        本文标题:windowIsTranslucent和windowBackgr

        本文链接:https://www.haomeiwen.com/subject/zxfhuftx.html