Android Canvas裁剪和Region、RegionIterator
轉自:http://blog.csdn.net/lonelyroamer/article/details/8349601
canvas 還提供裁剪的功能。
裁剪功能由Canvas提供的一系列的clip…方法 和quickReject方法來完成。 前面已經提到,真正提供可繪制區域的是Canvas内部的mutable bitmap。 Canvas更像是一個圖層,我們隻能在這上面的圖層來繪制東西。
1、首先介紹Region類
Region,中文意思即區域的意思,它表示的是canvas圖層上的某一塊封閉的區域。
/**構造方法*/
public Region() //建立一個空的區域
public Region(Region region) //拷貝一個region的範圍
public Region(Rect r) //建立一個矩形的區域
public Region(int left, int top, int right, int bottom) //建立一個矩形的區域
/**一系列set方法,這些set方法,和上面構造方法形式差不多*/
public void setEmpty() {
public boolean set(Region region)
public boolean set(Rect r)
public boolean set(int left, int top, int right, int bottom)
/*往一個Region中添加一個Path隻有這種方法,參數clip代表這個整個Region的區域,在在裡面裁剪出path範圍的區域*/
public boolean setPath(Path path, Region clip) //用指定的Path和裁剪範圍建構一個區域
/**幾個判斷方法*/
public native boolean isEmpty();//判斷該區域是否為空
public native boolean isRect(); //是否是一個矩陣
public native boolean isComplex();//是否是多個矩陣組合
/**一系列的getBound方法,傳回一個Region的邊界*/
public Rect getBounds()
public boolean getBounds(Rect r)
public Path getBoundaryPath()
public boolean getBoundaryPath(Path path)
/**一系列的判斷是否包含某點 和是否相交*/
public native boolean contains(int x, int y);//是否包含某點
public boolean quickContains(Rect r) //是否包含某矩陣
public native boolean quickContains(int left, int top, int right,
int bottom) //是否沒有包含某矩陣
public boolean quickReject(Rect r) //是否沒和該矩陣相交
public native boolean quickReject(int left, int top, int right, int bottom); //是否沒和該矩陣相交
public native boolean quickReject(Region rgn); //是否沒和該矩陣相交
/**幾個平移變換的方法*/
public void translate(int dx, int dy)
public native void translate(int dx, int dy, Region dst);
public void scale(float scale) //hide
public native void scale(float scale, Region dst);//hide
/**一系列組合的方法*/
public final boolean union(Rect r)
public boolean op(Rect r, Op op) {
public boolean op(int left, int top, int right, int bottom, Op op)
public boolean op(Region region, Op op)
public boolean op(Rect rect, Region region, Op op)
上面幾乎是Region的所有API,很好了解,主要說明一下最後的一組關于Region組合的方式。組合即目前的Region和另外的一個Region組合,可以用不同的Op方式來進行組合。
Op是一個枚舉,定義在Region類中。
假設用region1 去組合region2
public enum Op {
DIFFERENCE(), //最終區域為region1 與 region2不同的區域
INTERSECT(), // 最終區域為region1 與 region2相交的區域
UNION(), //最終區域為region1 與 region2組合一起的區域
XOR(), //最終區域為region1 與 region2相交之外的區域
REVERSE_DIFFERENCE(), //最終區域為region2 與 region1不同的區域
REPLACE(); //最終區域為為region2的區域
}
ApiDemo中已經提供了一個關于組合的例子,在最後面給出。
Android還提供了一個RegionIterator來對Region中的所有矩陣進行疊代,可以使用該類,獲得某個Region的所有矩陣。比較簡單。
2、什麼是裁剪
裁剪Clip,即裁剪Canvas圖層,我們繪制的東西,隻能在裁剪區域的範圍能才能顯示出來。
@Override
protected void onDraw(Canvas canvas) {
Paint paint=new Paint();
canvas.save();
canvas.clipRect(new Rect(,,,));
canvas.drawColor(Color.BLUE);//裁剪區域的rect變為藍色
canvas.drawRect(new Rect(,,,), paint);//在裁剪的區域之外,不能顯示
canvas.drawCircle(,, , paint);//在裁剪區域之内,能顯示
canvas.restore();
}
裁剪并不像Matrix變換,它相對于mutable bitmap的坐标是不會改變的。是以超出裁剪區域的繪制不會被顯示
3、裁剪的儲存和復原
在之前已經提到了,canvas.save()和canvas.restore()不僅對matrix有效,同樣對clip有類似的效果。
4、裁剪的方式
Canvas提供了三種裁剪的方式:
1、最基本的clipRect,裁剪一個矩形
2、clipPath,裁剪Path包括的範圍,Path所包括的範圍不是空的才有效。
3、clipRegion。
Region在前面已經介紹過了,其實Region就是一個對區域組合的一個封裝。但是它和clipRect和clipPath的最大差別在于下面:
與clipRect和clipPath要使用目前的matrix進行變換不同。clipRegion不會進行轉換。也就是說canvas的matrix對clipRegion沒有影響。
Paint paint=new Paint();
canvas.scale(f, f);
canvas.save();
canvas.clipRect(new Rect(,,,));//裁剪區域實際大小為50*50
canvas.drawColor(Color.RED);
canvas.restore();
canvas.drawRect(new Rect(,,,), paint);//矩形實際大小為50*50
canvas.clipRegion(new Region(new Rect(,,,)));//裁剪區域實際大小為100*100
canvas.drawColor(Color.BLACK);
ApiDemo中關于組合的例子
public class Clipping extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private static class SampleView extends View {
private Paint mPaint;
private Path mPath;
public SampleView(Context context) {
super(context);
setFocusable(true);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setStrokeWidth();
mPaint.setTextSize();
mPaint.setTextAlign(Paint.Align.RIGHT);
mPath = new Path();
}
private void drawScene(Canvas canvas) {
canvas.clipRect(, , , );
canvas.drawColor(Color.WHITE);
mPaint.setColor(Color.RED);
canvas.drawLine(, , , , mPaint);
mPaint.setColor(Color.GREEN);
canvas.drawCircle(, , , mPaint);
mPaint.setColor(Color.BLUE);
canvas.drawText("Clipping", , , mPaint);
}
@Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
canvas.save();
canvas.translate(, );
drawScene(canvas);
canvas.restore();
canvas.save();
canvas.translate(, );
canvas.clipRect(, , , );
canvas.clipRect(, , , , Region.Op.DIFFERENCE);
drawScene(canvas);
canvas.restore();
canvas.save();
canvas.translate(, );
mPath.reset();
canvas.clipPath(mPath); // makes the clip empty
mPath.addCircle(, , , Path.Direction.CCW);
canvas.clipPath(mPath, Region.Op.REPLACE);
drawScene(canvas);
canvas.restore();
canvas.save();
canvas.translate(, );
canvas.clipRect(, , , );
canvas.clipRect(, , , , Region.Op.UNION);
drawScene(canvas);
canvas.restore();
canvas.save();
canvas.translate(, );
canvas.clipRect(, , , );
canvas.clipRect(, , , , Region.Op.XOR);
drawScene(canvas);
canvas.restore();
canvas.save();
canvas.translate(, );
canvas.clipRect(, , , );
canvas.clipRect(, , , , Region.Op.REVERSE_DIFFERENCE);
drawScene(canvas);
canvas.restore();
}
}
}
5、裁剪的一個小用處
public class ClippingRegion extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
private class SampleView extends View {
private Bitmap mBitmap;
private int limitLength = ;
private int width;
private int heigth;
private static final int CLIP_HEIGHT = ;
private boolean status = HIDE;//顯示還是隐藏的狀态,最開始為HIDE
private static final boolean SHOW = true;//顯示圖檔
private static final boolean HIDE = false;//隐藏圖檔
public SampleView(Context context) {
super(context);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.image1);
limitLength = width = mBitmap.getWidth();
heigth = mBitmap.getHeight();
}
@Override
protected void onDraw(Canvas canvas) {
Region region = new Region();
int i = ;
while (i * CLIP_HEIGHT <= heigth) {//計算clip的區域
if (i % == ) {
region.union(new Rect(, i * CLIP_HEIGHT, limitLength, (i + ) * CLIP_HEIGHT));
} else {
region.union(new Rect(width - limitLength, i * CLIP_HEIGHT, width, (i + )
* CLIP_HEIGHT));
}
i++;
}
canvas.clipRegion(region);
canvas.drawBitmap(mBitmap, , , new Paint());
if (status == HIDE) {//如果此時是隐藏
limitLength -= ;
if(limitLength<=)
status=SHOW;
} else {//如果此時是顯示
limitLength += ;
if(limitLength>=width)
status=HIDE;
}
invalidate();
}
}
}
轉自:http://blog.csdn.net/lonelyroamer/article/details/8349601