SlidingMenu实现沉浸式状态栏的终极办法




前段时间做项目 用到了因为SlidingMenu发现SlidingMenu无法实现沉浸式状态栏 当时项目时间紧张 没来的及研究源码 故只改了状态栏的颜色,今天有空在完善项目的时候 感觉只修改状态栏颜色是万万达不到想要的效果 故研究了下SlidingMenu的源码。看了源码才发现 要实现SlidingMenu沉浸式状态栏 只需要把SlidingMenu.java源码里的一个状态
修改下!

private boolean mActionbarOverlay = false;
修改为:

private boolean mActionbarOverlay = true;

这样 就可以实现沉浸式了!!!


附:加上与状态栏等高的空布局

获取状态栏高度:

[java] view plain copy
  1. /** 
  2.  * 获取状态栏高度 
  3.  * 
  4.  * @param context context 
  5.  * @return 状态栏高度 
  6.  */  
  7. public static int getStatusBarHeight(Context context) {  
  8.     int result = -1;  
  9.     int resourceId = context.getResources().getIdentifier("status_bar_height""dimen""android");  
  10.     if (resourceId > 0) {  
  11.         result = context.getResources().getDimensionPixelSize(resourceId);  
  12.     }  
  13.     return result;  
  14. }  


空布局是否显示的一些逻辑:

 
  
[java] view plain copy
  1. <span style="font-size:14px;">if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {  
  2.     Window window = getWindow();  
  3.     window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);  
  4.     // 改变titlebar的高度  
  5.     int statusbarHeight = BarUtils.getStatusBarHeight(this);  
  6.     com.lcworld.intelchargingpile.util.LogUtil.log("statusbarHeight:" + statusbarHeight);  
  7.     LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) tv_statusBar_slide.getLayoutParams();  
  8.     layoutParams.height = statusbarHeight;  
  9.     tv_statusBar_slide.setLayoutParams(layoutParams);  
  10.     RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) tv_statusBar_mian.getLayoutParams();  
  11.     layoutParams1.height = statusbarHeight;  
  12.     tv_statusBar_mian.setLayoutParams(layoutParams1);  
  13. else {  
  14.     tv_statusBar_mian.setVisibility(View.GONE);  
  15.     tv_statusBar_slide.setVisibility(View.GONE);  
  16. }</span>  

实现后的效果图:



/**********************2017.1.12补充*******************/


通过多款手机测试发现  屏幕有软菜单的话布局会以屏幕为ViewGroup,简单点说 底部的布局会显示不完全 被屏幕上的软菜单遮挡 , 那么单纯改掉这个bool值是不全面的 ,因为slidemenu此时默认用整个屏幕做的布局 !!!

如这款华为机子底部的button被遮挡在华为的软菜单下边:


在slidemenu.java 中attachToActivity(Activity activity, int slideStyle, boolean actionbarOverlay) 方法中slideStyle有两种显示方式 

一种是以window展示方式 ,另一种是以屏幕内容展示方式 。actionbarOverlay代表是否覆盖actionbar

 

[java] view plain copy
  1. if ((slideStyle != 0) && (slideStyle != 1)) {  
  2.            throw new IllegalArgumentException("slideStyle must be either SLIDING_WINDOW or SLIDING_CONTENT");  
  3.        }  
  4.   
  5.   
  6. f ((slideStyle != 0) && (slideStyle != 1)) {  
  7.            throw new IllegalArgumentException("slideStyle must be either SLIDING_WINDOW or SLIDING_CONTENT");  
  8.        }  



以window展示方式:


[java] view plain copy
  1. ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();  
  2. ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);  
  3.   
  4.   
  5. decorChild.setBackgroundResource(background);  
  6. decor.removeView(decorChild);  
  7. decor.addView(this);  
  8. setContent(decorChild);  




以屏幕内容展示方式:


[java] view plain copy
  1. ViewGroup contentParent = (ViewGroup) activity.findViewById(16908290);  
  2. View content = contentParent.getChildAt(0);  
  3. contentParent.removeView(content);  
  4. contentParent.addView(this);  
  5. setContent(content);  
[java] view plain copy
  1. if (content.getBackground() == null)  
  2.     content.setBackgroundResource(background);  







其中 actionbarOverlay最终决定的是是否要fitSystemWindows

[java] view plain copy
  1. @SuppressLint({"NewApi"})  
  2.   protected boolean fitSystemWindows(Rect insets) {  
  3.       int leftPadding = insets.left;  
  4.       int rightPadding = insets.right;  
  5.       int topPadding = insets.top;  
  6.       int bottomPadding = insets.bottom;  
  7.       if (!this.mActionbarOverlay) {  
  8.           Log.v("SlidingMenu""setting padding!");  
  9.           setPadding(leftPadding, topPadding, rightPadding, bottomPadding);  
  10.   
  11.   
  12.       }  
  13.       return true;  
  14.   }  



从源码里可以看到 我们要想做沉浸式状态栏 自然要将mActionbarOverlay设为true   
考虑到 不想被某些手机屏幕上的软菜单遮挡 布局的话  那么就得选用以屏幕内容展示方式
那么 我们可以把attachToActivity(Activity activity, int slideStyle, boolean actionbarOverlay) 的调用写成attachToActivity(activity, 1, true),那么这个方法是在哪里调用的呢?通过进一步查看源码 
 在SlidingActivityHelper.java中 

[java] view plain copy
  1. public void onPostCreate(Bundle savedInstanceState) {  
  2.       if ((this.mViewBehind == null) || (this.mViewAbove == null)) {  
  3.           throw new IllegalStateException("Both setBehindContentView must be called in onCreate in addition to setContentView.");  
  4.       }  
  5.   
  6.   
  7.       this.mOnPostCreateCalled = true;  
  8.   
  9.   
  10.       this.mSlidingMenu.attachToActivity(this.mActivity, this.mEnableSlide ? 0 : 1);  
  11.       final boolean secondary;  
  12.       final boolean open;  
  13.       if (savedInstanceState != null) {  
  14.           open = savedInstanceState.getBoolean("SlidingActivityHelper.open");  
  15.           secondary = savedInstanceState.getBoolean("SlidingActivityHelper.secondary");  
  16.       } else {  
  17.           open = false;  
  18.           secondary = false;  
  19.       }  
  20.       new Handler().post(new Runnable() {  
  21.           public void run() {  
  22.               if (open) {  
  23.                   if (secondary)  
  24.                       SlidingActivityHelper.this.mSlidingMenu.showSecondaryMenu(false);  
  25.                   else  
  26.                       SlidingActivityHelper.this.mSlidingMenu.showMenu(false);  
  27.               } else  
  28.                   SlidingActivityHelper.this.mSlidingMenu.showContent(false);  
  29.           }  
  30.       });  
  31.   }  

其中的
 this.mSlidingMenu.attachToActivity(this.mActivity, this.mEnableSlide ? 0 : 1);
改为 :
mEnableSlide=false;
 this.mSlidingMenu.attachToActivity(this.mActivity, this.mEnableSlide ? 0 : 1, true);
接下来运行项目测试一下 发现大功告成了 !!!!


/**************2017.02.16*************/

demo gif效果图:


源码下载地址:


https://github.com/xiaochenMate/ImmersiveSlideMenu

                                                                          SlidingMenu实现沉浸式状态栏的终极办法

1651人阅读 评论(3) 收藏 举报
分类:
Android (32)



前段时间做项目 用到了因为SlidingMenu发现SlidingMenu无法实现沉浸式状态栏 当时项目时间紧张 没来的及研究源码 故只改了状态栏的颜色,今天有空在完善项目的时候 感觉只修改状态栏颜色是万万达不到想要的效果 故研究了下SlidingMenu的源码。看了源码才发现 要实现SlidingMenu沉浸式状态栏 只需要把SlidingMenu.java源码里的一个状态
修改下!

private boolean mActionbarOverlay = false;
修改为:

private boolean mActionbarOverlay = true;

这样 就可以实现沉浸式了!!!


附:加上与状态栏等高的空布局

获取状态栏高度:

[java] view plain copy
  1. /** 
  2.  * 获取状态栏高度 
  3.  * 
  4.  * @param context context 
  5.  * @return 状态栏高度 
  6.  */  
  7. public static int getStatusBarHeight(Context context) {  
  8.     int result = -1;  
  9.     int resourceId = context.getResources().getIdentifier("status_bar_height""dimen""android");  
  10.     if (resourceId > 0) {  
  11.         result = context.getResources().getDimensionPixelSize(resourceId);  
  12.     }  
  13.     return result;  
  14. }  


空布局是否显示的一些逻辑:

 
    
[java] view plain copy
  1. <span style="font-size:14px;">if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {  
  2.     Window window = getWindow();  
  3.     window.setFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS, WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);  
  4.     // 改变titlebar的高度  
  5.     int statusbarHeight = BarUtils.getStatusBarHeight(this);  
  6.     com.lcworld.intelchargingpile.util.LogUtil.log("statusbarHeight:" + statusbarHeight);  
  7.     LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) tv_statusBar_slide.getLayoutParams();  
  8.     layoutParams.height = statusbarHeight;  
  9.     tv_statusBar_slide.setLayoutParams(layoutParams);  
  10.     RelativeLayout.LayoutParams layoutParams1 = (RelativeLayout.LayoutParams) tv_statusBar_mian.getLayoutParams();  
  11.     layoutParams1.height = statusbarHeight;  
  12.     tv_statusBar_mian.setLayoutParams(layoutParams1);  
  13. else {  
  14.     tv_statusBar_mian.setVisibility(View.GONE);  
  15.     tv_statusBar_slide.setVisibility(View.GONE);  
  16. }</span>  

实现后的效果图:



/**********************2017.1.12补充*******************/


通过多款手机测试发现  屏幕有软菜单的话布局会以屏幕为ViewGroup,简单点说 底部的布局会显示不完全 被屏幕上的软菜单遮挡 , 那么单纯改掉这个bool值是不全面的 ,因为slidemenu此时默认用整个屏幕做的布局 !!!

如这款华为机子底部的button被遮挡在华为的软菜单下边:


在slidemenu.java 中attachToActivity(Activity activity, int slideStyle, boolean actionbarOverlay) 方法中slideStyle有两种显示方式 

一种是以window展示方式 ,另一种是以屏幕内容展示方式 。actionbarOverlay代表是否覆盖actionbar

 

[java] view plain copy
  1. if ((slideStyle != 0) && (slideStyle != 1)) {  
  2.            throw new IllegalArgumentException("slideStyle must be either SLIDING_WINDOW or SLIDING_CONTENT");  
  3.        }  
  4.   
  5.   
  6. f ((slideStyle != 0) && (slideStyle != 1)) {  
  7.            throw new IllegalArgumentException("slideStyle must be either SLIDING_WINDOW or SLIDING_CONTENT");  
  8.        }  



以window展示方式:


[java] view plain copy
  1. ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();  
  2. ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);  
  3.   
  4.   
  5. decorChild.setBackgroundResource(background);  
  6. decor.removeView(decorChild);  
  7. decor.addView(this);  
  8. setContent(decorChild);  




以屏幕内容展示方式:


[java] view plain copy
  1. ViewGroup contentParent = (ViewGroup) activity.findViewById(16908290);  
  2. View content = contentParent.getChildAt(0);  
  3. contentParent.removeView(content);  
  4. contentParent.addView(this);  
  5. setContent(content);  
[java] view plain copy
  1. if (content.getBackground() == null)  
  2.     content.setBackgroundResource(background);  







其中 actionbarOverlay最终决定的是是否要fitSystemWindows

[java] view plain copy
  1. @SuppressLint({"NewApi"})  
  2.   protected boolean fitSystemWindows(Rect insets) {  
  3.       int leftPadding = insets.left;  
  4.       int rightPadding = insets.right;  
  5.       int topPadding = insets.top;  
  6.       int bottomPadding = insets.bottom;  
  7.       if (!this.mActionbarOverlay) {  
  8.           Log.v("SlidingMenu""setting padding!");  
  9.           setPadding(leftPadding, topPadding, rightPadding, bottomPadding);  
  10.   
  11.   
  12.       }  
  13.       return true;  
  14.   }  



从源码里可以看到 我们要想做沉浸式状态栏 自然要将mActionbarOverlay设为true   
考虑到 不想被某些手机屏幕上的软菜单遮挡 布局的话  那么就得选用以屏幕内容展示方式
那么 我们可以把attachToActivity(Activity activity, int slideStyle, boolean actionbarOverlay) 的调用写成attachToActivity(activity, 1, true),那么这个方法是在哪里调用的呢?通过进一步查看源码 
 在SlidingActivityHelper.java中 

[java] view plain copy
  1. public void onPostCreate(Bundle savedInstanceState) {  
  2.       if ((this.mViewBehind == null) || (this.mViewAbove == null)) {  
  3.           throw new IllegalStateException("Both setBehindContentView must be called in onCreate in addition to setContentView.");  
  4.       }  
  5.   
  6.   
  7.       this.mOnPostCreateCalled = true;  
  8.   
  9.   
  10.       this.mSlidingMenu.attachToActivity(this.mActivity, this.mEnableSlide ? 0 : 1);  
  11.       final boolean secondary;  
  12.       final boolean open;  
  13.       if (savedInstanceState != null) {  
  14.           open = savedInstanceState.getBoolean("SlidingActivityHelper.open");  
  15.           secondary = savedInstanceState.getBoolean("SlidingActivityHelper.secondary");  
  16.       } else {  
  17.           open = false;  
  18.           secondary = false;  
  19.       }  
  20.       new Handler().post(new Runnable() {  
  21.           public void run() {  
  22.               if (open) {  
  23.                   if (secondary)  
  24.                       SlidingActivityHelper.this.mSlidingMenu.showSecondaryMenu(false);  
  25.                   else  
  26.                       SlidingActivityHelper.this.mSlidingMenu.showMenu(false);  
  27.               } else  
  28.                   SlidingActivityHelper.this.mSlidingMenu.showContent(false);  
  29.           }  
  30.       });  
  31.   }  

其中的
 this.mSlidingMenu.attachToActivity(this.mActivity, this.mEnableSlide ? 0 : 1);
改为 :
mEnableSlide=false;
 this.mSlidingMenu.attachToActivity(this.mActivity, this.mEnableSlide ? 0 : 1, true);
接下来运行项目测试一下 发现大功告成了 !!!!


/**************2017.02.16*************/

demo gif效果图:


源码下载地址:


https://github.com/xiaochenMate/ImmersiveSlideMenu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值