Maison > Java > javaDidacticiel > le corps du texte

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

伊谢尔伦
Libérer: 2017-01-16 13:12:56
original
5429 Les gens l'ont consulté

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);
    }
}
Copier après la connexion

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());  
    }  
});
Copier après la connexion
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());  
    }  
});
Copier après la connexion
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());  
    }  
});
Copier après la connexion

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();
Copier après la connexion

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() {}
Copier après la connexion

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;  
}
Copier après la connexion

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;  
    }  
}
Copier après la connexion

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;  
}
Copier après la connexion

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;  
}
Copier après la connexion

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();  
}
Copier après la connexion

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();  
}
Copier après la connexion

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));  
}
Copier après la connexion

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();  
}
Copier après la connexion

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)));  
}
Copier après la connexion

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(']');  
}
Copier après la connexion

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;  
}
Copier après la connexion

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;  
}
Copier après la connexion
13. Calculez la largeur de la zone rectangulaire

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

public final int centerX() {  
    return (left + right) >> 1;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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;  
}
Copier après la connexion
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);  
}
Copier après la connexion

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;  
}
Copier après la connexion

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;  
}
Copier après la connexion

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;  
}
Copier après la connexion

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;  
        }  
    }  
}
Copier après la connexion

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

public void union(Rect r) {  
    union(r.left, r.top, r.right, r.bottom);  
}
Copier après la connexion

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;  
    }  
}
Copier après la connexion

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;  
    }  
}
Copier après la connexion

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);  
    }  
}
Copier après la connexion

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);  
    }  
}
Copier après la connexion

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


Étiquettes associées:
source:php.cn
Déclaration de ce site Web
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal