map = mBarParams.viewMap.get(view);
404 | if (map.size() != 0) {
405 | mBarParams.viewMap.remove(view);
406 | }
407 | }
408 | return this;
409 | }
410 |
411 | /**
412 | * Remove support all view immersion bar.
413 | *
414 | * @return the immersion bar
415 | */
416 | public ImmersionBar removeSupportAllView() {
417 | if (mBarParams.viewMap.size() != 0) {
418 | mBarParams.viewMap.clear();
419 | }
420 | return this;
421 | }
422 |
423 | /**
424 | * 有导航栏的情况下,Activity是否全屏显示
425 | *
426 | * @param isFullScreen the is full screen
427 | * @return the immersion bar
428 | */
429 | public ImmersionBar fullScreen(boolean isFullScreen) {
430 | mBarParams.fullScreen = isFullScreen;
431 | return this;
432 | }
433 |
434 | /**
435 | * 状态栏透明度
436 | *
437 | * @param statusAlpha the status alpha
438 | * @return the immersion bar
439 | */
440 | public ImmersionBar statusBarAlpha(@FloatRange(from = 0f, to = 1f) float statusAlpha) {
441 | mBarParams.statusBarAlpha = statusAlpha;
442 | return this;
443 | }
444 |
445 | /**
446 | * 导航栏透明度
447 | *
448 | * @param navigationAlpha the navigation alpha
449 | * @return the immersion bar
450 | */
451 | public ImmersionBar navigationBarAlpha(@FloatRange(from = 0f, to = 1f) float navigationAlpha) {
452 | mBarParams.navigationBarAlpha = navigationAlpha;
453 | return this;
454 | }
455 |
456 | /**
457 | * 状态栏和导航栏透明度
458 | *
459 | * @param barAlpha the bar alpha
460 | * @return the immersion bar
461 | */
462 | public ImmersionBar barAlpha(@FloatRange(from = 0f, to = 1f) float barAlpha) {
463 | mBarParams.statusBarAlpha = barAlpha;
464 | mBarParams.navigationBarAlpha = barAlpha;
465 | return this;
466 | }
467 |
468 | /**
469 | * 状态栏字体深色或亮色
470 | *
471 | * @param isDarkFont true 深色
472 | * @return the immersion bar
473 | */
474 | public ImmersionBar statusBarDarkFont(boolean isDarkFont) {
475 | mBarParams.darkFont = isDarkFont;
476 | return this;
477 | }
478 |
479 | /**
480 | * 隐藏导航栏或状态栏
481 | *
482 | * @param barHide the bar hide
483 | * @return the immersion bar
484 | */
485 | public ImmersionBar hideBar(BarHide barHide) {
486 | mBarParams.barHide = barHide;
487 | if (Build.VERSION.SDK_INT == Build.VERSION_CODES.KITKAT) {
488 | if ((mBarParams.barHide == BarHide.FLAG_HIDE_NAVIGATION_BAR) ||
489 | (mBarParams.barHide == BarHide.FLAG_HIDE_BAR)) {
490 | mBarParams.navigationBarColor = Color.TRANSPARENT;
491 | mBarParams.fullScreenTemp = true;
492 | } else {
493 | mBarParams.navigationBarColor = mBarParams.navigationBarColorTem;
494 | mBarParams.fullScreenTemp = false;
495 | }
496 | }
497 | return this;
498 | }
499 |
500 | /**
501 | * 解决布局与状态栏重叠问题
502 | *
503 | * @param fits the fits
504 | * @return the immersion bar
505 | */
506 | public ImmersionBar fitsSystemWindows(boolean fits) {
507 | mBarParams.fits = fits;
508 | return this;
509 | }
510 |
511 | /**
512 | * 通过状态栏高度动态设置状态栏布局
513 | *
514 | * @param view the view
515 | * @return the immersion bar
516 | */
517 | public ImmersionBar statusBarView(View view) {
518 | mBarParams.statusBarViewByHeight = view;
519 | return this;
520 | }
521 |
522 | /**
523 | * 通过状态栏高度动态设置状态栏布局,只支持在activity里设置
524 | *
525 | * @param viewId the view id
526 | * @return the immersion bar
527 | */
528 | @SuppressWarnings("ResourceType")
529 | public ImmersionBar statusBarView(@IntegerRes int viewId) {
530 | mBarParams.statusBarViewByHeight = mActivity.findViewById(viewId);
531 | return this;
532 | }
533 |
534 | /**
535 | * 通过上面配置后初始化后方可成功调用
536 | */
537 | public void init() {
538 | mMap.put(mActivity.getClass().getName(), mBarParams);
539 | initBar(); //初始化沉浸式
540 | setStatusBarView(); //通过状态栏高度动态设置状态栏布局
541 | fitsSystemWindows(); //解决状态栏和布局重叠问题
542 | transformView(); //变色view
543 | }
544 |
545 | /**
546 | * 当Activity关闭的时候,在onDestroy方法中调用
547 | */
548 | public void destroy() {
549 | String key = mActivity.getClass().getName();
550 | if (key != null) {
551 | if (mBarParams != null) {
552 | mBarParams = null;
553 | }
554 | mMap.remove(key);
555 | }
556 | }
557 |
558 | private void initBar() {
559 | int uiFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE; //防止系统栏隐藏时内容区域大小发生变化
560 | uiFlags = hideBar(uiFlags); //隐藏状态栏或者导航栏
561 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
562 | uiFlags = setStatusBarDarkFont(uiFlags); //设置状态栏字体为暗色
563 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
564 | uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; //Activity全屏显示,但状态栏不会被隐藏覆盖,状态栏依然可见,Activity顶端布局部分会被状态栏遮住。
565 | if (mBarParams.fullScreen) {
566 | uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION; //Activity全屏显示,但导航栏不会被隐藏覆盖,导航栏依然可见,Activity底部布局部分会被导航栏遮住。
567 | }
568 | mWindow.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS
569 | | WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION); //取消设置透明状态栏和导航栏
570 | mWindow.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); //需要设置这个才能设置状态栏颜色
571 | mWindow.setStatusBarColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
572 | mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha)); //设置状态栏颜色
573 | mWindow.setNavigationBarColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
574 | mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha)); //设置导航栏颜色
575 | } else {
576 | mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);//透明状态栏
577 | mWindow.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);//透明导航栏,设置这个,如果有导航栏,底部布局会被导航栏遮住
578 | setupStatusBarView(); //创建一个假的状态栏
579 | if (mConfig.hasNavigtionBar()) //判断是否存在导航栏
580 | setupNavBarView(); //创建一个假的导航栏
581 |
582 | // 解决android4.4有导航栏的情况下,activity底部被导航栏遮挡的问题
583 | if (mConfig.hasNavigtionBar() && !mBarParams.fullScreenTemp && !mBarParams.fullScreen) {
584 | if (mConfig.isNavigationAtBottom()) //判断导航栏是否在底部
585 | mContentView.setPadding(0, 0, 0, mConfig.getNavigationBarHeight()); //有导航栏,获得rootView的根节点,然后设置距离底部的padding值为导航栏的高度值
586 | else
587 | mContentView.setPadding(0, 0, mConfig.getNavigationBarWidth(), 0); //不在底部,设置距离右边的padding值为导航栏的宽度值
588 | } else {
589 | mContentView.setPadding(0, 0, 0, 0); //没有导航栏,什么都不做
590 | }
591 | }
592 | }
593 | mWindow.getDecorView().setSystemUiVisibility(uiFlags);
594 | }
595 |
596 | /**
597 | * Hide bar.
598 | * 隐藏或显示状态栏和导航栏。 状态栏和导航栏的颜色不起作用,都是透明色,以最后一次调用为准
599 | *
600 | * @param uiFlags the ui flags
601 | * @return the int
602 | */
603 | private int hideBar(int uiFlags) {
604 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
605 | switch (mBarParams.barHide) {
606 | case FLAG_HIDE_BAR:
607 | uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
608 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
609 | | View.INVISIBLE;
610 | break;
611 | case FLAG_HIDE_STATUS_BAR:
612 | uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.INVISIBLE;
613 | break;
614 | case FLAG_HIDE_NAVIGATION_BAR:
615 | uiFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
616 | | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
617 | break;
618 | case FLAG_SHOW_BAR:
619 | uiFlags |= View.SYSTEM_UI_FLAG_VISIBLE;
620 | break;
621 | }
622 | }
623 | return uiFlags | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
624 | }
625 |
626 | /**
627 | * Sets status bar dark font.
628 | * 设置状态栏字体颜色,android6.0以上或者miuiv6以上或者flymeOS
629 | */
630 | private int setStatusBarDarkFont(int uiFlags) {
631 | String MIUIVersion = OSUtils.MIUIVersion();
632 | if (!MIUIVersion.isEmpty()) {
633 | if (Integer.valueOf(MIUIVersion.substring(1)) >= 6) {
634 | MIUISetStatusBarLightMode();
635 | }
636 | return uiFlags;
637 | }
638 | if (OSUtils.isFlymeOS()) {
639 | flymeSetStatusBarLightMode();
640 | return uiFlags;
641 | }
642 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && mBarParams.darkFont) {
643 | return uiFlags | View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
644 | } else {
645 | return uiFlags | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
646 | }
647 | }
648 |
649 | /**
650 | * 设置状态栏图标为深色和魅族特定的文字风格
651 | * 可以用来判断是否为Flyme用户
652 | *
653 | * @return boolean 成功执行返回true
654 | */
655 | private boolean flymeSetStatusBarLightMode() {
656 | boolean result = false;
657 | if (mWindow != null) {
658 | try {
659 | WindowManager.LayoutParams lp = mWindow.getAttributes();
660 | Field darkFlag = WindowManager.LayoutParams.class
661 | .getDeclaredField("MEIZU_FLAG_DARK_STATUS_BAR_ICON");
662 | Field meizuFlags = WindowManager.LayoutParams.class
663 | .getDeclaredField("meizuFlags");
664 | darkFlag.setAccessible(true);
665 | meizuFlags.setAccessible(true);
666 | int bit = darkFlag.getInt(null);
667 | int value = meizuFlags.getInt(lp);
668 | if (mBarParams.darkFont) {
669 | value |= bit;
670 | } else {
671 | value &= ~bit;
672 | }
673 | meizuFlags.setInt(lp, value);
674 | mWindow.setAttributes(lp);
675 | result = true;
676 | } catch (Exception e) {
677 | e.printStackTrace();
678 | }
679 | }
680 | return result;
681 | }
682 |
683 | /**
684 | * 设置状态栏字体图标为深色,需要MIUIV6以上
685 | *
686 | * @return boolean 成功执行返回true
687 | */
688 | private boolean MIUISetStatusBarLightMode() {
689 | boolean result = false;
690 | if (mWindow != null) {
691 | Class clazz = mWindow.getClass();
692 | try {
693 | int darkModeFlag = 0;
694 | Class layoutParams = Class.forName("android.view.MiuiWindowManager$LayoutParams");
695 | Field field = layoutParams.getField("EXTRA_FLAG_STATUS_BAR_DARK_MODE");
696 | darkModeFlag = field.getInt(layoutParams);
697 | Method extraFlagField = clazz.getMethod("setExtraFlags", int.class, int.class);
698 | if (mBarParams.darkFont) {
699 | extraFlagField.invoke(mWindow, darkModeFlag, darkModeFlag);//状态栏透明且黑色字体
700 | } else {
701 | extraFlagField.invoke(mWindow, 0, darkModeFlag);//清除黑色字体
702 | }
703 | result = true;
704 | } catch (Exception e) {
705 | e.printStackTrace();
706 | }
707 | }
708 | return result;
709 | }
710 |
711 | /**
712 | * 变色view
713 | *
714 | * Transform view.
715 | */
716 | private void transformView() {
717 | if (mBarParams.view != null) {
718 | mBarParams.view.setBackgroundColor(ColorUtils.blendARGB(mBarParams.viewColorBeforeTransform,
719 | mBarParams.viewColorAfterTransform, mBarParams.statusBarAlpha));
720 | }
721 | if (mBarParams.viewMap.size() != 0) {
722 | Set>> entrySet = mBarParams.viewMap.entrySet();
723 | for (Map.Entry> entry : entrySet) {
724 | View view = entry.getKey();
725 | Map map = entry.getValue();
726 | Integer colorBefore = mBarParams.statusBarColor;
727 | Integer colorAfter = mBarParams.statusBarColorTransform;
728 | for (Map.Entry integerEntry : map.entrySet()) {
729 | colorBefore = integerEntry.getKey();
730 | colorAfter = integerEntry.getValue();
731 | }
732 | if (view != null)
733 | view.setBackgroundColor(ColorUtils.blendARGB(colorBefore, colorAfter, mBarParams.statusBarAlpha));
734 |
735 | }
736 | }
737 | }
738 |
739 |
740 | /**
741 | * 通过状态栏高度动态设置状态栏布局
742 | */
743 | private void setStatusBarView() {
744 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && mBarParams.statusBarViewByHeight != null) {
745 | ViewGroup.LayoutParams params = mBarParams.statusBarViewByHeight.getLayoutParams();
746 | params.height = mConfig.getStatusBarHeight();
747 | mBarParams.statusBarViewByHeight.setLayoutParams(params);
748 | }
749 | mBarParams.statusBarViewByHeight = null;
750 | }
751 |
752 | /**
753 | * 解决状态栏和布局重叠问题
754 | * Fits system windows.
755 | */
756 | private void fitsSystemWindows() {
757 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
758 | if (mBarParams.fits) {
759 | mContentView.setPadding(0, getStatusBarHeight(mActivity), 0, 0);
760 | } else {
761 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
762 | mContentView.setPadding(0, 0, 0, 0);
763 | }
764 | }
765 | }
766 |
767 | /**
768 | * 设置一个可以自定义颜色的状态栏
769 | */
770 | private void setupStatusBarView() {
771 | if (mBarParams.statusBarView == null) {
772 | mBarParams.statusBarView = new View(mActivity);
773 | }
774 | FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getStatusBarHeight(mActivity));
775 | params.gravity = Gravity.TOP;
776 | if (!isNavigationAtBottom(mActivity)) {
777 | params.rightMargin = getNavigationBarWidth(mActivity);
778 | }
779 | mBarParams.statusBarView.setLayoutParams(params);
780 | mBarParams.statusBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.statusBarColor,
781 | mBarParams.statusBarColorTransform, mBarParams.statusBarAlpha));
782 | mBarParams.statusBarView.setVisibility(View.VISIBLE);
783 | ViewGroup viewGroup = (ViewGroup) mBarParams.statusBarView.getParent();
784 | if (viewGroup != null)
785 | viewGroup.removeView(mBarParams.statusBarView);
786 | mViewGroup.addView(mBarParams.statusBarView);
787 | }
788 |
789 | /**
790 | * 设置一个可以自定义颜色的导航栏
791 | */
792 | private void setupNavBarView() {
793 | if (mBarParams.navigationBarView == null) {
794 | mBarParams.navigationBarView = new View(mActivity);
795 | }
796 | FrameLayout.LayoutParams params;
797 | if (isNavigationAtBottom(mActivity)) {
798 | params = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, getNavigationBarHeight(mActivity));
799 | params.gravity = Gravity.BOTTOM;
800 | } else {
801 | params = new FrameLayout.LayoutParams(getNavigationBarWidth(mActivity), FrameLayout.LayoutParams.MATCH_PARENT);
802 | params.gravity = Gravity.END;
803 | }
804 | mBarParams.navigationBarView.setLayoutParams(params);
805 | if (!mBarParams.fullScreen && (mBarParams.navigationBarColorTransform == Color.TRANSPARENT)) {
806 | mBarParams.navigationBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
807 | Color.BLACK, mBarParams.navigationBarAlpha));
808 | } else {
809 | mBarParams.navigationBarView.setBackgroundColor(ColorUtils.blendARGB(mBarParams.navigationBarColor,
810 | mBarParams.navigationBarColorTransform, mBarParams.navigationBarAlpha));
811 | }
812 | mBarParams.navigationBarView.setVisibility(View.VISIBLE);
813 | ViewGroup viewGroup = (ViewGroup) mBarParams.navigationBarView.getParent();
814 | if (viewGroup != null)
815 | viewGroup.removeView(mBarParams.navigationBarView);
816 | mViewGroup.addView(mBarParams.navigationBarView);
817 | }
818 |
819 | /**
820 | * Has navigtion bar boolean.
821 | * 判断是否存在导航栏
822 | *
823 | * @param activity the activity
824 | * @return the boolean
825 | */
826 | @TargetApi(14)
827 | public static boolean hasNavigationBar(Activity activity) {
828 | BarConfig config = new BarConfig(activity);
829 | return config.hasNavigtionBar();
830 | }
831 |
832 | /**
833 | * Gets navigation bar height.
834 | * 获得导航栏的高度
835 | *
836 | * @param activity the activity
837 | * @return the navigation bar height
838 | */
839 | @TargetApi(14)
840 | public static int getNavigationBarHeight(Activity activity) {
841 | BarConfig config = new BarConfig(activity);
842 | return config.getNavigationBarHeight();
843 | }
844 |
845 | /**
846 | * Gets navigation bar width.
847 | * 获得导航栏的宽度
848 | *
849 | * @param activity the activity
850 | * @return the navigation bar width
851 | */
852 | @TargetApi(14)
853 | public static int getNavigationBarWidth(Activity activity) {
854 | BarConfig config = new BarConfig(activity);
855 | return config.getNavigationBarWidth();
856 | }
857 |
858 | /**
859 | * Is navigation at bottom boolean.
860 | * 判断导航栏是否在底部
861 | *
862 | * @param activity the activity
863 | * @return the boolean
864 | */
865 | @TargetApi(14)
866 | public static boolean isNavigationAtBottom(Activity activity) {
867 | BarConfig config = new BarConfig(activity);
868 | return config.isNavigationAtBottom();
869 | }
870 |
871 | /**
872 | * Gets status bar height.
873 | * 或得状态栏的高度
874 | *
875 | * @param activity the activity
876 | * @return the status bar height
877 | */
878 | @TargetApi(14)
879 | public static int getStatusBarHeight(Activity activity) {
880 | BarConfig config = new BarConfig(activity);
881 | return config.getStatusBarHeight();
882 | }
883 |
884 | /**
885 | * Gets action bar height.
886 | * 或得ActionBar得高度
887 | *
888 | * @param activity the activity
889 | * @return the action bar height
890 | */
891 | @TargetApi(14)
892 | public static int getActionBarHeight(Activity activity) {
893 | BarConfig config = new BarConfig(activity);
894 | return config.getActionBarHeight();
895 | }
896 |
897 | /**
898 | * Gets bar params.
899 | *
900 | * @return the bar params
901 | */
902 | public BarParams getBarParams() {
903 | return mBarParams;
904 | }
905 | }
906 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wkz/hover/immersionbar/ImmersionFragment.java:
--------------------------------------------------------------------------------
1 | package com.wkz.hover.immersionbar;
2 |
3 | import android.support.v4.app.Fragment;
4 |
5 | /**
6 | * ImmersionFragment沉浸式基类,因为fragment是基于activity之上的,
7 | * 为了能够在fragment使用沉浸式而fragment之间又相互不影响,必须实现immersionInit方法,
8 | * 原理是当用户可见才执行沉浸式初始化
9 | *
10 | * Created by geyifeng on 2017/5/12.
11 | */
12 | public abstract class ImmersionFragment extends Fragment {
13 | @Override
14 | public void setUserVisibleHint(boolean isVisibleToUser) {
15 | super.setUserVisibleHint(isVisibleToUser);
16 | if ((isVisibleToUser && isResumed())) {
17 | onResume();
18 | }
19 | }
20 |
21 | @Override
22 | public void onResume() {
23 | super.onResume();
24 | if (getUserVisibleHint()) {
25 | immersionInit();
26 | }
27 | }
28 |
29 | protected abstract void immersionInit();
30 | }
31 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wkz/hover/immersionbar/KeyboardPatch.java:
--------------------------------------------------------------------------------
1 | package com.wkz.hover.immersionbar;
2 |
3 | import android.app.Activity;
4 | import android.graphics.Rect;
5 | import android.os.Build;
6 | import android.view.View;
7 | import android.view.ViewTreeObserver;
8 | import android.view.WindowManager;
9 |
10 | /**
11 | * 解决EditText和软键盘的问题
12 | * Created by geyifeng on 2017/5/17.
13 | */
14 |
15 | public class KeyboardPatch {
16 | private Activity mActivity;
17 | private View mDecorView;
18 | private View mContentView;
19 |
20 |
21 | private KeyboardPatch() {
22 | }
23 |
24 | /**
25 | * 构造函数
26 | *
27 | * @param activity 需要解决bug的activity
28 | * @param contentView 界面容器,如果使用ImmersionBar这个库,对于android 5.0来说,在activity中一般是R.id.content
29 | * ,也可能是Fragment的容器,根据个人需要传递,为了方便指定布局的根节点就行
30 | */
31 | private KeyboardPatch(Activity activity, View contentView) {
32 | this.mActivity = activity;
33 | this.mDecorView = activity.getWindow().getDecorView();
34 | this.mContentView = contentView;
35 | }
36 |
37 | public static KeyboardPatch patch(Activity activity, View contentView) {
38 | return new KeyboardPatch(activity, contentView);
39 | }
40 |
41 | /**
42 | * 监听layout变化
43 | */
44 | public void enable() {
45 | mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
46 | | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE);
47 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
48 | mDecorView.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener);//当在一个视图树中全局布局发生改变或者视图树中的某个视图的可视状态发生改变时,所要调用的回调函数的接口类
49 | }
50 | }
51 |
52 | /**
53 | * 取消监听
54 | */
55 | public void disable() {
56 | mActivity.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN
57 | | WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
58 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
59 | mDecorView.getViewTreeObserver().removeOnGlobalLayoutListener(onGlobalLayoutListener);
60 | }
61 | }
62 |
63 | private ViewTreeObserver.OnGlobalLayoutListener onGlobalLayoutListener = new ViewTreeObserver.OnGlobalLayoutListener() {
64 | @Override
65 | public void onGlobalLayout() {
66 | Rect r = new Rect();
67 | mDecorView.getWindowVisibleDisplayFrame(r); //获取当前窗口可视区域大小的
68 | int height = mDecorView.getContext().getResources().getDisplayMetrics().heightPixels; //获取屏幕密度,不包含导航栏
69 | int diff = height - r.bottom;
70 | if (diff > 0) {
71 | if (mContentView.getPaddingBottom() != diff) {
72 | mContentView.setPadding(0, 0, 0, diff);
73 | }
74 | } else {
75 | if (mContentView.getPaddingBottom() != 0) {
76 | mContentView.setPadding(0, 0, 0, 0);
77 | }
78 | }
79 | }
80 | };
81 | }
82 |
--------------------------------------------------------------------------------
/app/src/main/java/com/wkz/hover/immersionbar/OSUtils.java:
--------------------------------------------------------------------------------
1 | package com.wkz.hover.immersionbar;
2 |
3 | import android.text.TextUtils;
4 |
5 | import java.lang.reflect.Method;
6 |
7 | /**
8 | * Created by geyifeng on 2017/4/18.
9 | */
10 |
11 | public class OSUtils {
12 |
13 | private static final String KEY_MIUI_VERSION_NAME = "ro.miui.ui.version.name";
14 | private static final String KEY_EMUI_VERSION_NAME = "ro.build.version.emui";
15 | private static final String KEY_DISPLAY = "ro.build.display.id";
16 |
17 | public static String MIUIVersion() {
18 | return isMIUI() ? getSystemProperty(KEY_MIUI_VERSION_NAME, null) : "";
19 | }
20 |
21 | public static boolean isMIUI() {
22 | String property = getSystemProperty(KEY_MIUI_VERSION_NAME, null);
23 | return !TextUtils.isEmpty(property);
24 | }
25 |
26 | public static boolean isFlymeOS() {
27 | return getMeizuFlymeOSFlag().toLowerCase().contains("flyme");
28 | }
29 |
30 | public static boolean isEMUI() {
31 | String property = getSystemProperty(KEY_EMUI_VERSION_NAME, null);
32 | return !TextUtils.isEmpty(property);
33 | }
34 |
35 | public static boolean isEMUI3_1() {
36 | if ("EmotionUI_3.1".equals(getSystemProperty(KEY_EMUI_VERSION_NAME, null))) {
37 | return true;
38 | }
39 | return false;
40 | }
41 |
42 | public static String getMeizuFlymeOSFlag() {
43 | return getSystemProperty(KEY_DISPLAY, "");
44 | }
45 |
46 | private static String getSystemProperty(String key, String defaultValue) {
47 | try {
48 | Class> clz = Class.forName("android.os.SystemProperties");
49 | Method get = clz.getMethod("get", String.class, String.class);
50 | return (String) get.invoke(clz, key, defaultValue);
51 | } catch (Exception e) {
52 | e.printStackTrace();
53 | }
54 | return defaultValue;
55 | }
56 |
57 |
58 | private static String getEmuiVersion() {
59 | Class> classType;
60 | try {
61 | classType = Class.forName("android.os.SystemProperties");
62 | Method getMethod = classType.getDeclaredMethod("get", String.class);
63 | return (String) getMethod.invoke(classType, "ro.build.version.emui");
64 | } catch (Exception e) {
65 | e.printStackTrace();
66 | }
67 | return "";
68 | }
69 |
70 | }
71 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
12 |
13 |
19 |
22 |
25 |
26 |
27 |
28 |
34 |
35 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_arrow_left.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_more.xml:
--------------------------------------------------------------------------------
1 |
6 |
12 |
18 |
24 |
25 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
13 |
14 |
18 |
19 |
22 |
23 |
31 |
32 |
41 |
42 |
52 |
53 |
67 |
68 |
69 |
78 |
79 |
83 |
84 |
93 |
94 |
104 |
105 |
115 |
116 |
117 |
118 |
119 |
120 |
125 |
126 |
135 |
136 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fragment_test.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
11 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/item_recycler.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/pic_image.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/app/src/main/res/mipmap-xxxhdpi/pic_image.webp
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #008577
4 | #00574B
5 | #D81B60
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | HoverToolbarTabLayout
3 |
4 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/src/test/java/com/wkz/hover/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wkz.hover;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | apply from: 'config/config.gradle'
2 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
3 |
4 | buildscript {
5 | repositories {
6 | google()
7 | jcenter()
8 |
9 | }
10 | dependencies {
11 | classpath 'com.android.tools.build:gradle:3.4.1'
12 |
13 | // NOTE: Do not place your application dependencies here; they belong
14 | // in the individual module build.gradle files
15 | }
16 | }
17 |
18 | allprojects {
19 | repositories {
20 | google()
21 | jcenter()
22 |
23 | }
24 | }
25 |
26 | task clean(type: Delete) {
27 | delete rootProject.buildDir
28 | }
29 |
--------------------------------------------------------------------------------
/config/config.gradle:
--------------------------------------------------------------------------------
1 | ext {
2 |
3 | android = [
4 | compileSdkVersion: 28,
5 | buildToolsVersion: "28.0.3",
6 | minSdkVersion : 17,
7 | targetSdkVersion : 28,
8 | ]
9 |
10 | dependenceVersion = [
11 | support: "28.0.0",
12 | ]
13 |
14 | support = [
15 | supportv4 : "com.android.support:support-v4:$dependenceVersion.support",
16 | appcompat : "com.android.support:appcompat-v7:$dependenceVersion.support",
17 | design : "com.android.support:design:$dependenceVersion.support",
18 | recyclerview: "com.android.support:recyclerview-v7:$dependenceVersion.support",
19 | cardview : "com.android.support:cardview-v7:$dependenceVersion.support",
20 | ]
21 |
22 | /*依赖这个,相当于依赖support下所有项*/
23 | supportLibs = support.values()
24 | }
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 | # IDE (e.g. Android Studio) users:
3 | # Gradle settings configured through the IDE *will override*
4 | # any settings specified in this file.
5 | # For more details on how to configure your build environment visit
6 | # http://www.gradle.org/docs/current/userguide/build_environment.html
7 | # Specifies the JVM arguments used for the daemon process.
8 | # The setting is particularly useful for tweaking memory settings.
9 | org.gradle.jvmargs=-Xmx1536m
10 | # When configured, Gradle will run in incubating parallel mode.
11 | # This option should only be used with decoupled projects. More details, visit
12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
13 | # org.gradle.parallel=true
14 | # AndroidX package structure to make it clearer which packages are bundled with the
15 | # Android operating system, and which are packaged with your app's APK
16 | # https://developer.android.com/topic/libraries/support-library/androidx-rn
17 | #android.useAndroidX=true
18 | # Automatically convert third-party libraries to use AndroidX
19 | #android.enableJetifier=true
20 |
21 |
--------------------------------------------------------------------------------
/preview/hover.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FPhoenixCorneaE/HoverToolbarTabLayout/64b75c5e9a615b740c18a8cb2ff069824cd6db2a/preview/hover.gif
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------