在上一篇博客中,我们基本了解了Android中View的绘制流程,知道了绘制流程以后,是不是想要马上写一些自定义控件来玩一下呢?不急,在这一篇博客中,我们先来了解一下Android给我们提供的一些常见的绘图的API。绘图的API是什么呢,我就用一个比喻吧。当Android工程师在自定义view是就相当于一个画家,那么画家作画是不是需要了工具了,如画板、画布、画笔以及颜料等,而Android系统也给我们提供了很多这样的工具,就是Android中的一些绘图相关的API。这篇文章主要介绍Point/PointF、Rect/RectF、Bitmap/BitmapDrawable几个类;在下一篇文章中将主要介绍Paint类和Canvas类。

1.Point类和PointF类(讨论的是android.graphics包下面的,不是java.awt包下面的)

Point类是一个简单的类,代表一个"点",实现了Parcelable序列化接口,支付序列化和反序列化。Point类中定义了两个成员变量x和y,表示一个点的横坐标和纵坐标。在Android中的坐标与数学中的平面坐标有所不同,Android中x轴向右为正,向左为负;y轴向下为正,向上为负,坐标原点在屏幕的左上角,也就是说屏幕内的所有点不管是x坐标还是y坐标都是正数。


Point类作为最简单的类,提供的功能也很简单

① 通过Point类创建一个点的方法

// 创建一个新的点public Point() {}// 根据x,y坐标创建一个新的点public Point(int x, int y) {this.x = x;this.y = y;}// 通过一个点创建一个新的点,就是将一个点的坐标赋值给另一个点public Point(Point src) {this.x = src.x;this.y = src.y;}
② 对Point点进行操作的方法

// 对点进行重新设置x和ypublic void set(int x, int y) {this.x = x;this.y = y;}// 将x和y取反值public final void negate() {x = -x;y = -y;}// 对x和y的值做改变,dx、dy表示偏移量,正负号决定偏移的方向public final void offset(int dx, int dy) {x += dx;y += dy;}
③ 判断方法

// 通过x和y坐标判断是否为同一点public final boolean equals(int x, int y) {return this.x == x && this.y == y;}// 判断一个对象是否和当前点是否是同一个点或者重合@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Point point = (Point) o;if (x != point.x) return false;if (y != point.y) return false;return true;}
PointF类和Point类功能和用法完全一样,唯一不同的就是Point类的成员变量x、y是int类型的;PointF类的成员变量x、y是float类型的。

2.Rect类和RectF类

Rect 类定义了一个矩形结构,同样实现了Parcelable序列化接口。Rect类定义了left、top、right、bottom 四个成员变量,我们需要正确理解这4个成员变量的作用:
◆ left: 矩形左边线条离 y 轴的距离
◆ top:矩形上面线条离 x 轴的距离
◆ right:矩形右边线条离 y 轴的距离
◆ bottom:矩形底部线条离 x 轴的距离


矩形是一种非常常见的图形结构,并且能衍生出更多的图形,如椭圆、扇形、弧线等等;矩形还能进行各种图形运算,如交集、并集等等,所以与之对应的 Rect 类功能也更加复杂。
① 创建一个Rect,主要有3个构造方法

// 创建一个空对象,left、topright、bottom都为0public Rect() {}// 根据指定的left、topright、bottom创建一个Rect对象public Rect(int left, int top, int right, int bottom) {...}// 从另外一个Rect对象复制出一个新的Rect对象public Rect(Rect r) {...}
② 对Rect重新设置值的方法

// 将Rect对象置空,就是将left、topright、bottom的值都设置为0public void setEmpty() {left = right = top = bottom = 0;}// 重新设置left、topright、bottom的值 public void set(int left, int top, int right, int bottom) {this.left = left;this.top = top;this.right = right;this.bottom = bottom;}// 将另外一个Rect对象的值设置到当前Rect对象中public void set(Rect src) {this.left = src.left;this.top = src.top;this.right = src.right;this.bottom = src.bottom;}

③ Rect类中的计算相关的方法

// 获取Rect的宽  public final int width() {      return right - left;  }  // 获取Rect的高  public final int height() {      return bottom - top;  }  // 计算Rect中心点的x坐标,返回int类型的值  public final int centerX() {      return (left + right) >> 1; // >>1 相当于 /2  }  // 计算Rect中心点的y坐标,返回int类型的值public final int centerY() {      return (top + bottom) >> 1;  }  // 计算Rect中心点的x坐标,返回float类型的值,结果更精确  public final float exactCenterX() {      return (left + right) * 0.5f;  }  // 计算Rect中心点的y坐标,返回float类型的值,结果更精确  public final float exactCenterY() {      return (top + bottom) * 0.5f;  }
④ Rect类中的判断相关的方法
// 判断是否为空public final boolean isEmpty() {return left >= right || top >= bottom;}// 判断是否包含点x、ypublic boolean contains(int x, int y) {return left < right && top < bottom  // check for empty first   && x >= left && x < right && y >= top && y < bottom;}// 判断是否包含另外一个矩形public boolean contains(int left, int top, int right, int bottom) {return this.left < this.right && this.top < this.bottom&& this.left <= left && this.top <= top&& this.right >= right && this.bottom >= bottom;}// 判断是否包含另外一个矩形public boolean contains(Rect r) {return this.left < this.right && this.top < this.bottom   && left <= r.left && top <= r.top && right >= r.right && bottom >= r.bottom;}
⑤ 缩放和平移相关的方法

// 实现矩形的缩放功能,缩放中心就是矩形的中心点,dx、 dy为正数时表示缩小,负数表示放大public void inset(int dx, int dy) {left += dx;top += dy;right -= dx;bottom -= dy;}// 矩形的left和right同时移动相同的距离dx,矩形的top和bottom同时移动相同的距离dy,正负决定移动方向public void offset(int dx, int dy) {left += dx;top += dy;right += dx;bottom += dy;}// 也是移位, 只是offset()是绝对定位,offsetTo()是相对定位。public void offsetTo(int newLeft, int newTop) {right += newLeft - left;bottom += newTop - top;left = newLeft;top = newTop;}
⑥ 运算相关的方法

// 取交集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;}// 取交集public boolean intersect(Rect r) {return intersect(r.left, r.top, r.right, r.bottom);}// 取并集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;}}}// 取并集public void union(Rect r) {union(r.left, r.top, r.right, r.bottom);}// 更新矩形的值,扩大范围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;}}

RectF类与Rect类功能和用法完全一样,不同是Rect的left、topright、 bottom四个成员变量为int类型,而RectF为float类型。另外在开发中可能会用到Rect和RectF的相互转换,在RectF类中定义了两个方法用于将RectF装换成Rect

// 将float类型的left、top、right、 bottom都以四舍五入的方式变为int类型public void round(Rect dst) {dst.set(FastMath.round(left), FastMath.round(top),FastMath.round(right), FastMath.round(bottom));}// 将float类型的left、top做floor()运算:返回最大的值,该值小于等于参数,并等于某个整数(如15.3、15.8都返回15)// 将float类型的right、 bottom做ceil()运算:返回最小的值,该值大于等于参数,并等于某个整数(如15.3、15.8都返回16)public void roundOut(Rect dst) {dst.set((int) Math.floor(left), (int) Math.floor(top),(int) Math.ceil(right), (int) Math.ceil(bottom));}
而Rect转换成RectF就可以直接通过构造函数就可以实现转换了

public RectF(Rect r) {...}


3.Bitmap类和BitmapDrawable类

Bitmap表示“位图”,用于存储png、jpg、gif等格式的图片数据,在Android中对图片进行处理,需要先将图片读成Bitmap对象,然后在对Bitmap对象进行操作,图片读取操作是BitmapFactory 类完成的,该类定义了一些方法用于读取不同路径下的图片数据:

// 从指定的文件路径中读取图片public static Bitmap decodeFile(String pathName)// 通过资源id读取res/drawable或res/mipmap目录下的图片public static Bitmap decodeResource(Resources res, int id)// 从InputStream输入流中读取图片数据public static Bitmap decodeStream(InputStream is)// 从字节数组中读取图片数据public static Bitmap decodeByteArray(byte[] data, int offset, int length)
当然上面的方法还有很多的重载方法,能在读取图片数据的同时设置一些参数。
如果需要创建一个图片的话,在Bitmap中提供了createBitmap()方法可以创建,这个方法同样有很多的重载版本,可以在创建图片的同时指定图片的各种参数,下面提供一种比较常见的做法做参考:

// 创建一个宽和高都是500的ARGB_8888类型的空白位图对象Bitmap bitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
在Bitmap类中还有一些比较常用的方法:

// 压缩图片 format:图片格式;quality:压缩率;stream:保存压缩后的数据public boolean compress(CompressFormat format, int quality, OutputStream stream)// 复制一张图片 config:图片的配置;isMutable:复制后得到的图片是否可以修改,true表示可以public Bitmap copy(Config config, boolean isMutable)// 获取Bitmap的宽public final int getWidth()// 获取Bitmap的高public final int getHeight()// 设置Bitmap的宽public final int setWidth()// 设置Bitmap的高public final int setHeight()// 判断图片是否已经回收public final boolean isRecycled()// 回收Bitmap内存public void recycle()// 返回Bitmap的字节数public final int getByteCount()
在Android中Bitmap是一个比较消耗资源的对象,所以在使用完成时候要释放掉Bitmap对象,一般释放Bitmap的代码如下:

// 判断bitmap是否为null或者已经释放掉if (bitmap != null && !bitmap.isRecycled()) {bitmap.recycle(); // 释放Bitmap内存bitmap = null;    // 将bitmap对象置为nullSystem.gc();      // 手动调用gc(),提醒JVM释放资源}
BimapDrawable是Android 的一种通用位图格式,也可以理解成Bitmap的另外一种表现形式。 但比Bitmap占用资源更少、性能更高。
在BitmapDrawable中的一些常用方法,同时也提供了BitmapDrawable和Bitmap的相互转化的方法:

// 通过构造可以将Bitmap对象转换成BitmapDrawable对象public BitmapDrawable(Bitmap bitmap)// 将Bitmap对象设置到BitmapDrawable对象中protected void setBitmap(Bitmap bitmap)// 从BitmapDrawable对象中得到Bitmap对象public final Bitmap getBitmap()// 获取BitmapDrawable的宽,和Bitmap有一点区别public int getIntrinsicWidth()// 获取BitmapDrawable的高,和Bitmap有一点区别public int getIntrinsicHeight()// 获取BitmapDrawable的透明度public int getAlpha()// 获取BitmapDrawable中的Paint对象public final Paint getPaint()


更多相关文章

  1. Android属性动画(下),InterPolator、ViewPropertyAnimator和布局动
  2. Android文件命名规范初版
  3. GreenDao开源ORM框架浅析
  4. (4.2.6)【android开源组件】SwitchButton 开关按钮 的多种实现方式
  5. Android通过ksoap向webserice传递复杂类型数据
  6. Android获取当前应用分配的最大内存和目前使用内存的方法
  7. 动态化部署:Android热修复之代码修复(一)
  8. android 中用代码模拟发送按键
  9. 在 SQL 数据库中保存数据

随机推荐

  1. Android中给按钮同时设置背景和圆角示例
  2. android 用java动态设置布局(增添删除修改
  3. 反杀套路!阿里独家的《Android(安卓)开发
  4. TextView在显示文字的时候有个问题就是一
  5. android如何让后台服务service不被杀死(设
  6. Android多点触控实现图片缩放预览
  7. android 的外部存储的挂载的理解
  8. react-native Android截屏长图
  9. Android消息推送:手把手教你集成小米推送
  10. 只要找对路子,Android游戏也能赚钱