java rect_深入理解Android开发RectF和Rect之间的区别

Rect中文意思“矩形或长方形”,Rect对象持有一个矩形的四个integer坐标值,RectF对象持有一个矩形的四个float坐标值,这是两者最大的区别。从实现的方式上看,Rect是一个final类实现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());

}

});

正是因为每一个矩形局域包含着left、top、right和bottom四个顶点坐标,getLeft()、getTop()、getRight()和getBottom()属于View声明的方法,因此每一个View子类或者控件继承上述方法,Rect或RectF类似一个工具类,封装四个顶点坐标的计算关系,使用getLeft()、getTop()、getRight()和getBottom()需要注意两个问题:

第一个问题:getLeft()、getTop()、getRight()和getBottom()计算相对其父容器的位置

第二个问题:getLeft()、getTop()、getRight()和getBottom()计算结果为0,是因为当前View子类或控件没有绘制完成。解决办法,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深入

Rect是一个final类,不属于被继承,实现Parcelable接口执行序列化,声明public作用域的四个整型属性:left、top、right和bottom,用来记录View矩形局域的四个顶点坐标。public Rect() {}

1、创建一个空的Rect对象,left、top、right和bottom的默认值为0public Rect(int left, int top, int right, int bottom) {

this.left = left;

this.top = top;

this.right = right;

this.bottom = bottom;

}

2、创建一个指定坐标值的Rect对象,left、top、right和bottom为指定值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对象,left、top、right和bottom为已知的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是否同一个,相同的条件:属于同一个对象或者两者left、top、right或bottom属性值一样@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、以Rect(left,top-right,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]的格式返回矩形四个坐标值,即矩形区域左上角和右下角坐标public String toShortString() {

return toShortString(new StringBuilder(32));

}

8、以[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、以left top right bottom的格式返回矩形四个坐标值,即平铺的格式,比如:0 0 400 400或 100 100 800 300public 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]的格式写入给定的PrintWriter流中public final boolean isEmpty() {

return left >= right || top >= bottom;

}

12、判断Rect是否一个空对象,即包含的属性值是否不为0public final int width() {

return right - left;

}

13、计算矩形区域的宽度public final int height() {

return bottom - top;

}

14、计算矩形区域的高度public final int centerX() {

return (left + right) >> 1;

}

15、计算矩形区域的水平中心点,计算结果为分数则返回最接近的整型数,例如:水平中心点400public final int centerY() {

return (top + bottom) >> 1;

}

16、计算矩形区域的垂直中心点,计算结果为分数则返回最接近的整型数,例如:垂直中心点850public final float exactCenterX() {

return (left + right) * 0.5f;

}

17、计算矩形区域的水平中心点,返回结果float类型,例如:水平中心点400.0public final float exactCenterY() {

return (top + bottom) * 0.5f;

}

18、计算矩形区域的垂直中心点,返回结果float类型,例如:垂直中心点850.0public void setEmpty() {

left = right = top = bottom = 0;

}

19、将Rect对象包含的属性值设置为0public 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、垂直平移dypublic void inset(int dx, int dy) {

left += dx;

top += dy;

right -= dx;

bottom -= dy;

}

24、在当前矩形区域的水平方向、垂直方向分别减少dx、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,否则返回falsepublic 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、计算指定的left、top、right、bottom顶点是否包含在矩形区域范围内,包含返回true,否则返回falsepublic 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,否则返回falsepublic 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与指定的left、top、right、bottom顶点是否存在交集区域,存在返回true并且返回指定坐标,否则返回falsepublic boolean intersect(Rect r) {

return intersect(r.left, r.top, r.right, r.bottom);

}

29、计算当前Rect与指定的Rect是否存在交集区域,存在返回true并且返回指定坐标,否则返回falsepublic 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并且返回最大坐标,否则返回falsepublic 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并且不返回指定坐标,否则返回falsepublic 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并且不返回最大坐标,否则返回falsepublic 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、排序当前矩形区域,符合:leftpublic 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、按照指定的值缩放当前矩形区域

本文原创发布php中文网,转载请注明出处,感谢您的尊重!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值