Android custom control coordinate system analysis

Posted by Domhnall on Fri, 11 Feb 2022 05:55:49 +0100

If you want to thoroughly grasp the custom control and master the coordinate meaning of various Android coordinate systems and some API s, there is no doubt that it is a skill that can not be ignored. The placement position, touch point and control drawing of the control are inseparable from the coordinate system, so let's talk about the Android coordinate system before learning the custom control.

1, The difference between Android screen coordinate system and mathematical coordinate system

(1) In the mathematical coordinate system, the intersection of xy axis is taken as the coordinate origin, the right of x axis is the positive direction, and the up of y axis is the positive direction, which is familiar to children's shoes, as shown in the figure:

(2) The coordinate system on the mobile phone screen is different from the mathematical coordinate system. Mobile devices generally define the upper left corner of the screen as the coordinate origin, the right of the x axis as the positive direction, and the down of the y axis as the positive direction, as shown in the figure:

2, Division of Android screen area

Android screen area is mainly divided into five areas: status bar area, ActionBar area, View layout area, application App area and screen area, which are nested with each other. As shown in the figure:

Let's take a look at the height acquisition of each area:

(1) . Height Acquisition of status bar area:

        //The first method is to wait until the interface rendering is finished
        Rect rect = new Rect();
        getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
        int statusBarHeight = rect.top;
        

        //The second method is to obtain the height of the status bar
        Resources resources = this.getResources();
        int resourceId = resources.getIdentifier("status_bar_height", "dimen", "android");
        int height = resources.getDimensionPixelSize(resourceId);//Get the height of the status bar this time
  

        //The third way is to obtain the height of the status bar through reflection
        int statusHeight = -1;
        try {
            Class clazz = Class.forName("com.android.internal.R$dimen");
            Object object = clazz.newInstance();
            int intheight = Integer.parseInt(clazz.getField("status_bar_height")
                    .get(object).toString());
            //Get status bar height
            statusHeight = this.getResources().getDimensionPixelSize(intheight); 
        } catch (Exception e) {
            e.printStackTrace();
        }

(2) . Height Acquisition of ActionBar area:

        //The first way is to wait until the interface rendering is finished
        int actionBarHeight = getSupportActionBar().getHeight();

        //The second way
        TypedValue tv = new TypedValue();
        if (this.getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
            int actionBarHeightOther = TypedValue.complexToDimensionPixelSize(
                    tv.data, this.getResources().getDisplayMetrics()); 
        }

(3) . View layout area Height Acquisition:

  //The first way
  Rect rect = new Rect();
  getWindow().findViewById(Window.ID_ANDROID_CONTENT).getDrawingRect(rect);

  //The second way
  //It can be seen that onWindowFocusChanged will be called when onResume and onPause are executed. The interface has been rendered
   @Override
  public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    if (hasFocus) {
        int width = view.getMeasuredWidth();//Get width
        int height = view.getMeasuredHeight();//Gain height
    }
  }
  
  //The third way
  view.post(new Runnable() {
         @Override
         public void run() {
             int width=view.getMeasuredWidth();
             int height=view.getMeasuredHeight();
         }
     })
     
  //The fourth way
    view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            int width=view.getMeasuredWidth();
            int height=view.getMeasuredHeight();
        }
    });

(4) . App area Height Acquisition:

 Rect rect = new Rect();
 getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);

(5) . screen area Height Acquisition:

        //The first method is outdated after version 4.1.
        Display display = getWindowManager().getDefaultDisplay();
        int width = display.getWidth();
        int height = display.getHeight();

        //The second way
        Display defaultDisplay = getWindowManager().getDefaultDisplay();
        Point point = new Point();
        defaultDisplay.getSize(point);
        int x = point.x;
        int y = point.y;

        //The third way
        Rect outSize = new Rect();
        getWindowManager().getDefaultDisplay().getRectSize(outSize);
        int left = outSize.left;
        int top = outSize.top;
        int right = outSize.right;
        int bottom = outSize.bottom;

        //The fourth way
        DisplayMetrics outMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
        int widthPixels = outMetrics.widthPixels;
        int heightPixels = outMetrics.heightPixels;

        //The fifth way
        Point outSizeOther = new Point();
        getWindowManager().getDefaultDisplay().getRealSize(outSizeOther);
        int x1 = outSizeOther.x;
        int y1 = outSizeOther.y;

        //The sixth way
        DisplayMetrics outMetrics1 = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getRealMetrics(outMetrics1);
        int widthPixel = outMetrics1.widthPixels;
        int heightPixel = outMetrics1.heightPixels;

Special note: the above methods are best invoked after the onWindowFocusChanged() method of Activity, or later, because only at this time can the real display be complete.

3, Classification of Android coordinate system

Above, we analyzed the division of Android screen area, and then we analyzed the Android coordinate system related to the area, which can be divided into screen coordinate system and view coordinate system.

(1) Screen coordinate system

The difference between the screen coordinate system and the mathematical coordinate system has been introduced earlier. Take the upper left corner of the screen as the coordinate origin, the right of the x-axis as the positive direction, and the down of the y-axis as the positive direction, as shown in the figure:

(2) View coordinate system

View coordinate system in the view drawing process, the drawing content will take the coordinate system as a reference, and finally determine the position of the drawing content in the view.

Let's take a look at the common coordinate methods. Note that these methods are relative to the parent container:

View related methods: method description

view.getLeft(): the distance between the left edge of the current View and the left edge of its parent View (View coordinates);

view.getRight(): the distance between the right edge of the current View and the left edge of its parent View (View coordinates);

view.getTop(): the distance between the upper edge of the current View and the upper edge (top) of its parent View (View coordinates);

view.getBottom(): the distance between the lower edge of the current View and the upper edge (top) of its parent View (View coordinates);

View.getTranslationX(): the offset of the current view on the X axis. The initial value is 0, the left offset value is negative, and the right offset value is positive; (common in attribute animation)

View.getTranslationY(): the offset of the current view on the Y axis. The initial value is 0, the upward offset is negative, and the downward offset is positive; (common in attribute animation)

View.getX: the offset of the current view on the X axis. The initial value is 0, the left offset value is negative, and the right offset value is positive; The return value is getLeft()+getTranslationX(). When setTranslationX() changes to getLeft(), getX() changes.

View.getY: the offset of the current view on the Y axis. The initial value is 0, the upward offset is negative, and the downward offset is positive; The return value is getTop()+getTranslationY(). When setTranslationY() changes to getTop(), getY() changes.

In order to explain these methods clearly, a diagram is prepared, as shown in the figure:

At this point, we can obtain the width and height of the View:

View width height method: method description
getWidth(): the width of the current View, that is, getRight()-getLeft()
getHeight(): current View width, i.e. getBottom()-getTop()

It should be noted that in the process of using the above method, the value obtained is 0 after the View measurement is completed, that is, after the rendering is completed.

Let's take a look at some methods provided by MotionEvent when a finger touches the screen:

MotionEvent coordinate method: method description
getX(): the distance between the touch center point and the left edge of the View (relative coordinates)
getY(): the distance between the touch center point and the upper edge of the View (relative coordinates)
getRawX(): the distance between the touch center point and the left edge of the screen (absolute coordinates)
getRawY(): the distance between the touch center point and the upper edge of the screen (absolute coordinates)

In order to explain these methods clearly, a diagram is prepared, as shown in the figure:

That's all for today's content. This article mainly expounds the concepts related to common methods and coordinates in View, and also paves the way for later content. Welcome to the official account of the dragon.

Topics: Java Android Android Studio