您的位置:首页 > 其它

shader初探之BitmapShader

2015-09-10 15:34 309 查看
public BitmapShader(Bitmap bitmap,Shader.TileMode tileX,Shader.TileMode tileY)

调用这个方法来产生一个画有一个位图的渲染器(Shader)。

bitmap 在渲染器内使用的位图

tileX The tiling mode for x to draw the bitmap in. 在位图上X方向渲染器平铺模式

tileY The tiling mode for y to draw the bitmap in. 在位图上Y方向渲染器平铺模式

TileMode:

CLAMP :如果渲染器超出原始边界范围,会复制范围内边缘染色。

REPEAT :横向和纵向的重复渲染器图片,平铺。

MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT重复方式不一样,他是以镜像方式平铺。

下面说下Shader的使用步骤:

1. 构建Shader对象

2. 通过Paint的setShader方法设置渲染对象

3.绘制时使用这个Paint对象

activity代码:

package com.example.shader;

import android.app.Activity;
import android.graphics.*;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;

public class MyActivity extends Activity {
    ImageView image;
    int width,height;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        image = (ImageView) findViewById(R.id.image);
        width = ValueUtil.dp2px(this,300);
        height = ValueUtil.dp2px(this,300);

        Bitmap bitmap = BitmapFactory.decodeResource(getResources(),R.drawable.tupian); //创建bitmap时会依据屏幕密度缩放,如density为2,drawable-xhdpi下的图片不缩放
        Log.e("bitmapwh",bitmap.getWidth()+"+"+bitmap.getHeight()); //352*220
//        TileMode:
//        CLAMP  :如果渲染器超出原始边界(在这个例子中是bitmap的边界)范围,会复制范围内边缘染色,边缘拉伸.
//        REPEAT :横向和纵向的重复渲染器图片,平铺。
//        MIRROR :横向和纵向的重复渲染器图片,这个和REPEAT重复方式不一样,他是以镜像方式平铺,倒影式平铺
        BitmapShader bitmapShader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

        Bitmap bitmapTemp = Bitmap.createBitmap(width,height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmapTemp);

        /* 第一种使用方式*/
        Paint paint = new Paint();
        paint.setShader(bitmapShader);
        canvas.drawRect(new RectF(0, 0, width, height), paint);
//        canvas.drawArc(new RectF(0,0,width,height),90,180,false,paint);
//        canvas.drawOval(new RectF(0,0,width,height),paint);

        /* 第二种使用方式
        ShapeDrawable shapeDrawable = new ShapeDrawable(new OvalShape());
        //得到画笔并设置渲染器
        shapeDrawable.getPaint().setShader(bitmapShader);
        //设置显示区域
        shapeDrawable.setBounds(0, 0, width,height);
        //绘制shapeDrawable
        shapeDrawable.draw(canvas);
        */

        image.setImageBitmap(bitmapTemp);

    }
}


效果图:

CLAMP:






REPEAT :






MIRROR



代码中第一种方式中的canvas.drawOval(new RectF(0,0,width,height),paint)的效果与第二种方式相同,效果图如下:



第二种方式其原理就是canvas的draw系列方法。

我们看shapeDrawable.draw(canvas);的源码:
public void draw(Canvas canvas) {
        final Rect r = getBounds();
        final ShapeState state = mShapeState;
        final Paint paint = state.mPaint;

        final int prevAlpha = paint.getAlpha();
        paint.setAlpha(modulateAlpha(prevAlpha, state.mAlpha));

        // only draw shape if it may affect output
        if (paint.getAlpha() != 0 || paint.getXfermode() != null || paint.hasShadowLayer()) {
            final boolean clearColorFilter;
            if (mTintFilter != null && paint.getColorFilter() == null) {
                paint.setColorFilter(mTintFilter);
                clearColorFilter = true;
            } else {
                clearColorFilter = false;
            }

            if (state.mShape != null) {
                // need the save both for the translate, and for the (unknown)
                // Shape
                final int count = canvas.save();
                canvas.translate(r.left, r.top);
                onDraw(state.mShape, canvas, paint);
                canvas.restoreToCount(count);
            } else {
                canvas.drawRect(r, paint);
            }

            if (clearColorFilter) {
                paint.setColorFilter(null);
            }
        }

        // restore
        paint.setAlpha(prevAlpha);
    }


关键代码onDraw(state.mShape, canvas, paint);继续:

/**
     * Called from the drawable's draw() method after the canvas has been set to
     * draw the shape at (0,0). Subclasses can override for special effects such
     * as multiple layers, stroking, etc.
     */
    protected void onDraw(Shape shape, Canvas canvas, Paint paint) {
        shape.draw(canvas, paint);
    }
继续看shape的draw方法,发现其是一个抽象方法,shape是个抽象类,在本例中,我们找shape子孙类OvalShape的draw方法。

@Override
    public void draw(Canvas canvas, Paint paint) {
        canvas.drawOval(rect(), paint);
    }
其参数canvas就是我们最初shapeDrawable.draw(canvas)传入的canvas.

View关于背景drawable的绘制

view的draw()方法中会调用drawBackground(Canvas canvas)方法,该方法中调用了background.draw(canvas);而background是setBackgroundDrawable(Drawable background)
设置的。Drawable是抽象类,本例中的ShapeDrawable是其子类。




参考资料:/article/1875781.html

源码:http://yunpan.cn/c3f2qgcVtNSwP (提取码:2ccf)

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: