rendering

Analysis of the

  • Drop-down refresh Sets the status bar mode according to the drop-down distance.
  • Change TopBar background color and status bar mode according to sliding distance.
  • After switching to the classification interface, change the status bar to the required mode of the classification interface.
  • When switching back to the home screen, you will revert to the previous mode.

The first two points are easy to implement. The third point can be set according to the classification interface (or other interface). The key is number four: when the home page is displayed again, switch back to the mode it should be based on its state.

isLightMode

On the home page, after every pull-down refresh or sliding to change the mode of the status bar, we use this variable to record the mode, and use this variable to judge the display when we switch to another interface.

implementation

The analysis above all has the same word: when the interface is displayed. Then change the mode of the status bar.

We’ve all been exposed to the lazy loading mode of Fragments:

private boolean isFirstInit = true; public void onLazyResume(){ if(isFirstInit){ onLazyInit(); } } public void onLazyInit(){ isFirstInit = false; // lazy loading code}Copy the code

Similarly, we can place the status bar toggle on display

/** * private Boolean isLightMode; public void onLazyResume(){ updateStatusBarMode(isLightMode); . } /** * protected void updateStatusBarMode(Boolean isLightMode) {if (isLight) { QMUIStatusBarHelper.setStatusBarLightMode(getBaseFragmentActivity()); } else { QMUIStatusBarHelper.setStatusBarDarkMode(getBaseFragmentActivity()); }}Copy the code

This will show the correct status bar mode according to isLightMode every time it is displayed.

encapsulation

There’s a problem with the above analysis:

  • What should the isLightMode default be?

Since this is global encapsulation, what is the most common layout?

  • TopBar + content layer

So we directly take the background color of TopBar as a judgment

/** * Set TopBar to a white background Public class StatusBarUtil {public static Boolean isWhiteBg(View View) {if (null == View) return false; int bgColor; try { bgColor = QMUISkinHelper.getSkinColor(view, R.attr.qmui_skin_support_topbar_bg); } catch (Exception e) { bgColor = Color.WHITE; } return bgColor == color.white; }}Copy the code

This is only a default value. If it needs to be changed dynamically as above, then we need to change the above method to:

*/ protected Boolean isStatusBarLightMode() {return StatusBarUtil.isWhiteBg(mRootView); } public void onLazyResume() { updateStatusBarMode(isStatusBarLightMode()); }Copy the code

A subclass records a variable

  • isLightMode

Override the isStatusBarLightMode method to return this variable:

    @Override
    protected boolean isStatusBarLightMode() {
        return isLightMode;
    }
Copy the code

But it’s not possible to call this method every time every Fragment appears when the interface above appears:

  • Fragment: ViewPager+TabLayout
  • ItemFragment: It may be a home page that needs to be changed, it may be a category that contains ViewPager, or it may be normal.

After all, there are very few cases like this. We only take the basic case, where only the root Fragment has the permission to change the status bar, and the rest (such as those in the ViewPager) are its child fragments. If a small number of cases occur, subclasses override the above method and solve the problem themselves.

So here comes the question:

  • How do you tell if it’s a root Fragment?
/** * whether the Fragment is root Fragment */ protected Boolean isIndexFragment = false;Copy the code

Where are sub-fragments used?

  • ViewPager?
    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        isIndexFragment = container instanceof ViewPager;
        return super.onCreateView(inflater, container, savedInstanceState);
    }
Copy the code

Yes, its parent is ViewPager, which is fine. But there is another case where ViewPager is useless:

  • Wrap it with layout and click to switch

That’s not uncommon. And here’s another one:

  • Embed directly as part of the layout (actually the same as above)

So in both cases the above judgment is completely false. Go back to that quote:

  • Everything else is its child Fragment

If a child Fragment has a parent Fragment, then a root Fragment has no parent Fragment.

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        isIndexFragment =  null == getParentFragment();
        return super.onCreateView(inflater, container, savedInstanceState);
    }
Copy the code

The above judgment should be written as:

/ * * * @ return whether must carry on the handling of the status bar * @ remark by default for root fragments when processing * / protected Boolean isNeedChangeStatusBarMode () {/ / OnCreateView assigns this value, which was first called in onLazyResume, so it's a return isIndexFragment; } public void onLazyResume() { if (isNeedChangeStatusBarMode()) { updateStatusBarMode(isStatusBarLightMode()); }}Copy the code

PS

  • Lazy loading can not also use this judgment?

Lazy loading can be divided into two cases:

  • As the root Fragment, the time-consuming initialization operation begins after the animation ends to avoid page switch lag.
  • As a child Fragment, data requests only begin when displayed.

Similarly, it is possible to use isIndexFragment judgment to directly encapsulate lazy loads:

   private void checkLazyInit() {
       if (mIsFirstLayInit) {
           mIsFirstLayInit = false;
           onLazyInit();
       }
   }

   @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
   public void onLazyResume() {
   	...
       if (!isIndexFragment) {
           checkLazyInit();
       }
   }

   @Override
   protected void onEnterAnimationEnd(@Nullable Animation animation) {
       super.onEnterAnimationEnd(animation);
       if (isIndexFragment) {
           checkLazyInit();
       }
   }

Copy the code