什么是沉浸式凹髓?
沉浸式這個概念提出來很久了孵坚,相信大家也都知道是什么付枫。是什么我不啰嗦了,反正玩來玩去就是在玩狀態(tài)欄的顏色狗热。
我記得 MaterialDesign 系列的第一篇文章就給大家分享了一張圖钞馁。
對,沒錯匿刮,我們今天要講的就是圖上的StatusBarColor僧凰。沉浸式也就是在玩這個 StatuBarColor,其實沒什么意思熟丸。
如 全民TV 的首頁設計
怎么用
getWindow().setStatusBarColor(int color);
好了训措,講完了。
兼容性問題
剛剛這個方法僅適用與5.0+的手機虑啤,如果要兼容5.0以下的手機隙弛,則狀態(tài)欄只支持透明效果,但是沒有 api 提供去設置顏色狞山。
4.4以前的手機不支持修改狀態(tài)欄顏色
現(xiàn)在我們就來看看怎么修改4.4~5.0的狀態(tài)欄顏色全闷。
首先我們的,系統(tǒng)中有一個 windowTranslucentStatus 屬性萍启,不知道大家用過沒总珠,就是設置狀態(tài)欄為半透明屏鳍,并且會被 View 填充。然后我們的思路就是局服,抽取出 TranslucentActivity钓瞭,然后提供方法,讓 Toolbar 填充狀態(tài)欄淫奔。
第一步山涡,在 values-v19/style.xml 文件里面給 style 添加下面這條屬性
<item name="android:windowTranslucentStatus">true</item>
第二步,使用繼承了這個 Theme 的 的主題給 Activity唆迁。
第三步鸭丛,抽取 BaseTranslucentActivity
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
public class BaseTranslucentActivity extends AppCompatActivity {
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//判斷版本,如果[4.4,5.0)就設置狀態(tài)欄和導航欄為透明
if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT
&&android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.LOLLIPOP){
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
//設置虛擬導航欄為透明
getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
}
}
@SuppressLint("NewApi")
public void setOrChangeTranslucentColor(Toolbar toolbar,int translucentPrimaryColor){
//判斷版本,如果[4.4,5.0)就設置狀態(tài)欄和導航欄為透明
if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.KITKAT
&&android.os.Build.VERSION.SDK_INT<android.os.Build.VERSION_CODES.LOLLIPOP){
if(toolbar!=null){
//1.先設置toolbar的高度
LayoutParams params = toolbar.getLayoutParams();
int statusBarHeight = getStatusBarHeight(this);
params.height += statusBarHeight ;
toolbar.setLayoutParams(params );
//2.設置paddingTop,以達到狀態(tài)欄不遮擋toolbar的內(nèi)容唐责。
toolbar.setPadding(
toolbar.getPaddingLeft(),
toolbar.getPaddingTop()+getStatusBarHeight(this),
toolbar.getPaddingRight(),
toolbar.getPaddingBottom());
//設置頂部的顏色
toolbar.setBackgroundColor(translucentPrimaryColor);
}else if(android.os.Build.VERSION.SDK_INT>=android.os.Build.VERSION_CODES.LOLLIPOP){
getWindow().setNavigationBarColor(translucentPrimaryColor);
getWindow().setStatusBarColor(translucentPrimaryColor);
}else{
//<4.4的鳞溉,不做處理
}
}
private int getNavigationBarHeight(Context context) {
return getSystemComponentDimen(this, "navigation_bar_height");
}
/**
* 獲取狀態(tài)欄的高度
* @param context
* @return
*/
private int getStatusBarHeight(Context context) {
// 反射手機運行的類:android.R.dimen.status_bar_height.
return getSystemComponentDimen(this, "status_bar_height");
}
private static int getSystemComponentDimen(Context context, String dimenName){
// 反射手機運行的類:android.R.dimen.status_bar_height.
int statusHeight = -1;
try {
Class<?> clazz = Class.forName("com.android.internal.R$dimen");
Object object = clazz.newInstance();
String heightStr = clazz.getField(dimenName).get(object).toString();
int height = Integer.parseInt(heightStr);
//dp--->px
statusHeight = context.getResources().getDimensionPixelSize(height);
} catch (Exception e) {
e.printStackTrace();
}
return statusHeight;
}
private static boolean hasNavigationBarShow(WindowManager wm){
Display display = wm.getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics();
//獲取整個屏幕的高度
display.getRealMetrics(outMetrics);
int heightPixels = outMetrics.heightPixels;
int widthPixels = outMetrics.widthPixels;
//獲取內(nèi)容展示部分的高度
outMetrics = new DisplayMetrics();
display.getMetrics(outMetrics);
int heightPixels2 = outMetrics.heightPixels;
int widthPixels2 = outMetrics.widthPixels;
int w = widthPixels-widthPixels2;
int h = heightPixels-heightPixels2;
return w>0||h>0;//豎屏和橫屏兩種情況。
}
}
代碼里面的注釋清晰明了鼠哥,簡單粗暴熟菲。寶寶在做這一塊兼容性開發(fā)的時候踩過很多很多的坑,查了很多資料朴恳,最后才有了這個類抄罕。使用反射機制獲取代碼中狀態(tài)欄的高度,然后再給 Toolbar 設置 PaddingTop菜皂,然后就 Ok 了贞绵。
當然厉萝,你也可以用 fitsSystemWindows 為true 來恍飘,實現(xiàn),那不那個需要給每個activity 的 xml 都設置這個屬性谴垫,多麻煩章母,哈哈哈~
第二個問題:可能很多同學都會有這樣的場景需求,我們需要一個全透明的狀態(tài)欄覆蓋在圖片上方翩剪,如下圖
但是實際上卻變成了這樣乳怎,半透明
媽賣批,這是為什么前弯,我明明設置了 windowTranslucentStatus 為 true蚪缀,系統(tǒng)控件可以填充狀態(tài)欄,然后再把狀態(tài)欄設置為透明色啊恕出。
后來询枚,終于在一篇博客中找到了解決方案~~
if (Build.VERSION.SDK_INT >= 21) {
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);
}
不用設置 windowTranslucentStatus 為 true,直接使用這兩個 flag 就好了浙巫,不會的同學趕緊做筆記~~
問題解決了金蜀,那么這些 flag 到底有什么作用呢刷后,我們直接點擊這個 flag 就可以看源碼,源碼里面都有英語注釋的渊抄,下面是我統(tǒng)計好的一些 flag 的作用尝胆。
參數(shù) | api 版本 | 含義 |
---|---|---|
View.SYSTEM_UI_FLAG_VISIBLE | 14 | 默認標記 |
View.SYSTEM_UI_FLAG_LOW_PROFILE | 14 | 低功耗模式, 會隱藏狀態(tài)欄圖標, 在4.0上可以實現(xiàn)全屏 |
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | 16 | 保持整個View穩(wěn)定, 常跟bar 懸浮, 隱藏共用, 使View不會因為SystemUI的變化而做layout |
View.SYSTEM_UI_FLAG_FULLSCREEN | 16 | 狀態(tài)欄隱藏 |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | 16 | 狀態(tài)欄上浮于Activity |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | 14 | 隱藏導航欄 |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | 16 | 導航欄上浮于Activity |
View.SYSTEM_UI_FLAG_IMMERSIVE | 19 | Kitkat新加入的Flag, 沉浸模式, 可以隱藏掉status跟navigation bar, 并且在第一次會彈泡提醒, 它會覆蓋掉之前兩個隱藏bar的標記, 并且在bar出現(xiàn)的位置滑動可以呼出bar |
View.SYSTEM_UI_FLAG_IMMERSIVE_STIKY | 19 | 與上面唯一的區(qū)別是, 呼出隱藏的bar后會自動再隱藏掉 |
然后這里設置的 flag 會和WindowManger 的一些 flag相互影響,如果使用的過程中护桦,出現(xiàn)了預測之外的效果含衔,可以去看看源碼注釋,上面有說明哪些 flag 會影響到哪些 flag二庵,或許能解決問題抱慌。
沉浸式牽涉到的知識點也就這些,有什么問題留言吧~
上周五有了新需求眨猎,所以這篇文章晚來了今天抑进,Sorry~