Android three-step simple fit Liu Hai system status bar

Keywords: Mobile Android

Personal thinking:

When it comes to Qiliuhai adaptation, the most typical one is that some fragments of MainActivity need transparent system status bar or not, while fragments that need transparent system status bar usually have a rotation chart at the top, and then a search box is put on the rotation chart. The so-called adaptation means that the location of the search box is set according to the height of the system status bar, so as to search on Qiliuhai mobile phone. The cable frame is not covered.

As shown in the figure above, the following three-step analysis of the system status bar as shown in the dynamic diagram

1. Getting the height of the system status bar

Two lines of code give you the height of the current system status bar

      int resourceId = mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
      int viewHeight = mContext.getResources().getDimensionPixelSize(resourceId);

2. Setting Colors

According to the requirement of UI, my approach is to set the system status bar transparent, monitor gesture action, add a view with the same height of the system status bar to start sliding, change the background color gradient (gradient value is 0-100%, percentage is the same as sliding distance/rotation map height), change the color of the system status bar icon to dark color, then rewrite scrollview, set the transparent system when listening to the sliding top. Hold the status bar and hide the occupied view.

/**
 * Setting Transparent System Status Bar
 */
View decorView = getActivity().getWindow().getDecorView();
decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
getActivity().getWindow().setStatusBarColor(Color.parseColor("#00000000"));//Setting Transparency
/**
 * Set the system status bar icon color, and use false and true to set the color to white or dark
 */
 StatusBarCompat.setLightStatusBar(getActivity().getWindow(), false);
/**
 * Sliding monitor
 */
 private MyScrollView.OnMyScrollListener listener;

 listener = new MyScrollView.OnMyScrollListener() {
                @Override
                public void onScrollStateChanged(MyScrollView view, int state) {
                    String str;
                    if (state == 0) {
                        str = "IDLE";
                    } else if (state == 1) {
                        str = "DRAG";
                    } else if (state == 2) {
                        str = "FLING";
                    } else {
                        str = "ERROR";
                    }
                    Log.d("brycegao", "Sliding state:" + str);
                }

                @Override
                public void onScroll(MyScrollView view, int y) {
                    int height = banner.getHeight();
                    if (scroll_view.getScrollY() > 0) {
                        if (scroll_view.getScrollY() < height) {
                            float scale = (float) scroll_view.getScrollY() / height;
                            float alpha = (255 * scale);
                            //Percentage gradient
                            view_placeholder.setBackgroundColor(Color.argb((int) alpha, 0xff, 0xff, 0xff));
                            //Get the height of the system status bar
                            int resourceId = mContext.getResources().getIdentifier("status_bar_height", "dimen", "android");
                            //Get screen width
                            int viewWidth = (int) (ScreenUtils.getScreenWidth(mContext));
                            if (resourceId > 0) {
                                int viewHeight = mContext.getResources().getDimensionPixelSize(resourceId);
                                RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(viewWidth, viewHeight);
                                view_placeholder.setLayoutParams(params);
                            }
                            StatusBarCompat.setLightStatusBar(getActivity().getWindow(), true);//Setting the font color of navigation bar
                        }
                    }

                }

                @Override
                public void onScrollToTop() {
                    Log.d("brycegao", "Slide to the top");
                    view_placeholder.setLayoutParams(new RelativeLayout.LayoutParams(0, 0));
                    StatusBarCompat.setLightStatusBar(getActivity().getWindow(), false);//Setting the font color of navigation bar
                }

                @Override
                public void onScrollToBottom() {
                    Log.d("brycegao", "Sliding bottom");
                }
            };
/**
 * Custom scroll lview listens for sliding events, which can be found on the Internet and tested personally, but forgive me for forgetting the original address.
 */
public class MyScrollView extends ScrollView {

    private ArrayList<OnMyScrollListener> listeners;

    private int currentState;
    private boolean isLastBottom;  //Was the last refresh bottom?
    private int lastDrawPos;     //Longitudinal displacement of last refresh

    public interface OnMyScrollListener {
        int SCROLL_STATE_FLING = 2;   //Release the finger after sliding and slide automatically
        int SCROLL_STATE_IDLE = 0;   //No sliding
        int SCROLL_STATE_TOUCH_SCROLL = 1;   //Slide your finger against the screen

        void onScrollStateChanged(MyScrollView view, int state);

        void onScroll(MyScrollView view, int y); //Sliding distance

        void onScrollToTop();   //Slide to the top

        void onScrollToBottom(); //Slide to the bottom
    }

    public MyScrollView(Context context) {
        super(context);
    }

    public MyScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
        listeners = new ArrayList<>();
    }

    public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override public boolean onTouchEvent(MotionEvent ev) {
        boolean lastDragState = getDragState();

        boolean ret = super.onTouchEvent(ev);
        if (ev.getActionMasked() == MotionEvent.ACTION_MOVE) {
            for (OnMyScrollListener listener:listeners) {
                listener.onScroll(this, getScrollY());
            }
        }

        if ((ev.getActionMasked() == MotionEvent.ACTION_UP
                || ev.getActionMasked() == MotionEvent.ACTION_CANCEL)
                && currentState == OnMyScrollListener.SCROLL_STATE_TOUCH_SCROLL) {
            //Cancel Sliding
            currentState = OnMyScrollListener.SCROLL_STATE_IDLE;
            for (OnMyScrollListener listener:listeners) {
                listener.onScrollStateChanged(this, OnMyScrollListener.SCROLL_STATE_IDLE);
            }

        }
        boolean curDragState = getDragState();

        //drag
        if (!lastDragState && curDragState) {
            currentState = OnMyScrollListener.SCROLL_STATE_TOUCH_SCROLL;
            for (OnMyScrollListener listener:listeners) {
                listener.onScrollStateChanged(this, OnMyScrollListener.SCROLL_STATE_TOUCH_SCROLL);
            }
        }
        return ret;
    }

    @Override protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (lastDrawPos == getScrollY()
                && getScrollY() > 0
                && currentState == OnMyScrollListener.SCROLL_STATE_FLING ) {
            currentState = OnMyScrollListener.SCROLL_STATE_IDLE;  //Set the state to idle
            for (OnMyScrollListener listener:listeners) {
                listener.onScrollStateChanged(this, OnMyScrollListener.SCROLL_STATE_IDLE);
            }
        }

        if (getScrollY() == 0 && lastDrawPos == 0
                && currentState != OnMyScrollListener.SCROLL_STATE_IDLE) {
            currentState = OnMyScrollListener.SCROLL_STATE_IDLE;  //Set the state to idle
            for (OnMyScrollListener listener:listeners) {
                listener.onScrollStateChanged(this, OnMyScrollListener.SCROLL_STATE_IDLE);
                listener.onScrollToTop();
            }
        }

        lastDrawPos = getScrollY();

        if (isCurrentBottom()
                && !isLastBottom) {
            for (OnMyScrollListener listener:listeners) {
                listener.onScrollToBottom();
            }
        }
        isLastBottom = isCurrentBottom();
    }

    @Override public void fling(int velocityY) {
        super.fling(velocityY);

        if (getChildCount() > 0) {
            currentState = OnMyScrollListener.SCROLL_STATE_FLING;
            for (OnMyScrollListener listener:listeners) {
                listener.onScrollStateChanged(this, OnMyScrollListener.SCROLL_STATE_FLING);
            }
        }
    }

    //Judge whether to slide to the bottom
    private boolean isCurrentBottom() {
        boolean ret = false;

        int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
        int heightPadding;  //The sum of padding up and down in scrollview
        View child = getChildAt(0);
        final FrameLayout.LayoutParams lp = (LayoutParams) child.getLayoutParams();
        if (targetSdkVersion >= Build.VERSION_CODES.M) {
            heightPadding = getPaddingTop() + getPaddingBottom() + lp.topMargin + lp.bottomMargin;
        } else {
            heightPadding = getPaddingTop() + getPaddingBottom();
        }

        if (getMeasuredHeight() - heightPadding + getScrollY() == child.getMeasuredHeight()) {
            ret = true;
        }
        return ret;
    }

    //Reflective Query mIsBeingDragged
    private boolean getDragState() {
        boolean state = false;
        try {
            Class clz = ScrollView.class;
            Field field = clz.getDeclaredField("mIsBeingDragged");
            field.setAccessible(true);
            state = field.getBoolean(this);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return state;
    }

    //Whether the sliding accelerator stops
    private boolean isfinishScroll() {
        boolean isfinish=false;
        Class scrollview=ScrollView.class;
        try {
            Field scrollField=scrollview.getDeclaredField("mScroller");
            scrollField.setAccessible(true);
            Object scroller=scrollField.get(this);
            Class overscroller= scrollField.getType();
            Method finishField=overscroller.getMethod("isFinished");
            finishField.setAccessible(true);
            isfinish= (boolean) finishField.invoke(scroller);
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {

        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return isfinish;
    }

    /**
     * Add Sliding Monitor
     * @param listener
     */
    public void addOnScrollListner(OnMyScrollListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("invalid listener");
        }

        if (!listeners.contains(listener)) {
            listeners.add(listener);
        }
    }

    public void removeOnScrollListener(OnMyScrollListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("invalid listener");
        }

        listeners.remove(listener);
    }
}

III. UI Adaptation

In fact, this UI adaptation is also very simple, that is to set the padding Top of the search box as the height of the system status bar + xdp, where no code is written.

Above is my idea of aligning Liu Hai. Welcome to make corrections, learn together and encourage each other.

Posted by phppucci on Fri, 25 Jan 2019 07:03:13 -0800