Rect는 중국어로 "직사각형 또는 직사각형"을 의미합니다. Rect 객체는 직사각형의 4개의 정수 좌표 값을 보유하고 있으며 RectF 객체는 직사각형의 4개의 부동 좌표 값을 보유하고 있습니다. 둘 사이의 차이. 구현 관점에서 Rect는 Parcelable 인터페이스를 구현하는 최종 클래스이고 RectF는 Parcelable 인터페이스를 구현하는 일반 클래스입니다. 기록되는 좌표 데이터 유형이 다른 점을 제외하면 Rect와 RectF는 일반적으로 동일한 메서드를 제공합니다.
1. 접촉:
은 좌표계의 직사각형 영역을 나타내는 데 사용되며 몇 가지 간단한 작업을 수행할 수 있습니다. 이 직사각형 영역은 왼쪽 상단과 오른쪽 하단의 두 좌표점으로 표시되어야 합니다.
2. 차이점:
(1) 정확도가 다릅니다. Rect는 int 유형을 숫자 값으로 사용하고 RectF는 float 유형을 숫자 값으로 사용합니다.
(2) 두 가지 유형이 제공하는 방법이 완전히 일치하지는 않습니다.
3. 코드 부분
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 및 Rect 기본
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()); } });
정확히 말하면 각 직사각형 영역에는 4개의 왼쪽, 위쪽, 오른쪽 및 아래쪽의 정점 좌표, getLeft(), getTop(), getRight() 및 getBottom()은 View에서 선언한 메서드에 속하므로 각 View 하위 클래스 또는 컨트롤은 위 메서드를 상속합니다. Rect 또는 RectF는 유사합니다. getLeft(), getTop(), getRight() 및 getBottom()을 사용할 때 두 가지 문제에 주의해야 합니다.
첫 번째 문제 : getLeft(), getTop(), getRight() 및 getBottom()은 상위 컨테이너를 기준으로 위치를 계산합니다.
두 번째 질문: getLeft(), getTop(), getRight() 및 getBottom() 계산 현재 View 하위 클래스 또는 컨트롤이 그려지지 않았기 때문에 결과는 0입니다. 해결책은 onClick 메서드를 클릭할 때를 계산하거나 스레드
/** * 延时获取控件相对父容器的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 및 Rect in deep
Rect의 지연 계산을 사용하는 것입니다. 클래스이며 Inherited에 속하지 않으며 직렬화를 수행하기 위해 Parcelable 인터페이스를 구현하고 View 직사각형 로컬 영역의 4개 꼭지점 좌표를 기록하는 데 사용되는 left, top, right 및 Bottom의 공용 범위에서 4개의 정수 속성을 선언합니다. .
public Rect() {}
1. 왼쪽, 위쪽, 오른쪽, 아래쪽의 기본값은 0입니다.
public Rect(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; }
2. 좌표 값 개체, 왼쪽, 위쪽, 오른쪽 및 아래쪽은 지정된 값
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. 알려진 Rect를 사용하여 새 Rect 개체를 생성하고 왼쪽, 위쪽, 오른쪽 및 아래쪽은 에 포함된 값입니다. 알려진 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. 현재 Rect와 지정된 o가 동일한지, 동일한 조건인지 확인합니다. 동일한 객체에 속하거나 둘 다의 왼쪽, 위쪽, 오른쪽 또는 아래쪽 속성 값이 동일
@Override public int hashCode() { int result = left; result = 31 * result + top; result = 31 * result + right; result = 31 * result + bottom; return result; }
5. 계산 Rect 속성값의 해시 코드
@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. 직사각형의 4개 좌표 값을 Rect(왼쪽,위-오른쪽) 형식으로 반환합니다. ,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. [left,top] 사용 [right,bottom] 형식은 직사각형의 4개 좌표, 즉 사각형의 왼쪽 위 모서리와 오른쪽 아래 모서리의 좌표를 반환합니다. 직사각형 영역
public String toShortString() { return toShortString(new StringBuilder(32)); }
8. 직사각형의 4개 좌표를 [left,top] [right,bottom] 형식으로 반환합니다. 즉, 사각형의 왼쪽 위 모서리와 오른쪽 아래 모서리의 좌표입니다. 직사각형 영역, 위의 방법
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. 직사각형의 4개 좌표값을 왼쪽 위 오른쪽 아래 형식, 즉 타일 형식으로 반환합니다. 예: 0 0 400 400 또는 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. 타일 형식의 문자열(예: 0 0 400 400)이 주어지면 그것이 적합한지 확인한 다음 이를 Rect 객체
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(']'); }
public final boolean isEmpty() { return left >= right || top >= bottom; }
public final int width() { return right - left; }
public final int height() { return bottom - top; }
public final int centerX() { return (left + right) >> 1; }
public final int centerY() { return (top + bottom) >> 1; }
public final float exactCenterX() { return (left + right) * 0.5f; }
public final float exactCenterY() { return (top + bottom) * 0.5f; }
public void setEmpty() { left = right = top = bottom = 0; }
public void set(int left, int top, int right, int bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; }
public void set(Rect src) { this.left = src.left; this.top = src.top; this.right = src.right; this.bottom = src.bottom; }
public void offset(int dx, int dy) { left += dx; top += dy; right += dx; bottom += dy; }
public void offsetTo(int newLeft, int newTop) { right += newLeft - left; bottom += newTop - top; left = newLeft; top = newTop; }
public void inset(int dx, int dy) { left += dx; top += dy; right -= dx; bottom -= dy; }
public boolean contains(int x, int y) { return left < right && top < bottom // check for empty first && x >= left && x < right && y >= top && y < bottom; }
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. 지정된 좌표(x, y)가 포함되는지 계산합니다. 하단 정점이 직사각형 영역에 포함되어 있으면 true를 반환하고, 그렇지 않으면 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를 반환합니다. 지정된 Rect가 직사각형 영역에 포함되는지 계산하고, 포함되면 true를 반환하고, 그렇지 않으면 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. 현재 Rect와 지정된 왼쪽, 위쪽, 오른쪽, 아래쪽 정점 사이에 교차 영역이 있는지 계산합니다. 그렇다면 true를 반환하고 지정된 좌표를 반환하고, 그렇지 않으면 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、排序当前矩形区域,符合:left
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、按照指定的值缩放当前矩形区域