public BitmapShader(Bitmap bitmap,TileMode titleX,TileMode tileY);
//TileMode.CLAMP:用边缘颜色来填充多余空间
//TileMode.REPEAT:用重复图像来填充多余空间
//TileMode.MIRROR: 用镜像来填充多余空间
//填充顺序,先填充竖向然后再填充横向
来看一个小例子:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(mBitmapBG == null){
mBitmapBG = Bitmap.createBitmap(200,200,Bitmap.Config.ARGB_8888);
Canvas canvas1 = new Canvas(mBitmapBG);
canvas1.drawBitmap(mBitmap,null,new Rect(0,0,200,200),mPaint);
}
if (mDx != -1 && mDy != -1) {
mPaint.setShader(new BitmapShader(mBitmapBG, Shader.TileMode.CLAMP,
Shader.TileMode.CLAMP));
canvas.drawCircle(mDx, mDy, 150, mPaint);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
mDx = event.getX();
mDy = event.getY();
postInvalidate();
return true;
case MotionEvent.ACTION_MOVE:
mDx = event.getX();
mDy = event.getY();
postInvalidate();
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
mDx = -1;
mDy = -1;
break;
}
postInvalidate();
return super.onTouchEvent(event);
}
我自己的理解,上面有三个比较关键canvas1,paint,canvas,这三者的角色就好比是一个版画
canvas1好比一个无形的需要印染的图案,如果图案想要1:1的印在canvas上,需要设置和canvas宽高相同,不然就会出现BitmapShader的多余填充效果, Canvas canvas1 = new Canvas(mBitmapBG);这里其实创建的是一个空白图层,没有绘制到canvas上,所以对于我们也是不可见的。
paint就好比是刻板,把canvas1对应位置的图案冲压到canvas。
canvas就好比作画的纸,最终呈现在用户视野里
在实际使用中,我们可以来实现圆角头像或使用bitmapShader.setLocalMatrix来对原图进行缩放等效果。
有趣的放大镜效果
public class TelescopeView extends View {
private Bitmap bitmap;
private ShapeDrawable drawable;
// 放大镜的半径
private static final int RADIUS = 80;
// 放大倍数
private static final int FACTOR = 3;
private final Matrix matrix = new Matrix();
public TelescopeView(Context context) {
super(context);
init();
}
public TelescopeView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TelescopeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final int x = (int) event.getX();
final int y = (int) event.getY();
// 这个位置表示的是绘制 Shader 的起始位置
matrix.setTranslate(RADIUS - x * FACTOR, RADIUS - y * FACTOR);
drawable.getPaint().getShader().setLocalMatrix(matrix);
drawable.setBounds(x - RADIUS, y - RADIUS, x + RADIUS, y + RADIUS);
invalidate();
return true;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (bitmap == null) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.
drawable.test1);
bitmap = Bitmap.createScaledBitmap(bmp, getWidth(), getHeight(),
false);
BitmapShader shader = new BitmapShader(Bitmap.createScaledBitmap
(bitmap,
bitmap.getWidth() * FACTOR, bitmap.getHeight() * FACTOR,
true),
Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
drawable = new ShapeDrawable(new OvalShape());
drawable.getPaint().setShader(shader);
}
canvas.drawBitmap(bitmap, 0, 0, null);
drawable.draw(canvas);
}
}