Android-UI-01-图形绘制-Paint

给paint设置渲染:

mPaint.setShader(bitMapShader);

!

1>位图渲染BitmapShader

BitmapShader.java  

public class MyGradientView extends View {

    private Paint mPaint;
    private Bitmap mBitMap = null;

    private int mWidth;
    private int mHeight;
    private int[] mColors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};

    public MyGradientView(Context context) {
        super(context);
        mBitMap = ((BitmapDrawable) getResources().getDrawable(R.drawable.xyjy2)).getBitmap();
        mPaint = new Paint();
        mWidth = mBitMap.getWidth();
        mHeight = mBitMap.getHeight();
    }

    public MyGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        mBitMap = ((BitmapDrawable) getResources().getDrawable(R.drawable.xyjy2)).getBitmap();
        mPaint = new Paint();
        mWidth = mBitMap.getWidth();
        mHeight = mBitMap.getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawColor(Color.WHITE);

        /**
         * 位图渲染,BitmapShader(@NonNull Bitmap bitmap, @NonNull TileMode tileX, @NonNull TileMode tileY)
         * Bitmap:构造shader使用的bitmap
         * tileX:X轴方向的TileMode
         * tileY:Y轴方向的TileMode
         */

        BitmapShader bitMapShader = new BitmapShader(mBitMap,Shader.TileMode.REPEAT,Shader.TileMode.REPEAT);
        mPaint.setShader(bitMapShader);
        mPaint.setAntiAlias(true);
        canvas.drawRect(new Rect(0, 0, 1000, 1600), mPaint);
    }

}

2>线性渲染LinearGradient

 private int[] mColors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};
        
           ...
           ...

        /**线性渲染
         * x0, y0, 起始点
         *  x1, y1, 结束点
         * int[]  mColors, 中间依次要出现的几个颜色
         * float[] positions 位置数组,position的取值范围[0,1],作用是指定几个颜色分别放置在那个位置上,
         * 如果传null,渐变就线性变化。
         *    tile 用于指定控件区域大于指定的渐变区域时,空白区域的颜色填充方法
         */
 
		LinearGradient linearGradient = new LinearGradient( 0, 0,800, 800,
                mColors, null, Shader.TileMode.CLAMP);
        // linearGradient = new LinearGradient(0, 0, 400, 400, mColors, null, Shader.TileMode.REPEAT);
		mPaint.setShader(linearGradient);
		canvas.drawRect(0, 0, 800, 800, mPaint);

效果图:

线性渲染类似歌词显示案列:

LinearGradientTextView.java

package com.dn_alan.myapplication.render;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;

import androidx.annotation.Nullable;
import androidx.appcompat.widget.AppCompatTextView;

/**
 * 线性渲染
 */

public class LinearGradientTextView extends AppCompatTextView {
    private LinearGradient mLinearGradient;
    private Matrix mGradientMatrix;
    private Paint mPaint;
    private int mViewWidth = 0;
    private int mTranslate = 0;

    private int delta = 15;

    public LinearGradientTextView(Context context) {
        super(context);
    }

    public LinearGradientTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mViewWidth == 0) {
            mViewWidth = getMeasuredWidth();
            if (mViewWidth > 0) {
                mPaint = getPaint();
                String text = getText().toString();
                //mViewWidth除字体总数就得到了每个字的像素    然后*3 表示3个文字的像素
                int size;
                if (text.length() > 0) {
                    size = mViewWidth / text.length() * 3;
                } else {
                    size = mViewWidth;
                }
                // 从左边-size开始,左边看不见的地方开始,滚动扫描过来
                mLinearGradient = new LinearGradient(-size, 0, 0, 0,
                        new int[]{0x33ffffff, 0xffffffff, 0x33ffffff},
                        new float[]{0, 0.2f, 1}, Shader.TileMode.CLAMP); //边缘融合
                mPaint.setShader(mLinearGradient);
                mGradientMatrix = new Matrix();
            }
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        float mTextWidth = getPaint().measureText(getText().toString());
        mTranslate += delta;
        /**
         * 如果位置已经移动到了整方了那个文字的地就开始往回滚动。
         * 但是如果小于1 了那么又开始递增,走另外一个逻辑
         */
        if (mTranslate > mTextWidth + 1 || mTranslate < 1) {
            delta = -delta;
        }
        mGradientMatrix.setTranslate(mTranslate, 0);
        mLinearGradient.setLocalMatrix(mGradientMatrix);
        //paint是textview的所以只需要不断色控制画笔的shader  然后利用矩阵控制位移即可
        postInvalidateDelayed(30);
    }
}

效果图:

 

3>环形渲染RadialGradient:

private int[] mColors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};
 
        /**
         * 环形渲染
         * centerX ,centerY:shader的中心坐标,开始渐变的坐标
         * radius:渐变的半径
         * centerColor,edgeColor:中心点渐变颜色,边界的渐变颜色
         * colors:渐变颜色数组
         * stops:渐变位置数组,类似扫描渐变的positions数组,取值[0,1],中心点为0,半径到达位置为1.0f
         * tileMode:shader未覆盖以外的填充模式
         */
RadialGradient mRadialGradient = new RadialGradient(300, 300, 100,
         mColors, null, Shader.TileMode.REPEAT);
		mPaint.setShader(mRadialGradient);
		canvas.drawCircle(300, 300, 300, mPaint);

效果:

 4>扫描渲染SweepGradient:

private int[] mColors = {Color.RED, Color.GREEN, Color.BLUE, Color.YELLOW};

        /**
         * 扫描渲染
         * cx,cy 渐变中心坐标
         * color0,color1:渐变开始结束颜色
         * colors,positions:类似LinearGradient,用于多颜色渐变,positions为null时,根据颜色线性渐变
         */       
 SweepGradient mSweepGradient = new SweepGradient(300, 300, mColors, null);
		mPaint.setShader(mSweepGradient);
		canvas.drawCircle(300, 300, 300, mPaint);

效果:

 案列:

RadarGradientView.java

package com.dn_alan.myapplication.render;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.util.AttributeSet;
import android.view.View;

import androidx.annotation.Nullable;

/**
 * 渐变渲染/梯度渲染
 */
public class RadarGradientView extends View {


    public RadarGradientView(Context context) {
        super(context);

        // 画圆用到的paint
        mPaintCircle = new Paint();
        mPaintCircle.setStyle(Paint.Style.STROKE); // 描边
        mPaintCircle.setStrokeWidth(1); // 宽度
        mPaintCircle.setAlpha(100); // 透明度
        mPaintCircle.setAntiAlias(true); // 抗锯齿
        mPaintCircle.setColor(Color.parseColor("#B0C4DE")); // 设置颜色 亮钢兰色

        // 扫描用到的paint
        mPaintRadar = new Paint();
        mPaintRadar.setStyle(Paint.Style.FILL_AND_STROKE); // 填充
        mPaintRadar.setAntiAlias(true); // 抗锯齿

        post(run);
    }

    public RadarGradientView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public RadarGradientView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }




    private int mWidth, mHeight;

    //五个圆
    private float[] pots = {0.05f, 0.1f, 0.15f, 0.2f, 0.25f};

    private Shader scanShader; // 扫描渲染shader
    private Matrix matrix = new Matrix(); // 旋转需要的矩阵
    private int scanSpeed = 5; // 扫描速度
    private int scanAngle; // 扫描旋转的角度

    private Paint mPaintCircle; // 画圆用到的paint
    private Paint mPaintRadar; // 扫描用到的paint



    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        for (int i = 0; i < pots.length; i++) {
            canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[i], mPaintCircle);
        }

        // 画布的旋转变换 需要调用save() 和 restore()
        canvas.save();

        scanShader = new SweepGradient(mWidth / 2, mHeight / 2,
                new int[]{Color.TRANSPARENT, Color.parseColor("#84B5CA")}, null);
        mPaintRadar.setShader(scanShader); // 设置着色器
        canvas.concat(matrix);
        canvas.drawCircle(mWidth / 2, mHeight / 2, mWidth * pots[4], mPaintRadar);

        canvas.restore();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 取屏幕的宽高是为了把雷达放在屏幕的中间
        mWidth = getMeasuredWidth();
        mHeight = getMeasuredHeight();
        mWidth = mHeight = Math.min(mWidth, mHeight);
    }

    private Runnable run = new Runnable() {
        @Override
        public void run() {
            scanAngle = (scanAngle + scanSpeed) % 360; // 旋转角度 对360取余
            matrix.postRotate(scanSpeed, mWidth / 2, mHeight / 2); // 旋转矩阵
            invalidate(); // 通知view重绘
            postDelayed(run, 50); // 调用自身 重复绘制
        }
    };

}

雷达扫描效果:静态图实际会动

滤镜:

!

FilterView.java  (使用颜色矩阵实现底片效果、颜色增强、黑白照片、复古等效果)
package com.dn_alan.myapplication.filter;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.EmbossMaskFilter;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.RectF;
import android.view.MotionEvent;
import android.view.View;

import com.dn_alan.myapplication.R;


public class FilterView extends View {

    Paint paint;

    Bitmap bitmap;

    public FilterView(Context context) {
        super(context);
        init();
    }

    private void init() {

        paint = new Paint(Paint.ANTI_ALIAS_FLAG);
        paint.setColor(Color.RED);

        bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.xyjy2);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        //关闭单个View的硬件加速功
//      setLayerType(View.LAYER_TYPE_SOFTWARE,null);
//
        RectF rectF = new RectF(200,100,bitmap.getWidth()+200,bitmap.getHeight());
        paint.reset();

        canvas.drawBitmap(bitmap,null, rectF,paint);

        // 平移运算---加法
//        ColorMatrix colorMartrix = new ColorMatrix(new float[]{
//                1, 0,0,0,0,
//                0,1,0,0,100,
//                0,0,1,0,0,
//                0,0,0,1,0,
//        });

        // 反相效果 -- 底片效果
//       ColorMatrix colorMartrix = new ColorMatrix(new float[]{
//                -1, 0,0,0,255,
//                0,-1,0,0,255,
//                0,0,-1,0,255,
//                0,0,0,1,0,
//        });

        // 缩放运算---乘法 -- 颜色增强
//        ColorMatrix colorMartrix = new ColorMatrix(new float[]{
//                1.2f, 0,0,0,0,
//                0,1.2f,0,0,0,
//                0,0,1.2f,0,0,
//                0,0,0,1.2f,0,
//        });

         /** 黑白照片
          *是将我们的三通道变为单通道的灰度模式
          *去色原理:只要把R G B 三通道的色彩信息设置成一样,那么图像就会变成灰色,
          *同时为了保证图像亮度不变,同一个通道里的R+G+B =1
          */
//        ColorMatrix colorMartrix = new ColorMatrix(new float[]{
//                0.213f, 0.715f,0.072f,0,0,
//                0.213f, 0.715f,0.072f,0,0,
//                0.213f, 0.715f,0.072f,0,0,
//                0,0,0,1,0,
//        });


        // 发色效果---(比如红色和绿色交换)
//        ColorMatrix colorMartrix = new ColorMatrix(new float[]{
//                1,0,0,0,0,
//                0, 0,1,0,0,
//                0,1,0,0,0,
//                0,0,0,0.5F,0,
//        });

        // 复古效果
//        ColorMatrix colorMartrix = new ColorMatrix(new float[]{
//                1/2f,1/2f,1/2f,0,0,
//                1/3f, 1/3f,1/3f,0,0,
//                1/4f,1/4f,1/4f,0,0,
//                0,0,0,1,0,
//        });

        // 颜色通道过滤
        //两个矩阵
        //本身颜色矩阵 A
        //过滤矩阵  c
        //a*c=out color
        ColorMatrix colorMartrix = new ColorMatrix(new float[]{
                1.3F,0,0,0,0,
                0,1.3F,0,0,0,
                0,0,1.3F,0,0,
                0,0,0,1,0,
        });

        RectF rectF2 = new RectF(200,100 + bitmap.getHeight(),bitmap.getWidth()+200,bitmap.getHeight() * 2);
        paint.setColorFilter(new ColorMatrixColorFilter(colorMartrix));
        canvas.drawBitmap(bitmap,null, rectF2,paint);
    }


}

Xfermode:

!

PorterDuff所有模式:https://developer.android.google.cn/reference/android/graphics/PorterDuff.Mode?hl=en#ADD

!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值