Home  >  Article  >  Java  >  In-depth understanding of the differences between RectF and Rect in Android development

In-depth understanding of the differences between RectF and Rect in Android development

伊谢尔伦
伊谢尔伦Original
2017-01-16 13:12:565364browse

Rect means "rectangle or rectangle" in Chinese. The Rect object holds four integer coordinate values ​​​​of a rectangle, and the RectF object holds four float coordinate values ​​​​of a rectangle. This is the biggest difference between the two. From the perspective of implementation, Rect is a final class that implements the Parcelable interface, and RectF is an ordinary class that implements the Parcelable interface. Except for the different coordinate data types recorded, Rect and RectF provide generally the same methods. .

1. Contact:
are used to represent a rectangular area in the coordinate system, and some simple operations can be performed on it. This rectangular area needs to be represented by two coordinate points, the upper left and the lower right.
2. Difference:
(1). The accuracy is different. Rect uses int type as numerical value, and RectF uses float type as numerical value.
(2). The methods provided by the two types are not exactly the same.

3. Code part

package com.pansoft.viewdemo.view;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.graphics.RectF;
import android.view.View;
/**
  自定义View
**/
public class MyView extends View {
    /** 上下文 */
    private Context mContext;    /** 画笔 */
    private Paint mPaint;    
    public MyView(Context context) {        
    super(context);
        mContext = context;
    }    
    @Override
    protected void onDraw(Canvas canvas) {        
    super.onDraw(canvas);
        mPaint = new Paint();        
        // 设置画笔的颜色
        mPaint.setColor(Color.RED);        
        // 设置填充颜色
        mPaint.setStyle(Style.FILL);
        RectF rect = new RectF(10, 10, 100, 100);        
        // Rect rect2 = new Rect(10, 10, 100, 100);
        canvas.drawRect(rect, mPaint);
    }
}

RectF and Rect basics

final TextView textView = new TextView(this);  
textView.setText("显示Rect存储坐标数据");  
/** 
 * 设置TextView的宽度和高度,最后计算TextView的左上角和右下角的坐标 
 */  
textView.setLayoutParams(new ViewGroup.LayoutParams(400, 400));  
textView.setBackgroundColor(Color.parseColor("#00BFFF"));  
textView.setGravity(Gravity.CENTER);  
textView.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
    int top = v.getTop();  
    int left = v.getLeft();  
    int right = v.getRight();  
    int bottom = v.getBottom();  
    /** 
     * 将TextView相对父控件的坐标保存在Rect对象 
     */  
    mRect.left = left;  
    mRect.right = right;  
    mRect.top = top;  
    mRect.bottom = bottom;  
  
    textView.setText(mRect.toShortString());  
    }  
});
final Button button = new Button(this);  
/** 
 * 设置button的宽度和高度,最后计算矩形局域的宽和高 
 */  
ViewGroup.MarginLayoutParams params=new ViewGroup.MarginLayoutParams(800, 300);  
/** 
 * 设置button的margin属性值 
 */  
params.setMargins(100,DensityUtil.dip2px(this,100),100,100);  
button.setLayoutParams(params);  
button.setText("计算Rect坐标");  
button.setBackgroundColor(Color.parseColor("#7FFFAA"));  
button.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
    int top = v.getTop();  
    int left = v.getLeft();  
    int right = v.getRight();  
    int bottom = v.getBottom();  
    /** 
     * 将TextView相对父控件的坐标保存在Rect对象 
     */  
    mRect.left = left;  
    mRect.right = right;  
    mRect.top = top;  
    mRect.bottom = bottom;  
  
    button.setText("宽度:"+mRect.width()+"\n"+"高度:"+mRect.height());  
    }  
});
final Button anim_btn =new Button(this);  
/** 
 * 设置button的宽度和高度 
 */  
params=new ViewGroup.MarginLayoutParams(800, 300);  
/** 
 * 设置button的margin属性值,计算矩形局域的中心点坐标 
 */  
params.setMargins(100,DensityUtil.dip2px(this,100),100,100);  
anim_btn.setLayoutParams(params);  
anim_btn.setText("计算Rect坐标");  
anim_btn.setBackgroundColor(Color.parseColor("#DDA0DD"));  
anim_btn.setGravity(Gravity.RIGHT);  
anim_btn.setOnClickListener(new View.OnClickListener() {  
    @Override  
    public void onClick(View v) {  
    int top = v.getTop();  
    int left = v.getLeft();  
    int right = v.getRight();  
    int bottom = v.getBottom();  
    /** 
     * 将TextView相对父控件的坐标保存在Rect对象 
     */  
    mRect.left = left;  
    mRect.right = right;  
    mRect.top = top;  
    mRect.bottom = bottom;  
    anim_btn.setText("水平中心点:"+mRect.centerX()+"\n垂直中心点:"+mRect.centerY());  
    }  
});

It is precisely because each rectangular local area contains The four vertex coordinates of left, top, right and bottom, getLeft(), getTop(), getRight() and getBottom() belong to the methods declared by View, so each View subclass or control inherits the above methods, Rect or RectF is similar to one Tool class, encapsulates the calculation relationship of four vertex coordinates. When using getLeft(), getTop(), getRight() and getBottom(), you need to pay attention to two issues:

The first issue: getLeft(), getTop (), getRight() and getBottom() calculate the position relative to its parent container

Second question: getLeft(), getTop(), getRight() and getBottom() calculate the result to 0 because The current View subclass or control has not been drawn. The solution is to calculate when the onClick method is clicked or use the delay calculation of the thread

/** 
 * 延时获取控件相对父容器的left、top、right、bottom坐标,否则为0 
 */  
new Thread(new Runnable() {  
    @Override  
    public void run() {  
    try {  
        Thread.sleep(1000);  
    } catch (InterruptedException e) {  
        e.printStackTrace();  
    }  
    saveCoordinateToRect();  
    }  
}).start();

RectF and Rect in-depth

Rect is a final class and does not belong to Inherited, implements the Parcelable interface to perform serialization, and declares four integer attributes in the public scope: left, top, right, and bottom, which are used to record the four vertex coordinates of the View rectangular local area.

public Rect() {}

1. Create an empty Rect object. The default values ​​of left, top, right and bottom are 0

public Rect(int left, int top, int right, int bottom) {  
    this.left = left;  
    this.top = top;  
    this.right = right;  
    this.bottom = bottom;  
}

2. Create a Rect with specified coordinate values. Object, left, top, right and bottom are the specified values

public Rect(Rect r) {  
    if (r == null) {  
        left = top = right = bottom = 0;  
    } else {  
        left = r.left;  
        top = r.top;  
        right = r.right;  
        bottom = r.bottom;  
    }  
}

3. Use the known Rect to create a new Rect object, left, top, right and bottom are the values ​​contained in the known Rect

@Override  
public boolean equals(Object o) {  
    if (this == o) return true;  
    if (o == null || getClass() != o.getClass()) return false;  
  
    Rect r = (Rect) o;  
    return left == r.left && top == r.top && right == r.right && bottom == r.bottom;  
}

4. Determine whether the current Rect and the specified o are the same, the same conditions: belong to the same object or the left, top, right or bottom attribute values ​​of both are the same

@Override  
public int hashCode() {  
    int result = left;  
    result = 31 * result + top;  
    result = 31 * result + right;  
    result = 31 * result + bottom;  
    return result;  
}

5. Calculation The hash code of the Rect attribute value

@Override  
public String toString() {  
    StringBuilder sb = new StringBuilder(32);  
    sb.append("Rect("); sb.append(left); sb.append(", ");  
    sb.append(top); sb.append(" - "); sb.append(right);  
    sb.append(", "); sb.append(bottom); sb.append(")");  
    return sb.toString();  
}

6. Return the four coordinate values ​​of the rectangle in the format of Rect(left,top-right,bottom)

public String toShortString(StringBuilder sb) {  
    sb.setLength(0);  
    sb.append('['); sb.append(left); sb.append(',');  
    sb.append(top); sb.append("]["); sb.append(right);  
    sb.append(','); sb.append(bottom); sb.append(']');  
    return sb.toString();  
}

7.With [left,top] The format of [right,bottom] returns the four coordinates of the rectangle, that is, the coordinates of the upper left corner and the lower right corner of the rectangular area

public String toShortString() {  
    return toShortString(new StringBuilder(32));  
}

8. The format of [left,top] [right,bottom] returns the four coordinates of the rectangle. Value, that is, the coordinates of the upper left corner and lower right corner of the rectangular area, the same as the above method

public String flattenToString() {  
    StringBuilder sb = new StringBuilder(32);  
    // WARNING: Do not change the format of this string, it must be  
    // preserved because Rects are saved in this flattened format.  
    sb.append(left);  
    sb.append(' ');  
    sb.append(top);  
    sb.append(' ');  
    sb.append(right);  
    sb.append(' ');  
    sb.append(bottom);  
    return sb.toString();  
}

9. Return the four coordinate values ​​of the rectangle in the format of left top right bottom, that is, the tiled format, for example: 0 0 400 400 or 100 100 800 300

public static Rect unflattenFromString(String str) {  
    Matcher matcher = UnflattenHelper.getMatcher(str);  
    if (!matcher.matches()) {  
        return null;  
    }  
    return new Rect(Integer.parseInt(matcher.group(1)),  
            Integer.parseInt(matcher.group(2)),  
            Integer.parseInt(matcher.group(3)),  
            Integer.parseInt(matcher.group(4)));  
}

10. Given a string in flat format, such as: 0 0 400 400, determine whether it is legal, and then convert it to a Rect object

public void printShortString(PrintWriter pw) {  
    pw.print('['); pw.print(left); pw.print(',');  
    pw.print(top); pw.print("]["); pw.print(right);  
    pw.print(','); pw.print(bottom); pw.print(']');  
}

11 . Write the attribute values ​​contained in Rect into the given PrintWriter stream in the format of [left, top] [right, bottom]

public final boolean isEmpty() {  
    return left >= right || top >= bottom;  
}

12. Determine whether Rect is an empty object, that is, whether the included attribute values ​​are Not 0

public final int width() {  
    return right - left;  
}

13. Calculate the width of the rectangular area

public final int height() {  
    return bottom - top;  
}

14. Calculate the height of the rectangular area

public final int centerX() {  
    return (left + right) >> 1;  
}

15. Calculate the horizontal center point of the rectangular area and calculate the result If it is a fraction, the nearest integer is returned, for example: the horizontal center point 400

public final int centerY() {  
    return (top + bottom) >> 1;  
}

16. Calculate the vertical center point of the rectangular area. If the calculation result is a fraction, the nearest integer is returned, for example: vertical Center point 850

public final float exactCenterX() {  
    return (left + right) * 0.5f;  
}

17. Calculate the horizontal center point of the rectangular area and return the result float type, for example: horizontal center point 400.0

public final float exactCenterY() {  
    return (top + bottom) * 0.5f;  
}

18. Calculate the vertical center point of the rectangular area and return the result float type, for example: vertical center point 850.0

public void setEmpty() {  
    left = right = top = bottom = 0;  
}

19. Set the attribute value contained in the Rect object to 0

public void set(int left, int top, int right, int bottom) {  
    this.left = left;  
    this.top = top;  
    this.right = right;  
    this.bottom = bottom;  
}

20. Set the attribute value of Rect to the specified value

public void set(Rect src) {  
    this.left = src.left;  
    this.top = src.top;  
    this.right = src.right;  
    this.bottom = src.bottom;  
}

21. Copy the attribute value contained in the specified Rect object

public void offset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right += dx;  
    bottom += dy;  
}

22. Increase the dx and dy distances in the horizontal and vertical directions of the current rectangular area, that is, expand

public void offsetTo(int newLeft, int newTop) {  
    right += newLeft - left;  
    bottom += newTop - top;  
    left = newLeft;  
    top = newTop;  
}

23. Offset dx and dy distances in the horizontal and vertical directions of the current rectangular area, that is, horizontal translation dx and vertical translation dy

public void inset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right -= dx;  
    bottom -= dy;  
}

24. Reduce dx in the horizontal and vertical directions of the current rectangular area respectively. , dy distance, that is, reducing

public boolean contains(int x, int y) {  
    return left < right && top < bottom  // check for empty first  
           && x >= left && x < right && y >= top && y < bottom;  
}

25. Calculate whether the specified coordinates (x, y) are included in the rectangular area, return true if included, otherwise return false

public boolean contains(int left, int top, int right, int bottom) {  
           // check for empty first  
    return this.left < this.right && this.top < this.bottom  
           // now check for containment  
            && this.left <= left && this.top <= top  
            && this.right >= right && this.bottom >= bottom;  
}

26. Calculate the specified Whether the left, top, right, and bottom vertices are included in the rectangular area, return true if included, otherwise return false

public boolean contains(Rect r) {  
           // check for empty first  
    return this.left < this.right && this.top < this.bottom  
           // now check for containment  
           && left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom;  
}

27. Calculate whether the specified Rect is included in the rectangular area, return true if included, otherwise Return false

public boolean intersect(int left, int top, int right, int bottom) {  
    if (this.left < right && left < this.right && this.top < bottom && top < this.bottom) {  
        if (this.left < left) this.left = left;  
        if (this.top < top) this.top = top;  
        if (this.right > right) this.right = right;  
        if (this.bottom > bottom) this.bottom = bottom;  
        return true;  
    }  
    return false;  
}

28. Calculate whether there is an intersection area between the current Rect and the specified left, top, right, and bottom vertices. Return true and return the specified coordinates, otherwise return false

public boolean intersect(Rect r) {  
    return intersect(r.left, r.top, r.right, r.bottom);  
}

29、计算当前Rect与指定的Rect是否存在交集区域,存在返回true并且返回指定坐标,否则返回false

public boolean setIntersect(Rect a, Rect b) {  
    if (a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom) {  
        left = Math.max(a.left, b.left);  
        top = Math.max(a.top, b.top);  
        right = Math.min(a.right, b.right);  
        bottom = Math.min(a.bottom, b.bottom);  
        return true;  
    }  
    return false;  
}

30、计算指定的a、b是否存在交集区域,存在返回true并且返回最大坐标,否则返回false

public boolean intersects(int left, int top, int right, int bottom) {  
    return this.left < right && left < this.right && this.top < bottom && top < this.bottom;  
}

31、计算当前Rect与指定的left、top、right、bottom顶点是否存在交集区域,存在返回true并且不返回指定坐标,否则返回false

public static boolean intersects(Rect a, Rect b) {  
    return a.left < b.right && b.left < a.right && a.top < b.bottom && b.top < a.bottom;  
}

32、计算指定的a、b是否存在交集区域,存在返回true并且不返回最大坐标,否则返回false

public void union(int left, int top, int right, int bottom) {  
    if ((left < right) && (top < bottom)) {  
        if ((this.left < this.right) && (this.top < this.bottom)) {  
            if (this.left > left) this.left = left;  
            if (this.top > top) this.top = top;  
            if (this.right < right) this.right = right;  
            if (this.bottom < bottom) this.bottom = bottom;  
        } else {  
            this.left = left;  
            this.top = top;  
            this.right = right;  
            this.bottom = bottom;  
        }  
    }  
}

33、计算当前Rect与指定的left、top、right、bottom顶点是否存在并集区域,存在更新当前矩形区域,否则不更新

public void union(Rect r) {  
    union(r.left, r.top, r.right, r.bottom);  
}

34、计算当前Rect与指定的Rect是否存在并集区域,存在更新当前矩形区域,否则不更新

public void union(int x, int y) {  
    if (x < left) {  
        left = x;  
    } else if (x > right) {  
        right = x;  
    }  
    if (y < top) {  
        top = y;  
    } else if (y > bottom) {  
        bottom = y;  
    }  
}

35、计算当前Rect与指定的坐标(x,y)是否存在并集区域,存在更新当前矩形区域,否则不更新

public void sort() {  
    if (left > right) {  
        int temp = left;  
        left = right;  
        right = temp;  
    }  
    if (top > bottom) {  
        int temp = top;  
        top = bottom;  
        bottom = temp;  
    }  
}

36、排序当前矩形区域,符合:left1a0efaddeef485005a08d823ed136161

public void scale(float scale) {  
    if (scale != 1.0f) {  
        left = (int) (left * scale + 0.5f);  
        top = (int) (top * scale + 0.5f);  
        right = (int) (right * scale + 0.5f);  
        bottom = (int) (bottom * scale + 0.5f);  
    }  
}

37、按照指定的值缩放当前矩形区域

public void scaleRoundIn(float scale) {  
    if (scale != 1.0f) {  
        left = (int) Math.ceil(left * scale);  
        top = (int) Math.ceil(top * scale);  
        right = (int) Math.floor(right * scale);  
        bottom = (int) Math.floor(bottom * scale);  
    }  
}

38、按照指定的值缩放当前矩形区域


Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Previous article:Java reflection mechanismNext article:Java reflection mechanism