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.