Heim > Java > javaLernprogramm > 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

伊谢尔伦
Freigeben: 2017-01-16 13:12:56
Original
5467 Leute haben es durchsucht

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);
    }
}
Nach dem Login kopieren

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());  
    }  
});
Nach dem Login kopieren
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());  
    }  
});
Nach dem Login kopieren
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());  
    }  
});
Nach dem Login kopieren

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();
Nach dem Login kopieren

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() {}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

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;  
    }  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

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();  
}
Nach dem Login kopieren

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();  
}
Nach dem Login kopieren

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));  
}
Nach dem Login kopieren

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();  
}
Nach dem Login kopieren

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)));  
}
Nach dem Login kopieren

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(']');  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

13. Berechnen Sie die Breite des rechteckigen Bereichs

public final int width() {  
    return right - left;  
}
Nach dem Login kopieren

14. Berechnen Sie die Höhe des rechteckigen Bereichs

public final int height() {  
    return bottom - top;  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
19 . Setzen Sie den im Rect-Objekt enthaltenen Attributwert auf 0

public void setEmpty() {  
    left = right = top = bottom = 0;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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;  
}
Nach dem Login kopieren
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);  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

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;  
}
Nach dem Login kopieren

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;  
        }  
    }  
}
Nach dem Login kopieren

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

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

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;  
    }  
}
Nach dem Login kopieren

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;  
    }  
}
Nach dem Login kopieren

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);  
    }  
}
Nach dem Login kopieren

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);  
    }  
}
Nach dem Login kopieren

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


Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
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
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage