- 使用Theme来统一基础背景色
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorNormalText</item>
<item name="windowBackground">@color/windowBackgroundColor</item>
<item name="textColorPrimary">@color/colorNormalText</item>
</style>
Theme里面统一设置了默认的背景颜色和字体颜色,在xml布局过程中,不单独对控件设置颜色,则使用默认
Theme的各种参数的解释
- android:colorPrimaryDark 应用的主要暗色调,statusBarColor默认使用该颜色
- android:statusBarColor 状态栏颜色,默认使用colorPrimaryDark
- android:colorPrimary 应用的主要色调,actionBar默认使用该颜色
- android:windowBackground 窗口背景颜色
- android:navigationBarColor 底部栏颜色
- android:colorForeground 应用的前景色,ListView的分割线,switch滑动区默认使用该颜色
- android:colorBackground 应用的背景色,popMenu的背景默认使用该颜色
- android:colorAccent 一般控件的选种效果默认采用该颜色
- android:colorControlNormal 控件的默认色调
- android:colorControlHighlight 控件按压时的色调
- android:colorControlActivated 控件选中时的颜色,默认使用colorAccent
- android:colorButtonNormal 默认按钮的背景颜色
- android:textColor Button,textView的文字颜色
- android:textColorPrimaryDisableOnly RadioButton checkbox等控件的文字
- android:textColorPrimary 应用的主要文字颜色,actionBar的标题文字默认使用该颜色
- 使用Style来统一常用的基础样式
常用的基础控件(Button,EditTextView)等可以抽取到Style,使用时引用即可,这样要改的时候直接改一个地方即可 - ToolBar不一定好用
官方的toolBar在某些情况下不一定好用,比如Title文字不能居中;不能添加左边的menu,左侧的返回按钮navigationIcon不能设置大小和padding值;menu在长按之后会弹出吐司,即使menu的title设置为空字符串,当然这些问题也可以有很多方法弥补,在你确定一定要用toolBar的情况下;否则按照自定义一个跟toolbar高度一样的view的方式来作为toolBar是比较好的选择 - 设置状态栏的颜色和状态栏字体颜色
1.安卓4.4以上版本才开始支持修改状态栏颜色
2.小米的MIUI,魅族的Flyme以及安卓6.0以上版本支持更改状态栏字体颜色,其他版本国内的rom目前没有找到好的解决办法
//小米
if (window != null) {
Class clazz = window.getClass();
try {
int darkModeFlag = 0;
Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
darkModeFlag = field.getInt(layoutParams);
Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
if (dark) {
extraFlagField.invoke(window, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
} else {
extraFlagField.invoke(window, 0, darkModeFlag);//清除黑色字体
}
} catch (Exception e) {
}
//魅族
try {
WindowManager.LayoutParams lp = window.getAttributes();
Field darkFlag = WindowManager.LayoutParams.class
.getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
Field meizuFlags = WindowManager.LayoutParams.class
.getDeclaredField("meizuFlags");
darkFlag.setAccessible(true);
meizuFlags.setAccessible(true);
int bit = darkFlag.getInt(null);
int value = meizuFlags.getInt(lp);
if (dark) {
value |= bit;
} else {
value &= ~bit;
}
meizuFlags.setInt(lp, value);
window.setAttributes(lp);
result = true;
} catch (Exception e) {
}
//android6.0以上版本
getWindow().getDecorView().setSystemUiVisibility( View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR);
注意6.0以上版本这里有坑,View的几个状态
1.View.SYSTEM_UI_FLAG_VISIBLE:显示状态栏,
Activity不全屏显示(恢复到有状态的正常情况)。
2.View.INVISIBLE:隐藏状态栏,同时Activity会伸展全屏显示。
3.View.SYSTEM_UI_FLAG_FULLSCREEN:Activity全屏显示,且状态栏被隐藏覆盖掉。
4.View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN:Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态遮住。
5.View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION:效果同 View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
6.View.SYSTEM_UI_LAYOUT_FLAGS:效果同View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
7.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION:隐藏虚拟按键(导航栏)。有些手机会用虚拟按键来代替物理按键。
8.View.SYSTEM_UI_FLAG_LOW_PROFILE:状态栏显示处于低能显示状态(low profile模式),状态栏上一些图标显示会被隐藏。
- 使用着色器实现Drawable的tint功能
Drawable的setColorFilter滤镜功能能够实现针对drawable的单独着色,例如app的一些icon,在某些情况下需要改变icon的颜色,一般我们就放两张图片,那么使用着色器就只需要一张图片;还有就是某些图片icon的按钮的按压效果,当按下去之后需要设置透明通道,将之前的图片覆盖一下,也可以使用着色器实现
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
iv.setImageDrawable(drawable);
这里有坑,在项目中使用时,发现同一个drawable下的图片,只要设置过一次颜色之后,其他图片都会成为这个颜色,再次设置无效,google了一番,发现是因为Android底层可能为了节约资源,将这个图片在内存中以共享的方式提供,加上这句代码,就可以实现图片在内存中是以copy形式存在(其实copy这个词也不确切,应该是重新引用了)
drawable.mutate();
drawable.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
iv.setImageDrawable(drawable);
- 使用系统自带的AlertDialog来实现弹窗
Support V7包在22.1.0之前的任何一个版本,AlertDialog一直都是Android4.0风格,直到Support-V7:22.1.0,在这之前,如果我们的项目中要使用Material样式的Dialog,Android5.0以下的设备根本不支持
但是,support-v7更新到22.1.0之后,我们就再也不需要使用上面的开源库来获得MaterialDiaolg了
但是... 系统自带的dialog能够定义的东西非常少,至少在api上没用能够定义字体颜色,按钮字体颜色和大小等属性,导致我们不得不自定义或者用第三方的库,那么其实我们只需要小小的更改一下系统dialog的style,就能实现很多东西
这里要感谢于神的这篇文章,通过查看分析源码,来自定义style
我们通过AlertDialog的Builder,跟源码
static int resolveDialogTheme(@NonNull Context context, @StyleRes int resid) {
if (resid >= 0x01000000) { // start of real resource IDs.
return resid;
} else {
TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.alertDialogTheme, outValue, true);
return outValue.resourceId;
}
}
发现系统要求我们如果需要自定义dialog属性,需要在theme里面使用alertDialogTheme,那么怎么去写这个alertDialogTheme呢,来看看系统怎么写的,我们就怎么写,于是就按照如下的style来写,这里有个小坑就是,我们自定义完了按钮字体颜色,运行发现content的字体颜色也跟着变了,
<!--更改的系统的dialog样式-->
<style name="Theme.AppCompat.Light.Dialog.Alert.Custom" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
<item name="android:background">@color/dialog_bg_color</item>
<!--取消按钮字体颜色-->
<item name="buttonBarNegativeButtonStyle">@style/buttonBarNegative</item>
<!--确认按钮字体颜色-->
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="buttonBarNegative" parent="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textColor">@color/title_color</item>
</style>
查看了一下,忘记加textColorPrimary这个属性
最终如下:
<!--更改的系统的dialog样式-->
<style name="Theme.AppCompat.Light.Dialog.Alert.Custom" parent="@style/Theme.AppCompat.Light.Dialog.Alert">
<item name="android:background">@color/dialog_bg_color</item>
<!--字体统一颜色-->
<item name="android:textColorPrimary">@color/title_color</item>
<!--取消按钮字体颜色-->
<item name="buttonBarNegativeButtonStyle">@style/buttonBarNegative</item>
<!--确认按钮字体颜色-->
<item name="colorAccent">@color/colorAccent</item>
</style>
<style name="buttonBarNegative" parent="@style/Widget.AppCompat.Button.ButtonBar.AlertDialog">
<item name="android:textColor">@color/title_color</item>
</style>
image.png
成功通过更改系统的style实现的MaterialDesign风格的弹窗
网友评论