Home >Java >javaTutorial >In-depth understanding of the differences between RectF and Rect in Android development
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、按照指定的值缩放当前矩形区域