有关于Activity作为dialog全屏显示,沉浸式状态栏及屏幕亮度问题的一次总结
需求:
1.弹出一个全屏显示的Dialog,里面做了好多的逻辑处理,比如抢红包,请求接口,比如动画效果。
2.通过某一事件改变当前布局的背景颜色
效果图:

分析:
如果碰到布局和逻辑比较复杂的dialog,则建议用弹出activity作为一个dialog,因为生命周期及其API提供的比较多
实现全屏的dialog要设置主题
实现状态栏透明
设置亮度的问题
设置Activity透明度

使用自定义主题,先看看自定义主题中需要用到的一些属性设置说明
<!-- 在此添加一种颜色值模式ARGB{xxxxxxxx},A{前两位}表示Appha即透明度,取值为0-255 --> <style name="activity_DialogTransparent"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowFullscreen">true</item> <item name="android:backgroundDimEnabled">true</item> <item name="android:backgroundDimAmount">0.2</item> <item name="android:windowIsTranslucent">true</item> <item name="android:layout_width">fill_parent</item> <item name="android:layout_height">fill_parent</item> <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item> <!--Activity切换动画效果--> </style>
定义好主题之后需要在Activity配置中进行对主题的引用!
在代码中对窗体设置透明度灰度的方法
设置透明度(这是窗体本身的透明度,非背景)
WindowManager.LayoutParams windowLP = getWindow().getAttributes(); windowLP.alpha = 0.5f; getWindow().setAttributes(windowLP);
alpha在0.0f到1.0f之间。1.0完全不透明,0.0f完全透明
设置灰度
WindowManager.LayoutParams windowLP = getWindow().getAttributes(); windowLP.dimAmount = 0.5f; getWindow().setAttributes(windowLP); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
dimAmount在0.0f和1.0f之间,0.0f完全不暗,1.0f全暗
这些设置对dialog对话框同样也有效;
在清单文件中配置Activity时声明
android:theme="@android:style/Theme.Translucent"
设置Activity/Application全屏
1.在代码中设置
//无title requestWindowFeature(Window.FEATURE_NO_TITLE); //全屏 getWindow().setFlags(WindowManager.LayoutParams. FLAG_FULLSCREEN , WindowManager.LayoutParams. FLAG_FULLSCREEN); //此两段代码必须设置在setContentView()方法之前 setContentView(R.layout.main);
2.在配置文件中设置
在Activity的声明中设置主题为全屏
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
状态栏着色-透明状态栏
从Android4.4开始,才可以实现状态栏着色,并且从5.0开始系统更加完善了这一功能,可直接在主题中设置
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
或者
getWindow().setStatusBarColor(color)
来实现,但毕竟4.4+的机器还有很大的占比,所以就有必要寻求其它的解决方案。
第一种方案:
1、首先将手机手机状态栏透明化:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {//5.0及以上 View decorView = getWindow().getDecorView(); int option = View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE; decorView.setSystemUiVisibility(option); getWindow().setStatusBarColor(Color.TRANSPARENT); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {//4.4到5.0 WindowManager.LayoutParams localLayoutParams = getWindow().getAttributes(); localLayoutParams.flags = (WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS | localLayoutParams.flags); }
在相应的Activity或基类执行这段代码就ok了。
可见在4.4到5.0的系统、5.0及以上系统的处理方式有所不同
除了这种代码修改额方式外,还可以通过主题来修改,需要在values、values-v19、values-v21目录下分别创建相应的主题:
//values <style name="TranslucentTheme" parent="AppTheme"> </style> //values-v19 <style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">false</item> </style> //values-v21 <style name="TranslucentTheme" parent="Theme.AppCompat.Light.NoActionBar"> <item name="android:windowTranslucentStatus">true</item> <item name="android:windowTranslucentNavigation">false</item> <item name="android:statusBarColor">@android:color/transparent</item> </style>
给相应Activity或Application设置该主题就ok了。
两种方式根据需求选择就好了,到这里我们就完成了第一步,将状态栏透明化了。
完成了第一步,我们开始给状态栏加上想要的色彩吧!
在values、values-v19目录添加如下尺寸:
//values <dimen name="padding_top">0dp</dimen> //values-v19 <dimen name="padding_top">25dp</dimen>
关于25dp,在有些系统上可能有误差,这里不做讨论!
2.1 页面顶部使用Toolbar(或自定义title)
一般情况状态栏的颜色和Toolbar的颜色相同,既然状态栏透明化后,布局页面延伸到了状态栏,何不给Toolbar加上一个状态栏高度的顶部padding呢:
<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:paddingTop="@dimen/padding_top" android:theme="@style/AppTheme.AppBarOverlay" />
效果图下:

第二种方案:
在方案一中,我们没有使用android:fitsSystemWindows="true"属性,而是将布局延伸到状态栏来处理,这次我们使用android:fitsSystemWindows="true"属性,不让布局延伸到状态栏,这时状态栏就是透明的,然后添加一个和状态栏高、宽相同的指定颜色View来覆盖被透明化的状态栏。我们一步步来实现。
1、第一步还是先将状态栏透明化,方法同上。
2、在布局文件中添加android:fitsSystemWindows="true"属性:
<?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="match_parent" android:fitsSystemWindows="true" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/colorPrimary" android:theme="@style/AppTheme.AppBarOverlay" app:title="第二种方案" /> </LinearLayout>
3、创建View并添加到状态栏:
private void addStatusBarView() { View view = new View(this); view.setBackgroundColor(getResources().getColor(R.color.colorPrimary)); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, getStatusBarHeight(this)); ViewGroup decorView = (ViewGroup) findViewById(android.R.id.content); decorView.addView(view, params); }
原理很简单,但是要额外写这些代码。。。最后看下效果:

第三种方案:
和方案二类似,同样使用android:fitsSystemWindows="true"属性,再修改布局文件的根布局为需要的状态栏颜色,因根布局的颜色被修改,所以你需要在里边多嵌套一层布局,来指定界面的主背景色,比如白色等等,否则就和状态栏颜色一样了。说起来有点抽象,还是看具体的例子吧:
1、先将状态栏透明化,方法同上。
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" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ff9900" android:fitsSystemWindows="true"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#ffffff" android:orientation="vertical"> <android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#ff9900" android:theme="@style/AppTheme.AppBarOverlay" app:title="第三种方案" /> </LinearLayout> </RelativeLayout>
修改完了,看效果:

如果项目有几十个界面,这样的方式修改起来还是挺累的,你还要考虑各种嵌套问题。
后两种方案的例子相对简单,有兴趣的话你可以尝试更多的场景!
三种方式如何选择,相信到这里你应该有答案了吧,我个人更喜欢第一种!
有关于Activity屏幕亮度问题
/** * Android获取并设置Activity的亮度 * 此API只适合2.1以上版本 */ public class ActivityUtils { /** * 判断是否开启了自动亮度调节 * * @param aContentResolver * @return */ public static boolean isAutoBrightness(ContentResolver aContentResolver) { boolean automicBrightness = false; try { automicBrightness = Settings.System.getInt(aContentResolver, Settings.System.SCREEN_BRIGHTNESS_MODE) == Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC; } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } return automicBrightness; } /** * 获取屏幕的亮度 * * @param activity * @return */ public static int getScreenBrightness(Activity activity) { int nowBrightnessValue = 0; ContentResolver resolver = activity.getContentResolver(); try { nowBrightnessValue = android.provider.Settings.System.getInt( resolver, Settings.System.SCREEN_BRIGHTNESS); } catch (Exception e) { e.printStackTrace(); } return nowBrightnessValue; } /** * 设置亮度 * * @param activity * @param brightness */ public static void setBrightness(Activity activity, int brightness) { // Settings.System.putInt(activity.getContentResolver(), // Settings.System.SCREEN_BRIGHTNESS_MODE, // Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); WindowManager.LayoutParams lp = activity.getWindow().getAttributes(); lp.screenBrightness = Float.valueOf(brightness) * (1f / 255f); activity.getWindow().setAttributes(lp); } /** * 停止自动亮度调节 * * @param activity */ public static void stopAutoBrightness(Activity activity) { Settings.System.putInt(activity.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL); } /** * 开启亮度自动调节 * * @param activity */ public static void startAutoBrightness(Activity activity) { Settings.System.putInt(activity.getContentResolver(), Settings.System.SCREEN_BRIGHTNESS_MODE, Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC); } /** * 保存亮度设置状态 * * @param resolver * @param brightness */ public static void saveBrightness(ContentResolver resolver, int brightness) { Uri uri = android.provider.Settings.System .getUriFor("screen_brightness"); android.provider.Settings.System.putInt(resolver, "screen_brightness", brightness); resolver.notifyChange(uri, null); } }
注意以上只适用于2.1的版本。
可以通过seekBar改变其亮度:
/** * 使用SeekBar进行亮度控制: */ private void detalSeekBar() { sSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { @Override public void onStopTrackingTouch(SeekBar seekBar) { } @Override public void onStartTrackingTouch(SeekBar seekBar) { } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { LogUtil.e("yuyahao","progress: "+progress); if (progress < 10) { } else { messageTv.setText("activity当前亮度为: "+progress); ActivityUtils.setBrightness(MyShowLightDialog.this, progress); //ll_contentView.setBackgroundResource(ContextCompat.getColor(MainActivity.this,Color.parseColor("#"+getRandColorCode())); ll_contentView.setBackgroundColor(Color.parseColor("#"+getRandColorCode())); } } }); //获取当前亮度的位置 // int a =ActivityUtils.getScreenBrightness(this); // sSeekBar.setProgress(a); }
效果图:

github项目的地址:
如果你觉得此文对您有所帮助,欢迎入群 QQ交流群 :232203809
作者:codegoogle