自定义控件其实很简单(笔记一)

2016-04-15  本文已影响203人  北疆_

目录

姿势点

ColorFilter


** ColorMatrix**

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        1, 0, 0, 0, 0,
        0, 1, 0, 0, 0,
        0, 0, 1, 0, 0,
        0, 0, 0, 1, 0,
});

Usage

// 生成色彩矩阵
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0.5F, 0, 0, 0, 0, /*1表示不变颜色*/
        0, 0.5F, 0, 0, 0,
        0, 0, 0.5F, 0, 0,
        0, 0, 0, 1, 0,
});
mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));

数学原理是:

ColorMatrix

实践效果

原图

Demo1

// 生成色彩矩阵
ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0.5F, 0, 0, 0, 0,
        0, 0.5F, 0, 0, 0,
        0, 0, 0.5F, 0, 0,
        0, 0, 0, 1, 0,
});
mPaint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
Demo1

Demo2

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0.33F, 0.59F, 0.11F, 0, 0,
        0.33F, 0.59F, 0.11F, 0, 0,
        0.33F, 0.59F, 0.11F, 0, 0,
        0, 0, 0, 1, 0,
});
Demo2

Demo3

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        -1, 0, 0, 1, 1,
        0, -1, 0, 1, 1,
        0, 0, -1, 1, 1,
        0, 0, 0, 1, 0,
});
Demo3

Demo4

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0.393F, 0.769F, 0.189F, 0, 0,
        0.349F, 0.686F, 0.168F, 0, 0,
        0.272F, 0.534F, 0.131F, 0, 0,
        0, 0, 0, 1, 0,
});
Demo4

Demo5 红色的变成了蓝色而蓝色的就变成了红色

ColorMatrix colorMatrix = new ColorMatrix(new float[]{
        0, 0, 1, 0, 0,
        0, 1, 0, 0, 0,
        1, 0, 0, 0, 0,
        0, 0, 0, 1, 0,
});
Demo5

LightingColorFilter
A color filter that can be used to simulate simple lighting effects.
[LightingColorFilter](http://developer.android.com/reference/android/graphics/LightingColorFilter.html#LightingColorFilter(int, int)) (int mul, int add)

R' = R * colorMultiply.R + colorAdd.R 
G' = G * colorMultiply.G + colorAdd.G 
B' = B * colorMultiply.B + colorAdd.B

usage:

//设置颜色过滤后为黄色  
mPaint.setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0X00FFFF00));  
 mPaint.setColorFilter(null);   //还原本色  

PorterDuffColorFilter

混合模式

Paint.setXfermode(Xfermode xfermode)

Xfermode
AvoidXfermode

AvoidXfermode.Mode.TARGET
在该模式下Android会判断画布上的颜色是否会有跟opColor不一样的颜色,比如我opColor是红色,那么在TARGET模式下就会去判断我们的画布上是否有存在红色的地方,如果有,则把该区域“染”上一层我们画笔定义的颜色,否则不“染”色,而tolerance容差值则表示画布上的像素和我们定义的红色之间的差别该是多少的时候才去“染”的,比如当前画布有一个像素的色值是(200, 20, 13),而我们的红色值为(255, 0, 0),当tolerance容差值为255时,即便(200, 20, 13)并不等于红色值也会被“染”色,容差值越大“染”色范围越广反之则反.
Usage:

 avoidXfermode = new AvoidXfermode(0XFFFFFFFF, 0, AvoidXfermode.Mode.TARGET);  
mPaint.setXfermode(avoidXfermode);  

API 16+没有关闭硬件加速


API 16以下关闭硬件加速



符合条件的效果,在我们的模式为TARGET容差值为0的时候此时只有当图片中像色颜色值为0XFFFFFFFF的地方才会被染色,而其他地方不会有改变,而当容差值为255的时候只要是跟0XFFFFFFFF有点接近的地方都会被染色。


Paste_Image.png

AvoidXfermode.Mode.AVOID
AVOID是我们指定的颜色是否与画布不一样
AvoidXfermode(0XFFFFFFFF, 0, AvoidXfermode.Mode.AVOID):


当模式为AVOID容差值为0时,只有当图片中像素颜色值与0XFFFFFFFF完全不一样的地方才会被染色
AvoidXfermode(0XFFFFFFFF, 255, AvoidXfermode.Mode.AVOID):


当容差值为255时,只要与0XFFFFFFFF稍微有点不一样的地方就会被染色
那么这玩意究竟有什么用呢?比如说当我们只想在白色的区域画点东西或者想把白色区域的地方替换为另一张图片的时候就可以采取这种方式!

PixelXorXfermode

PorterDuffXfermode

 paint.setXfermode( new PorterDuffXfermode(PorterDuff.Mode.SCREEN);

PorterDuffXfermode高级姿势


两个图像混合,较深的颜色总是会覆盖较浅的颜色,如果两者深浅相同则混合,如图,黄色覆盖了红色而蓝色和青色因为是跟透明混合所以不变.


两张图合成去掉美女头上的字

    
         // 先绘制dis目标图
        canvas.drawBitmap(bitmapDis, x, y, mPaint);
        // 设置混合模式
        mPaint.setXfermode(PorterDuff.Mode.DST_IN);
        // 再绘制src源图
        canvas.drawBitmap(bitmapSrc/*黑色底图*/, x, y, mPaint);
        // 还原混合模式
        mPaint.setXfermode(null);
        // 还原画布
        canvas.restoreToCount(sc);

Paint 之 Font

FontMetrics

Summary
            
         mFontMetrics = mPaint.getFontMetrics();
        Log.d("Aige", "ascent:" + mFontMetrics.ascent);
        Log.d("Aige", "top:" + mFontMetrics.top);
        Log.d("Aige", "leading:" + mFontMetrics.leading);
        Log.d("Aige", "descent:" + mFontMetrics.descent);
        Log.d("Aige", "bottom:" + mFontMetrics.bottom);
Log.d()——文字只有一行,故leading为零
StaticLayout结合TextPaint实现换行
mStaticLayout = new StaticLayout(TEXT, mTextPaint, canvas.getWidth(), Alignment.ALIGN_NORMAL, 1.0F, 0.0F, false);  
mStaticLayout.draw(canvas);  

Paint 之方法解析

//系统自带
textPaint.setTypeface(Typeface.create("SERIF", Typeface.NORMAL));
textPaint.setTypeface(Typeface.create(Typeface.SERIF, Typeface.NORMAL));
//自定义字体 一
createFromAsset(AssetManager mgr, String path)
createFromFile(String path)和createFromFile(File path)
//自定义字体 二
// 获取字体并设置画笔字体
Typeface typeface = Typeface.createFromAsset(context.getAssets(), "kt.ttf");
textPaint.setTypeface(typeface);

** setMaskFilter(MaskFilter maskfilter) **

BlurMaskFilter
BlurMaskFilter(float radius, BlurMaskFilter.Blur style) 是根据Alpha通道的边界来计算模糊的

mPaint.setMaskFilter(new BlurMaskFilter(20, BlurMaskFilter.Blur.SOLID));

SOLID: 在图像的Alpha边界外产生一层与Paint颜色一致的阴影效果而不影响图像本身,而NORMAL,OUTER和INNER,NORMAL会将整个图像模糊掉:

而NORMAL会在Alpha边界外产生一层阴影且会将原本的图像变透明 OUTER会在Alpha边界外产生一层阴影且会将原本的图像变透明: INNER则会在图像内部产生模糊:
        // 获取位图的Alpha通道图
        shadowBitmap = srcBitmap.extractAlpha();
        // 先绘制阴影
        canvas.drawBitmap(shadowBitmap, x, y, shadowPaint);ps
        // 再绘制位图
        canvas.drawBitmap(srcBitmap, x, y, null);
效果
EmbossMaskFilter让你绘制的图像感觉像是从屏幕中“凸”起来更有立体感一样(在设计软件中类似的效果称之为斜面浮雕)。
public EmbossMaskFilter (float[] direction, float ambient, float specular, float blurRadius)

setPathEffect(PathEffect effect)

PathEffect 六个子类分别可以实现不同的路径效果

setShadowLayer(float radius, float dx, float dy, int shadowColor)

/**
     * 初始化画笔
     */
    private void initPaint() {
        // 实例化画笔
        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPaint.setColor(Color.RED);
        mPaint.setStyle(Style.FILL);
        mPaint.setShadowLayer(10, 3, 3, Color.DKGRAY);
    }
setShadowLayer

Shader

Shader

BitmapShader
[BitmapShader](http://developer.android.com/reference/android/graphics/BitmapShader.html#BitmapShader(android.graphics.Bitmap, android.graphics.Shader.TileMode, android.graphics.Shader.TileMode))(Bitmap bitmap, Shader.TileMode tileX, Shader.TileMode tileY)
Usage:
mPaint.setShader(new BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR));
Shader.TileMode

BitmapShader(bitmap, Shader.TileMode.MIRROR, Shader.TileMode.MIRROR) BitmapShader(bitmap, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT) BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.MIRROR)

LinearGradient

positions[] =null, 各颜色均分

应用案例图片1——倒影:

reflect
        // 实例化一个矩阵对象
        Matrix matrix = new Matrix();
        matrix.setScale(1F, -1F);
        // 生成倒影图
        mRefBitmap = Bitmap.createBitmap(mSrcBitmap, 0, 0, mSrcBitmap.getWidth(), mSrcBitmap.getHeight(), matrix, true);
        //生产消失渐变
        mPaint.setShader(
                        new LinearGradient(x, y + mSrcBitmap.getHeight(), x,
                                y + mSrcBitmap.getHeight() + mSrcBitmap.getHeight() / 4,
                                0xAA000000, Color.TRANSPARENT, Shader.TileMode.CLAMP));

    //合成效果
    mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN);
    
    public void onDraw(Canvas canvas){
        canvas.draw(srcBitmap);
        int sc = canvas.saveLayer(......,null,Canvas.ALL_SAVE_FLAG) ;
        
        canvas.draw(mRefBitmap)
        mPaint.setXfermode(mXfermode) ;
        canvas.drawRect(left,top,right,bottom,mPaint) ;
        mPaint.setXfermode(mXfermode);
        canvas.restoreToCount(sc) ;
    }

应用案例图片2-(去饱和、提亮、色相矫正)
姿势诀窍第一式:


专业术语之梦幻特效
        // 实例化混合模式
        mXfermode = new PorterDuffXfermode(PorterDuff.Mode.SCREEN);
        // 去饱和、提亮、色相矫正
        mBitmapPaint.setColorFilter(new ColorMatrixColorFilter(
                new float[] {
                        0.8587F, 0.2940F, -0.0927F, 0, 6.79F,
                        0.0821F, 0.9145F, 0.0634F, 0, 6.79F,
                        0.2019F, 0.1097F, 0.7483F, 0, 6.79F,
                        0, 0, 0, 1, 0
                }));
    protected void onDraw(Canvas canvas){
        int sc = canvas.saveLayer(...,null,Canvas.ALL_SAVE_FLAG) ;
        canvas.drawColor(0xcc1c093e) ;
        mPaint.setXfermode(mXfermode) ;
        canvas.drawBitmap(bitmap,x,y,mPaint) ;
        mPaint.setXfermode(null) ;
        canvas.restoreToCount(sc) ;
    }

模拟单反相机的暗角效果,压暗图片周围的颜色亮度提亮中心:

姿势诀窍第二式:


RadialGradientPs.png
      onDraw() 最后添加
        // 实例化混合模式
        // 中心颜色为透明而边缘颜色为黑色
        mShaderPaint.setShader(new RadialGradient(screenW / 2, screenH / 2,
                mBitmap.getHeight() * 7 / 8, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP));
        // 绘制一个跟图片大小一样的矩形
        canvas.drawRect(x, y, x + mBitmap.getWidth(), y + mBitmap.getHeight(), mShaderPaint);

姿势二存在的问题:

姿势2.1 矩阵亮相

MatrixPs.png
    // 根据我们源图的大小生成暗角Bitmap
        darkCornerBitmap = Bitmap.createBitmap(mBitmap.getWidth(), mBitmap.getHeight(), Bitmap.Config.ARGB_8888);
        // 将该暗角Bitmap注入Canvas
        Canvas canvas = new Canvas(darkCornerBitmap);
        // 计算径向渐变半径
        float radiu = canvas.getHeight() * (2F / 3F);
        // 实例化Shader图形的画笔
        mShaderPaint = new Paint();
        // 设置径向渐变,渐变中心当然是图片的中心也是屏幕中心,渐变半径我们直接拿图片的高度但是要稍微小一点
        // 中心颜色为透明而边缘颜色为黑色
        RadialGradient radialGradient = new RadialGradient(screenW / 2 , screenH / 2 ,
                mBitmap.getHeight() * 7 / 8, Color.TRANSPARENT, Color.BLACK, Shader.TileMode.CLAMP);
        // 实例化一个矩阵
        Matrix matrix = new Matrix();
        // 设置矩阵的缩放
        matrix.setScale(canvas.getWidth() / (radiu * 2F), 1.0F);
        // 设置矩阵的预平移
        matrix.preTranslate(((radiu * 2F) - canvas.getWidth()) / 2F, 0);
        // 将该矩阵注入径向渐变
        radialGradient.setLocalMatrix(matrix);
        mShaderPaint.setShader(radialGradient);
        // 绘制矩形
        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), mShaderPaint);
               把姿势二onDraw换成
        //绘制我们画好的径向渐变图      
        canvas.drawBitmap(darkCornerBitmap, x, y, null);
上一篇 下一篇

猜你喜欢

热点阅读