Heim  >  Artikel  >  Java  >  Vertiefendes Verständnis der Unterschiede zwischen RectF und Rect in der Android-Entwicklung

Vertiefendes Verständnis der Unterschiede zwischen RectF und Rect in der Android-Entwicklung

伊谢尔伦
伊谢尔伦Original
2017-01-16 13:12:565366Durchsuche

Rect bedeutet auf Chinesisch „Rechteck oder Rechteck“. Das Rect-Objekt enthält vier ganzzahlige Koordinatenwerte eines Rechtecks, und das RectF-Objekt enthält vier Float-Koordinatenwerte eines Rechtecks Unterschied zwischen den beiden. Aus Sicht der Implementierung ist Rect eine endgültige Klasse, die die Parcelable-Schnittstelle implementiert, und RectF ist eine gewöhnliche Klasse, die die Parcelable-Schnittstelle implementiert. Mit Ausnahme der unterschiedlichen aufgezeichneten Koordinatendatentypen stellen Rect und RectF im Allgemeinen dieselben Methoden bereit.

1. Kontakt:
werden verwendet, um einen rechteckigen Bereich im Koordinatensystem darzustellen, und einige einfache Operationen können darauf ausgeführt werden. Dieser rechteckige Bereich muss durch zwei Koordinatenpunkte dargestellt werden: oben links und unten rechts.
2. Unterschied:
(1) Die Genauigkeit ist unterschiedlich. Rect verwendet den Typ „int“ als numerischen Wert und RectF verwendet den Typ „float“ als numerischen Wert.
(2). Die von den beiden Typen bereitgestellten Methoden sind nicht vollständig konsistent.

3. Codeteil

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- und Rect-Grundlagen

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());  
    }  
});

Gerade weil jeder rechteckige lokale Bereich vier Scheitelpunktkoordinaten links, oben, rechts und unten enthält, gehören getLeft (), getTop (), getRight () und getBottom () zu den von View deklarierten Methoden, sodass jede View-Unterklasse oder The Die Steuerung erbt die obige Methode. Rect oder RectF ähneln einer Werkzeugklasse und kapseln die Berechnungsbeziehung von vier Scheitelpunktkoordinaten. Bei der Verwendung von getLeft(), getTop(), getRight() und getBottom() sind zwei Probleme zu beachten. :

Die erste Frage: getLeft(), getTop(), getRight() und getBottom() berechnen die Position relativ zu seinem übergeordneten Container

Die zweite Frage: getLeft(), getTop( ), getRight() und Das Berechnungsergebnis von getBottom() ist 0, da die aktuelle View-Unterklasse oder das aktuelle View-Steuerelement nicht gezeichnet wurde. Die Lösung besteht darin, zu berechnen, wann die onClick-Methode angeklickt wird, oder die Verzögerungsberechnung des Threads zu verwenden

/** 
 * 延时获取控件相对父容器的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 und Rect gehen tief

Rect ist Eine endgültige Klasse. Sie implementiert die Parcelable-Schnittstelle zur Durchführung der Serialisierung und deklariert vier ganzzahlige Attribute im öffentlichen Bereich: links, oben, rechts und unten, die zum Aufzeichnen der vier Scheitelpunktkoordinaten des rechteckigen lokalen Bereichs verwendet werden .

public Rect() {}

1. Erstellen Sie ein leeres Rect-Objekt. Die Standardwerte für links, oben, rechts und unten sind 0

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

2 ein angegebenes Rect-Objekt mit Koordinatenwert, links, oben, rechts und unten sind angegebene Werte

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. Verwenden Sie das bekannte Rect, um ein neues Rect-Objekt zu erstellen, links, oben, rechts und unten sind bekannt Der in Rect enthaltene Wert

@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. Bestimmen Sie, ob das aktuelle Rect und das angegebene o gleich sind und dieselben Bedingungen erfüllen: zum selben Objekt oder zu den linken, oberen, rechten oder unteren Attributwerten gehören ​​von beiden sind gleich

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

Berechnen Sie den Hash-Code des Rect-Attributwerts

@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. Geben Sie die vier Koordinatenwerte des Rechtecks ​​​​zurück Format von Rect (links, oben rechts, unten)

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 Gibt die vier Koordinatenwerte des Rechtecks ​​im Format [links, oben] [rechts, unten] zurück , die Koordinaten der oberen linken Ecke und der unteren rechten Ecke des rechteckigen Bereichs

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

8. Im Format von [links, oben] [rechts, unten] Das Format von links, oben] [rechts ,bottom] gibt die vier Koordinatenwerte des Rechtecks ​​​​zurück, dh die Koordinaten der oberen linken Ecke und der unteren rechten Ecke des rechteckigen Bereichs, genau wie bei der obigen Methode

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. Im Format von links oben rechts unten werden die vier Koordinatenwerte des Rechtecks ​​zurückgegeben, d B.: 0 0 400 400, bestimmen Sie, ob sie zulässig ist, und konvertieren Sie sie dann in ein Rect-Objekt

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)));  
}

11. Schreiben Sie die in Rect enthaltenen Attributwerte in der angegebene PrintWriter-Stream im Format [links, oben] [rechts, unten]

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(']');  
}

12. Bestimmen Sie, ob Rect ein leeres Objekt ist, d. h. ob der darin enthaltene Attributwert nicht 0 ist

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

13. Berechnen Sie die Breite des rechteckigen Bereichs

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

14. Berechnen Sie die Höhe des rechteckigen Bereichs

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

15 Wenn das Berechnungsergebnis ein Bruch ist, wird die nächste ganze Zahl zurückgegeben, zum Beispiel: horizontaler Mittelpunkt 400

public final int centerX() {  
    return (left + right) >> 1;  
}
16. Berechnen Sie den vertikalen Mittelpunkt der rechteckigen Fläche Das Berechnungsergebnis ist ein Bruch, geben Sie die nächste ganze Zahl zurück, zum Beispiel: vertikaler Mittelpunkt 850

public final int centerY() {  
    return (top + bottom) >> 1;  
}
17 Berechnen Sie den vertikalen Mittelpunkt der rechteckigen Fläche. Horizontaler Mittelpunkt, geben Sie das Ergebnis vom Typ Float zurück Beispiel: horizontaler Mittelpunkt 400,0

public final float exactCenterX() {  
    return (left + right) * 0.5f;  
}
18. Berechnen Sie den vertikalen Mittelpunkt des rechteckigen Bereichs und geben Sie den Ergebnis-Float-Typ zurück, zum Beispiel: vertikaler Mittelpunkt 850,0

public final float exactCenterY() {  
    return (top + bottom) * 0.5f;  
}
19 . Setzen Sie den im Rect-Objekt enthaltenen Attributwert auf 0

public void setEmpty() {  
    left = right = top = bottom = 0;  
}
20. Setzen Sie den Attributwert von Rect auf den angegebenen Wert

public void set(int left, int top, int right, int bottom) {  
    this.left = left;  
    this.top = top;  
    this.right = right;  
    this.bottom = bottom;  
}
21 enthält Attributwerte

public void set(Rect src) {  
    this.left = src.left;  
    this.top = src.top;  
    this.right = src.right;  
    this.bottom = src.bottom;  
}
22. Erhöhen Sie die dx- und dy-Abstände in horizontaler und vertikaler Richtung, d. h. erweitern Sie

public void offset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right += dx;  
    bottom += dy;  
}
23 die aktuelle Die horizontale und vertikale Richtung des rechteckigen Bereichs sind um die Abstände dx bzw. dy versetzt, d horizontale und vertikale Richtungen des aktuellen rechteckigen Bereichs, d. h. Reduzieren Sie

public void offsetTo(int newLeft, int newTop) {  
    right += newLeft - left;  
    bottom += newTop - top;  
    left = newLeft;  
    top = newTop;  
}
25. Berechnen Sie, ob die angegebenen Koordinaten (x, y) im rechteckigen Bereich enthalten sind, andernfalls geben Sie true zurück Geben Sie „false“ zurück

public void inset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right -= dx;  
    bottom -= dy;  
}
26. Berechnen Sie, ob die angegebenen linken, oberen, rechten und unteren Eckpunkte im rechteckigen Bereich enthalten sind. Geben Sie „true“ zurück, wenn sie enthalten sind, andernfalls geben Sie „false“ zurück

public boolean contains(int x, int y) {  
    return left < right && top < bottom  // check for empty first  
           && x >= left && x < right && y >= top && y < bottom;  
}
27 . Berechnen Sie, ob das angegebene Rechteck im rechteckigen Bereich enthalten ist. Geben Sie „true“ zurück, andernfalls geben Sie „false“ zurück.

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;  
}
28. Berechnen Sie, ob es einen Schnittpunktbereich zwischen dem aktuellen Rechteck und dem angegebenen linken, oberen und rechten Bereich gibt , und untere Eckpunkte. Wenn ja, geben Sie „true“ und die angegebenen Koordinaten zurück, andernfalls geben Sie „false“ zurück

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、按照指定的值缩放当前矩形区域


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Vorheriger Artikel:Java-ReflexionsmechanismusNächster Artikel:Java-Reflexionsmechanismus