在上一篇博客中,我们基本了解了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() {} 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点进行操作的方法
public void set( int x, int y) { this .x = x; this .y = y; } public final void negate() { x = -x; y = -y; } public final void offset( int dx, int dy) { x += dx; y += dy; }
③ 判断方法
public final boolean equals( int x, int y) { return this .x == x && this .y == y; } @Override public 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个构造方法
public Rect() {} public Rect( int left, int top, int right, int bottom) {...} public Rect(Rect r) {...}
② 对Rect重新设置值的方法
public void setEmpty() { left = right = top = bottom = 0 ; } public void set( int left, int top, int right, int bottom) { this .left = left; this .top = top; this .right = right; this .bottom = bottom; } public void set(Rect src) { this .left = src.left; this .top = src.top; this .right = src.right; this .bottom = src.bottom; }
③ Rect类中的计算相关的方法
public final int width() { return right - left; } public final int height() { return bottom - top; } public final int centerX() { return (left + right) >> 1 ; } public final int centerY() { return (top + bottom) >> 1 ; } public final float exactCenterX() { return (left + right) * 0 .5f; } public final float exactCenterY() { return (top + bottom) * 0 .5f; }
④ Rect类中的判断相关的方法
public final boolean isEmpty() { return left >= right || top >= bottom; } public boolean contains( int x, int y) { return left < right && top < bottom && 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; }
⑤ 缩放和平移相关的方法
public void inset( int dx, int dy) { left += dx; top += dy; right -= dx; bottom -= dy; } public void offset( int dx, int dy) { left += dx; top += dy; right += dx; bottom += dy; } 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 :
public void round(Rect dst) { dst.set(FastMath.round(left), FastMath.round(top), FastMath.round(right), FastMath.round(bottom)); } 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) public static Bitmap decodeResource(Resources res, int id) public static Bitmap decodeStream(InputStream is) public static Bitmap decodeByteArray( byte [] data, int offset, int length)
当然上面的方法还有很多的重载方法,能在读取图片数据的同时设置一些参数。
如果需要创建一个图片的话,在Bitmap中提供了createBitmap()方法可以创建,这个方法同样有很多的重载版本,可以在创建图片的同时指定图片的各种参数,下面提供一种比较常见的做法做参考:
Bitmap bitmap = Bitmap.createBitmap(500 , 500 , Bitmap.Config.ARGB_8888);
在Bitmap类中还有一些比较常用的方法:
public boolean compress(CompressFormat format, int quality, OutputStream stream) public Bitmap copy(Config config, boolean isMutable) public final int getWidth() public final int getHeight() public final int setWidth() public final int setHeight() public final boolean isRecycled() public void recycle() public final int getByteCount()
在Android中Bitmap是一个比较消耗资源的对象,所以在使用完成时候要释放掉Bitmap对象,一般释放Bitmap的代码如下:
if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); bitmap = null ; System.gc(); }
BimapDrawable是Android 的一种通用位图格式,也可以理解成Bitmap的另外一种表现形式。 但比Bitmap占用资源更少、性能更高。
在BitmapDrawable中的一些常用方法,同时也提供了BitmapDrawable和Bitmap的相互转化的方法:
public BitmapDrawable(Bitmap bitmap) protected void setBitmap(Bitmap bitmap) public final Bitmap getBitmap() public int getIntrinsicWidth() public int getIntrinsicHeight() public int getAlpha() public final Paint getPaint()