>  기사  >  Java  >  Android 개발에서 RectF와 Rect의 차이점에 대한 심층적인 이해

Android 개발에서 RectF와 Rect의 차이점에 대한 심층적인 이해

伊谢尔伦
伊谢尔伦원래의
2017-01-16 13:12:565364검색

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(']');  
}
11 .Rect에 포함된 속성 값을 [left, top] [right, Bottom]

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

형식으로 지정된 PrintWriter 스트림에 씁니다. 12. Rect가 빈 객체인지 확인합니다. , 포함된 속성 값이 0이 아닌지

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

13. 직사각형 영역의 너비를 계산합니다

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

14. 직사각형 영역의 높이를 계산합니다

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

. 15. 직사각형 영역의 가로 중심점을 계산합니다. 계산 결과 분수인 경우 가장 가까운 정수를 반환합니다. 예: 가로 중심점 400

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

16. 직사각형 영역, 계산 결과가 분수인 경우 가장 가까운 정수를 반환합니다. 예: 수직 중심점 850

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

17 직사각형 영역의 수평 중심점을 계산하고 결과 부동 소수점을 반환합니다. 예: 수평 중심점 400.0

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

18. 직사각형 영역의 수직 중심점을 계산하고 결과 부동 소수점 유형을 반환합니다. 예: 수직 중심점 850.0

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

19. Rect 객체에 포함된 속성 값을 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으로 설정합니다. Rect의 속성 값을 지정된 값

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

21로 설정합니다. 지정된 Rect 객체

public void offset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right += dx;  
    bottom += dy;  
}
에 포함된 속성 값을 복사합니다.

22. 현재 직사각형 영역의 가로 및 세로 방향으로 dx 및 dy 거리를 늘립니다. 즉 확장

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

23. 현재 직사각형 영역의 가로 및 세로 방향으로 dx 및 dy 거리를 오프셋합니다. 직사각형 영역, 즉 수평 이동 dx 및 수직 이동 dy

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

24. 현재 직사각형 영역의 수평 및 수직 방향 각각 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;  
}
25. 지정된 좌표(x, y)가 직사각형 영역에 포함되는지 계산하고, 포함되면 true를 반환하고, 그렇지 않으면 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. 지정된 좌표(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、排序当前矩形区域,符合: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、按照指定的值缩放当前矩形区域


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
이전 기사:Java 반사 메커니즘다음 기사:Java 반사 메커니즘