BitmapShader初步认识

参考文章链接:
自定义控件其实很简单1/3
Android BitmapShader 实战 实现圆形、圆角图片

这两天在看android中android.graphics.Paint类的时候关注到一个方法:

/**
 * Set or clear the shader object.
 * <p />
 * Pass null to clear any previous shader.
 * As a convenience, the parameter passed is also returned.
 *
 * @param shader May be null. the new shader to be installed in the paint
 * @return       shader
 */
public Shader setShader(Shader shader) {
    long shaderNative = 0;
    if (shader != null)
        shaderNative = shader.getNativeInstance();
    native_setShader(mNativePaint, shaderNative);
    mShader = shader;
    return shader;
}

它的作用呢,就是为画笔着色,现在我们先看一个着色器 BitmapShader,它的构造方法如下:

/**
 * Call this to create a new shader that will draw with a bitmap.
 *
 * @param bitmap            The bitmap to use inside the shader
 * @param tileX             The tiling mode for x to draw the bitmap in.
 * @param tileY             The tiling mode for y to draw the bitmap in.
 */
public BitmapShader(Bitmap bitmap, TileMode tileX, TileMode tileY) {
    mBitmap = bitmap;
    mTileX = tileX;
    mTileY = tileY;
    final long b = bitmap.ni();
    init(nativeCreate(b, tileX.nativeInt, tileY.nativeInt));
}

构造方法中的三个参数,第一个是一个Bitmap对象,而另外两个是什么鬼?我翻了源码之后发现它是在BitmapShader类内定义的一个枚举类型,如下:

public enum TileMode {
    /**
     * 拉伸最后一排或一列像素
     * replicate the edge color if the shader draws outside of its
     * original bounds
     */
    CLAMP   (0),
    /**
     * repeat the shader's image horizontally and vertically
     */
    REPEAT  (1),
    /**
     * repeat the shader's image horizontally and vertically, alternating
     * mirror images so that adjacent images always seam
     */
    MIRROR  (2);

    TileMode(int nativeInt) {
        this.nativeInt = nativeInt;
    }
    final int nativeInt;
}

代码很简洁,意思也很明了,TileMode的取值有三种:

  • CLAMP 拉伸 这个和电脑屏保的模式应该有些不同,这个拉伸的是图片边缘的那列或一行像素

  • REPEAT 重复 就是横向、纵向不断重复这个bitmap

  • MIRROR 镜像 横向不断翻转重复,纵向不断翻转重复

那我们通过下面这张图片来实际看一下BitmapShader的使用:

这里写图片描述

首先,我们先初始化Paint对象:

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaintBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat);
mPaint.setShader(new BitmapShader(mPaintBitmap, TileMode.CLAMP, TileMode.CLAMP));

然后在onDraw方法中,用这个Paint对象画出来:

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);//画满整个画布
}

结果如下:
这里写图片描述

经过排列组合,结果就是这个样子:

这里写图片描述 这里写图片描述 这里写图片描述

看了上面的东东之后,我们尝试在view的画布上画一个局部图案,选的属性是这个:

int[] screenSize = getScreenSize(context);

int screenCenterX = screenSize[0] / 2;
int screenCenterY = screenSize[1] / 2;

left = screenCenterX - HALF_RECT_SIZE;
top = screenCenterY - HALF_RECT_SIZE;
right = screenCenterX + HALF_RECT_SIZE;
bottom = screenCenterY + HALF_RECT_SIZE;

mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG);
mPaintBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.cat);
mPaint.setShader(new BitmapShader(mPaintBitmap, TileMode.CLAMP, TileMode.CLAMP));

onDraw方法中这么写:

@Override
protected void onDraw(Canvas canvas) {
    canvas.drawRect(left, top, right, bottom, mPaint);
}

现在,我们先想象一下view样子是什么样:在view的中间有一个矩形,矩形的左上角是一个猫脸,其余部分是被拉伸出来的样子。

那么我们来看一下实际效果,WTF!!怎么是这个鬼样子??

这里写图片描述

其实,对比上面描述TileMode时用到的图,我们就会发现,我们用BitmapShaser修饰Paint对象的时候,Bitmap变换的起始位置并不是和Paint所绘制图形关联的,而是和Canvas对象相关的。所以,Bitmap的的起始位置其实是在Canvas的左上角,因此我们在Canvas的中间位置画矩形的时候才会显示现在这个鬼样子。

鉴于有的同学可能不相信,于是我就在Canvas的不同位置使用同一个Paint对象绘制图形,结果如下:
这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述 这里写图片描述

嗯,就是这样。

完:)

求助: 有哪位大神知道如何比较方便的从Android设备上截取出一个Gif动图出来,请帮忙留个言呀,老是截取一堆的图放上来是在是有点low呀

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值