Maison  >  Article  >  Java  >  Compréhension approfondie des différences entre RectF et Rect dans le développement Android

Compréhension approfondie des différences entre RectF et Rect dans le développement Android

伊谢尔伦
伊谢尔伦original
2017-01-16 13:12:565424parcourir

Rect signifie "rectangle ou rectangle" en chinois. L'objet Rect contient quatre valeurs de coordonnées entières d'un rectangle, et l'objet RectF contient quatre valeurs de coordonnées flottantes d'un rectangle. différence entre les deux. Du point de vue de l'implémentation, Rect est une classe finale qui implémente l'interface Parcelable, et RectF est une classe ordinaire qui implémente l'interface Parcelable, à l'exception des différents types de données de coordonnées enregistrées, Rect et RectF fournissent généralement les mêmes méthodes.

1. Contact :
sont utilisés pour représenter une zone rectangulaire dans le système de coordonnées, et certaines opérations simples peuvent être effectuées dessus. Cette zone rectangulaire doit être représentée par deux points de coordonnées, le coin supérieur gauche et le coin inférieur droit.
2. Différence :
(1). Rect utilise le type int comme valeur numérique et RectF utilise le type float comme valeur numérique.
(2). Les méthodes fournies par les deux types ne sont pas complètement cohérentes.

3. Partie code

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

Bases de RectF et 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());  
    }  
});

C'est précisément parce que chaque zone locale rectangulaire contient quatre coordonnées de sommet de gauche, haut, droite et bas, getLeft(), getTop(), getRight() et getBottom() appartiennent aux méthodes déclarées par View, donc chaque sous-classe View ou The Le contrôle hérite de la méthode ci-dessus. Rect ou RectF est similaire à une classe d'outils, encapsulant la relation de calcul de quatre coordonnées de sommet. Il y a deux problèmes à prendre en compte lors de l'utilisation de getLeft(), getTop(), getRight() et getBottom(). :

La première question : getLeft(), getTop(), getRight() et getBottom() calculent la position par rapport à son conteneur parent

La deuxième question : getLeft(), getTop( ), getRight() et Le résultat du calcul de getBottom() est 0 car la sous-classe ou le contrôle View actuel n'a pas été dessiné. La solution est de calculer le moment où l'on clique sur la méthode onClick ou d'utiliser le calcul du délai du 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 et Rect vont en profondeur

Rect est une classe finale. Elle n'est pas héritée. Elle implémente l'interface Parcelable pour effectuer la sérialisation et déclare quatre attributs entiers dans la portée publique : left, top, right et bottom, qui sont utilisés pour enregistrer les quatre coordonnées de sommet de la zone locale rectangulaire View. .

public Rect() {}

1. Créez un objet Rect vide. Les valeurs par défaut de gauche, haut, droite et bas sont 0

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

2. un objet Rect spécifié de valeur de coordonnée, gauche, haut, droite et bas sont des valeurs spécifiées

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. Utilisez le Rect connu pour créer un nouvel objet Rect, gauche, haut, droite et bas sont connu La valeur contenue dans 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. Déterminez si le Rect actuel et le o spécifié sont identiques, les mêmes conditions : appartiennent au même objet ou aux valeurs d'attribut gauche, haut, droite ou bas. ​​des deux sont identiques

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

5. Calculez le code de hachage de la valeur de l'attribut 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. Renvoyez les quatre valeurs de coordonnées du rectangle dans le format de Rect (gauche, haut-droit, bas)

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. Renvoie les quatre valeurs de coordonnées du rectangle au format [gauche, haut] [droite, bas], c'est-à-dire , les coordonnées du coin supérieur gauche et du coin inférieur droit de la zone rectangulaire

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

8 Au format [gauche, haut] [droite, bas] Le format gauche, haut] [droite. ,bottom] renvoie les quatre valeurs de coordonnées du rectangle, c'est-à-dire les coordonnées du coin supérieur gauche et du coin inférieur droit de la zone rectangulaire, les mêmes que la méthode ci-dessus

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. Au format gauche en haut à droite en bas Renvoie les quatre valeurs de coordonnées du rectangle, c'est-à-dire le format carrelé, tel que : 0 0 400 400 ou 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. une chaîne au format carrelé, tel que : 0 0 400 400, déterminez si elle est légale, puis convertissez-la en un objet 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. Écrivez les valeurs d'attribut contenues dans Rect dans le flux PrintWriter donné au format [gauche, haut] [droite, bas]

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

12. Déterminez si Rect est un objet vide, c'est-à-dire si la valeur d'attribut qu'il contient n'est pas 0<.>

public final int width() {  
    return right - left;  
}
13. Calculez la largeur de la zone rectangulaire

public final int height() {  
    return bottom - top;  
}
14 Calculez la hauteur de la zone rectangulaire

public final int centerX() {  
    return (left + right) >> 1;  
}
15. point de la zone rectangulaire. Si le résultat du calcul est une fraction, l'entier le plus proche est renvoyé, par exemple : point central horizontal 400

public final int centerY() {  
    return (top + bottom) >> 1;  
}
16 Calculez le point central vertical de la zone rectangulaire. le résultat du calcul est une fraction, renvoie l'entier le plus proche, par exemple : point central vertical 850

public final float exactCenterX() {  
    return (left + right) * 0.5f;  
}
17 Calculez le point central vertical de la zone rectangulaire Point central horizontal, renvoie le résultat de type flottant, par exemple. : point central horizontal 400,0

public final float exactCenterY() {  
    return (top + bottom) * 0.5f;  
}
18. Calculez le point central vertical de la zone rectangulaire, renvoie le résultat de type float, par exemple : point central vertical 850,0

public void setEmpty() {  
    left = right = top = bottom = 0;  
}
19. Définissez la valeur d'attribut contenue dans l'objet Rect sur 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. Définissez la valeur d'attribut de Rect sur la valeur spécifiée

public void set(Rect src) {  
    this.left = src.left;  
    this.top = src.top;  
    this.right = src.right;  
    this.bottom = src.bottom;  
}
21 Copiez le contenu spécifié de l'objet Rect. valeurs d'attribut

public void offset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right += dx;  
    bottom += dy;  
}
22. Augmentez les distances dx et dy dans les directions horizontale et verticale de la zone rectangulaire actuelle, c'est-à-dire développez

public void offsetTo(int newLeft, int newTop) {  
    right += newLeft - left;  
    bottom += newTop - top;  
    left = newLeft;  
    top = newTop;  
}
23. courant Les directions horizontale et verticale de la zone rectangulaire sont décalées respectivement par les distances dx et dy, c'est-à-dire la translation horizontale dx et la translation verticale dy

public void inset(int dx, int dy) {  
    left += dx;  
    top += dy;  
    right -= dx;  
    bottom -= dy;  
}
24 Réduisez respectivement dx et dy dans l'horizontale. et les directions verticales de la zone rectangulaire actuelle, c'est-à-dire réduire

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. Calculez si les coordonnées spécifiées (x, y) sont incluses dans la zone rectangulaire, retournez vrai si elles sont incluses, sinon retournez. 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. Calculez si les sommets gauche, supérieur, droit et inférieur spécifiés sont inclus dans la zone rectangulaire, renvoyez vrai s'ils sont inclus, sinon renvoyez faux

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. Calculez si le Rect spécifié est inclus dans la zone rectangulaire, inclus Renvoyez vrai, sinon renvoyez faux

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. Calculez s'il existe une zone d'intersection entre le Rect actuel et les valeurs spécifiées gauche, haut, droite, et les sommets inférieurs Si oui, renvoyez vrai et renvoyez les coordonnées spécifiées, sinon renvoyez faux

.

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


Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:Mécanisme de réflexion JavaArticle suivant:Mécanisme de réflexion Java