博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
android沉浸式状态栏StatusBar在不同Window下的实现
阅读量:3778 次
发布时间:2019-05-22

本文共 15190 字,大约阅读时间需要 50 分钟。

android沉浸式状态栏StatusBar在不同Window下的实现

StatusBar沉浸式的2种实现方式

对于沉浸式状态栏的实现,我觉得有两种实现方式

一是:将状态栏的颜色和状态栏下面的View颜色保持一致或相近。如图:

image

二是:将View充满全屏,状态栏覆盖在View上,将状态栏设置为透明色

image

StatusBar沉浸式实现的真相

我们使用Android Studio的提供的截图工具Layout Inspector工具分析可以知道,实际上显示时间、信号等SystemBar是系统级别的一个Window(悬浮窗)。而StatusBar是SystemBar下面的View,是DecorView的一部分。我们通常设置StatusBar的颜色其实就是给SystemBar覆盖的StatusBar设置一个背景色。

LayoutInspetor工具的截图:

image

由上图可知,StatusBar是DecorView的一部分,是一个View设置了背景色,没有系统的时间、信号等信息。

所以我们所设置状态栏的颜色,就是设置DecorView中的StatusBar的View的颜色。

image

上图说明:ImageView占满了怎个DecorView,没有StatusBar。

StatusBar的在不同Window上的实现

我们不管是Activity,Fragment还是在DialogFragment以及Window悬浮窗,都是有可能有使用沉浸式状态栏的。那么如何实现呢,以下实现是基于Android5.0以上,对Android4.4不兼容?

1. Activity和Fragment实现StatusBar的沉浸式

Activity和Fragment的实现StatusBar沉浸式的方式是一样的,我们知道Activity是依附于Window的,具体实现是PhoneWindow的DecorView。Fragment是依附于Activity的,所以可以通过获取Activity,在获取Window。来实现修改StatusBar的颜色。下面以Activity为例来分别看下2种实现方式,Fragment的实现方式会在的中分享到github上,不在此列举。

  • 方式一:
public class MutilStatusBarActivity extends Activity {
@Override protected void onCreate(Bundle savedInstanceState) { getWindow().requestFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); StatusBarManager.getInstance().setStatusBar(getWindow(), Color.parseColor("#dd0000")); setContentView(R.layout.activity_text); final TextView imageView = (TextView) findViewById(R.id.image); imageView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ViewHelperUtils.click(getWindow(), imageView); } }); }}
  • 方式二:
public class ImageStatusBarActivity extends Activity {
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { getWindow().requestFeature(Window.FEATURE_NO_TITLE); super.onCreate(savedInstanceState); StatusBarManager.getInstance().setActivityWindowStyle(getWindow()); StatusBarManager.getInstance().setStatusBar(getWindow(), Color.TRANSPARENT); setContentView(R.layout.common_image); initView(); } private void initView() { ImageView imageView = (ImageView) findViewById(R.id.second_image); ViewHelperUtils.setImageViewBitmap(imageView); }}

这里封装了2个类。

StatusBarManager:设置StatusBar的核心类

public class StatusBarManager {
private final static StatusBarManager ourInstance = new StatusBarManager(); public static StatusBarManager getInstance() { return ourInstance; } private StatusBarManager() { } /** * 设置StatusBar字体颜色 *

* 参数true表示StatusBar风格为Light,字体颜色为黑色 * 参数false表示StatusBar风格不是Light,字体颜色为白色 *

*

true
* 在theme或style中使用这个属性改变StatusBar的字体颜色,这种形式相对不灵活 */ @TargetApi(Build.VERSION_CODES.M) public void setStatusBarTextColor(Window window, boolean lightStatusBar) { if (window == null) return; View decor = window.getDecorView(); int ui = decor.getSystemUiVisibility(); if (lightStatusBar) { ui |= View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } else { ui &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR; } decor.setSystemUiVisibility(ui); } /** * 设置StatusBar的颜色 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setStatusBar(Window window, @ColorInt int color) { if (window == null) return; window.setStatusBarColor(color); } /** * 设置Dialog风格的Window的背景色 *

* 这个和设置StatusBar的颜色有区别的,它是设置一个Window背景色, * 这时StatusBar和Window的背景色保持一致,如果StatusBar下面的View背景色改变,会就盖住Window的背景色,界面就会丑陋, * 如果想做到沉浸式,除非将StatusBar下面的View的颜色和Window的背景色同时改变 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setDialogWindowStyle(Window window, @ColorInt int color) { if (window == null) return; window.setBackgroundDrawable(new ColorDrawable(color)); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR); window.addFlags(WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN); } /** * 设置Dialog风格的Window的StatusBar的颜色 *

* 这种实现方式是将原本在StatusBar下面的View,直接固定到屏幕最上面, * 这时StatusBar盖在View的上面,这时对View设置背景色,就像是沉浸式了 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setDialogWindowStyle2(Window window) { if (window == null) return; window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));//设置window背景色为透明色 setActivityWindowStyle(window); } /** * 设置Activity风格的Window的StatusBar的颜色 *

* 这种实现方式是将原本在StatusBar下面的View,直接固定到屏幕最上面, * 这时StatusBar盖在View的上面,如果这个View的背景设置的是一张图片,可以显示出很好的沉浸式效果。 * 如果View有图片,不要设置这个Window的属性,直接调用setStatusBar()方法 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setActivityWindowStyle(Window window) { if (window == null) return; window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION); } /** * 通过WindowManager来设置沉浸式状态 *

* 通过指定window的位置params.y来设置沉浸式, * 这里的params.height是WRAP_CONTENT,才有效果, * 如果是MATCH_PARENT会显示在最上面。 */ @TargetApi(Build.VERSION_CODES.LOLLIPOP) public void setWindowManagerStyle(final Window window, View view, boolean fullScreen) { if (window == null) return; WindowManager manager = window.getWindowManager(); WindowManager.LayoutParams params = window.getAttributes(); params.alpha = 1.0f; params.width = WindowManager.LayoutParams.MATCH_PARENT; params.height = fullScreen ? WindowManager.LayoutParams.MATCH_PARENT : WindowManager.LayoutParams.WRAP_CONTENT; params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN; params.type = WindowManager.LayoutParams.TYPE_SYSTEM_ALERT; params.format = PixelFormat.RGBA_8888; params.gravity = Gravity.START | Gravity.TOP; params.x = 0; params.y = fullScreen ? 0 : getStatusBarHeight(window.getContext()); manager.addView(view, params); } public int getStatusBarHeight(Context context) { // 获得状态栏高度 int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); return context.getResources().getDimensionPixelSize(resourceId); }}

ViewHelperUtils:对View操作控制的类

public class ViewHelperUtils {
private final static int RED = 0; private final static int YELLOW = 1; private final static int GREEN = 2; private final static int BLUE = 3; private final static int WHITE = 4; private final static int BLACK = 5; private static int color = RED; public static void click(Window window, TextView textView) { color++; StatusBarManager.getInstance().setStatusBarTextColor(window, false); textView.setTextColor(Color.WHITE); switch (color) { case RED: textView.setBackgroundColor(Color.RED); if (!window.isFloating()) { StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#dd0000")); } else { window.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#dd0000"))); } break; case YELLOW: textView.setBackgroundColor(Color.YELLOW); StatusBarManager.getInstance().setStatusBarTextColor(window, true); textView.setTextColor(Color.BLACK); if (!window.isFloating()) { StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#ffdd00")); } else { window.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#ffdd00"))); } break; case GREEN: textView.setBackgroundColor(Color.GREEN); if (!window.isFloating()) { StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#00dd00")); } else { window.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#00dd00"))); } break; case BLUE: textView.setBackgroundColor(Color.BLUE); if (!window.isFloating()) { StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#0000dd")); } else { window.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#0000dd"))); } break; case WHITE: textView.setBackgroundColor(Color.WHITE); StatusBarManager.getInstance().setStatusBarTextColor(window, true); textView.setTextColor(Color.BLACK); if (!window.isFloating()) { StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#ffffdd")); } else { window.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#ffffdd"))); } break; case BLACK: textView.setBackgroundColor(Color.BLACK); if (!window.isFloating()) { StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#333333")); } else { window.setBackgroundDrawable(new ColorDrawable(Color.parseColor("#333333"))); } color = -1; break; } } public static void setImageViewBitmap(ImageView imageView) { String path = Environment.getExternalStorageDirectory().getAbsolutePath(); path = path + "/1.jpg"; Bitmap bitmap = BitmapFactory.decodeFile(path); imageView.setImageBitmap(bitmap); }}

2. DialogFragment实现StatusBar的沉浸式

  • 方式一:
public class MutilDialogFragment extends DialogFragment {
public static MutilDialogFragment newInstance() { return new MutilDialogFragment(); } public static void showAdDialog(FragmentManager fragmentManager) { FragmentTransaction ft = fragmentManager.beginTransaction(); MutilDialogFragment prev = (MutilDialogFragment) fragmentManager.findFragmentByTag("dialog"); if (prev != null) { if (prev.isVisible()) { prev.dismiss(); } ft.remove(prev); } ft.addToBackStack(null); MutilDialogFragment adDialogFragment = MutilDialogFragment.newInstance(); adDialogFragment.show(ft, "dialog"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onStart() { super.onStart(); DisplayMetrics dm = new DisplayMetrics(); if (getActivity() != null) { getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); } Dialog dialog = getDialog(); if (dialog != null) { Window window = dialog.getWindow(); if (window != null) { //设置DialogFragment撑满屏幕 window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); } } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); //设置Dialog的Window样式或风格 StatusBarManager.getInstance().setDialogWindowStyle(getDialog().getWindow(), Color.parseColor("#dd0000")); View view = LayoutInflater.from(getActivity()).inflate(R.layout.activity_text, container); final TextView textView = (TextView) view.findViewById(R.id.image); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { ViewHelperUtils.click(getDialog().getWindow(), textView); } }); return view; }}
  • 方式二:
public class ImageDialogFragment extends DialogFragment {
public static ImageDialogFragment newInstance() { return new ImageDialogFragment(); } public static void showAdDialog(FragmentManager fragmentManager) { FragmentTransaction ft = fragmentManager.beginTransaction(); ImageDialogFragment prev = (ImageDialogFragment) fragmentManager.findFragmentByTag("dialog"); if (prev != null) { if (prev.isVisible()) { prev.dismiss(); } ft.remove(prev); } ft.addToBackStack(null); ImageDialogFragment adDialogFragment = ImageDialogFragment.newInstance(); adDialogFragment.show(ft, "dialog"); } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); } @Override public void onStart() { super.onStart(); DisplayMetrics dm = new DisplayMetrics(); if (getActivity() != null) { getActivity().getWindowManager().getDefaultDisplay().getMetrics(dm); } Dialog dialog = getDialog(); if (dialog != null) { Window window = dialog.getWindow(); if (window != null) { window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.MATCH_PARENT); } } } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { getDialog().requestWindowFeature(Window.FEATURE_NO_TITLE); StatusBarManager.getInstance().setDialogWindowStyle2(getDialog().getWindow()); View view = inflater.inflate(R.layout.common_image, container, false); ImageView imageView = (ImageView) view.findViewById(R.id.second_image); ViewHelperUtils.setImageViewBitmap(imageView); return view; }}

3. Window实现StatusBar的沉浸式

  • 方式一:
public void windowMutil(View view) {    final Window window = getWindow();    StatusBarManager.getInstance().setStatusBar(window, Color.parseColor("#dd0000"));    View v = LayoutInflater.from(getApplicationContext()).inflate(R.layout.activity_text2, null);    final TextView textView = (TextView) v.findViewById(R.id.text);    textView.setOnClickListener(new View.OnClickListener() {        @Override        public void onClick(View v) {            ViewHelperUtils.click(window, textView);        }    });    StatusBarManager.getInstance().setWindowManagerStyle(window, v, false);}
  • 方式二:
public void windowImage(View view) {    View v = LayoutInflater.from(getApplicationContext()).inflate(R.layout.common_image, null);    ImageView imageView = (ImageView) v.findViewById(R.id.second_image);    ViewHelperUtils.setImageViewBitmap(imageView);    StatusBarManager.getInstance().setWindowManagerStyle(getWindow(), v, true);}

转载地址:http://oesvn.baihongyu.com/

你可能感兴趣的文章
linux下卸载和安装mysql
查看>>
在初始化namenode时:java.net.NoRouteToHostException: 没有到主机的路由;
查看>>
hive-hbase
查看>>
浅谈scala-API的基础概念及简单例子
查看>>
spark的历史服务器配置
查看>>
spark的API操作
查看>>
SparkSql
查看>>
SparkRdd-scala版本
查看>>
spark常见算子
查看>>
scala符号初体验
查看>>
kafka生产者常用参数含义
查看>>
mysql编写函数
查看>>
面试笔试题之hql
查看>>
sql函数之cast()
查看>>
hql中substr函数截取字符串匹配
查看>>
mysql之指定ip、用户、数据库权限
查看>>
zookeeper的读和写数据流程(有图欧)
查看>>
bin/schematool -dbType mysql -initSchema HiveMetaException: Failed to get schema version.
查看>>
flink知识总结
查看>>
flink之检查点(checkpoint)和保存点(savepoint)的区别
查看>>