Android进阶(4)Paint实现几种效果
程序员文章站
2024-03-24 12:20:10
...
1.线性渐变 文字闪烁效果(聚光灯效果)
-
关于Shader.TileMode.CLAMP
-
CLAMP 如果当前的图片无法填满容器,则其在横/纵向上将最后一个像素拉伸
-
REPEAT 如果当前的图片无法填满容器,则其在横/纵向上复制一个去填充
-
MIRROR 如果当前的图片无法填满容器,则其在横/纵向上复制一个镜像去填充,需要注意的是横向上是左右镜像,纵向上是上下镜像
public class LinearGradientTextView extends AppCompatTextView { private Matrix mMatrix; private int mTranslateX = 10;//每次的平移量 private int mCurrentX;//当前平移的位置 private LinearGradient mGradient; private float mTextSize, mTextLength; public LinearGradientTextView(Context context, AttributeSet attrs) { super(context, attrs); } //在View的layout方法中调用 @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mTextSize = (mTextLength = getPaint().measureText(getText().toString().trim())) / getText().toString().length(); //因为需要的是聚光灯效果,开始和结束的颜色都应该和文本的颜色一致,中间的颜色用白色, //参数可以是多个,不一定是三个,根据需要的效果来确定 mGradient = new LinearGradient(-mTextSize * 3, 0, 0, 0, new int[]{Color.GRAY, Color.WHITE, Color.GRAY}, null, Shader.TileMode.CLAMP); mMatrix = new Matrix(); getPaint().setShader(mGradient); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mCurrentX += mTranslateX; if (mCurrentX > mTextLength + mTextSize * 3 || mCurrentX < 0) { mTranslateX = -mTranslateX; } //矩阵的平移函数 mMatrix.postTranslate(mTranslateX, 0); mGradient.setLocalMatrix(mMatrix); postInvalidateDelayed(10); } }
-
2.扫描式渐变 雷达扫描效果
public class RadarView extends View {
private int mWidth;
private int mHeight;
private int mDiameter;
private Paint mCirclePaint;
private Paint mRadarPaint;
private Matrix mMatrix;
public RadarView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mCirclePaint = new Paint();
mCirclePaint.setStyle(Paint.Style.STROKE);
mCirclePaint.setStrokeWidth(5);
mRadarPaint = new Paint();
mRadarPaint.setStyle(Paint.Style.FILL);
mMatrix = new Matrix();
mMatrix.postRotate(0);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mWidth == 0 && mHeight == 0) {
//此处减5的原因是画线是向外拓展,半径减5后加上画笔的宽度刚好到达布局边界
mDiameter = Math.min(mWidth = getMeasuredHeight(), mHeight = getMeasuredWidth()) - 5;
SweepGradient shader = new SweepGradient(mWidth >> 1, mHeight >> 1, Color.BLUE, Color.GRAY);
mRadarPaint.setShader(shader);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRoundRect((mWidth - mDiameter) >> 1, (mHeight - mDiameter) >> 1,
mWidth - ((mWidth - mDiameter) >> 1), mHeight - ((mHeight - mDiameter) >> 1),
mWidth >> 1, mHeight >> 1, mCirclePaint);
canvas.setMatrix(mMatrix);
canvas.drawCircle(mWidth >> 1, mHeight >> 1, mDiameter >> 1, mRadarPaint);
postInvalidateDelayed(30);
//矩阵的旋转函数,注意此处需要指明旋转的中心点,否则的话会按照0,0作为原点旋转
mMatrix.postRotate(2, mWidth >> 1, mHeight >> 1);
}
}
3.颜色矩阵运算
矩阵的运算 Amn * Bnl = Cml
public class ChannelView extends View {
private Bitmap mBitmap;
private Paint mPaint;
private Bitmap mTempBitmap;
private ColorMatrixColorFilter filter;
public ChannelView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.timg);
mBitmap = Bitmap.createScaledBitmap(mBitmap, mBitmap.getWidth() >> 1, mBitmap.getHeight() >> 1, false);
mTempBitmap = Bitmap.createBitmap(mBitmap, 0, 0, mBitmap.getWidth(), mBitmap.getHeight());
//底片效果,就是用255减去原来的数值
filter = new ColorMatrixColorFilter(new ColorMatrix(new float[]{
-1, 0, 0, 0, 255,
0, -1, 0, 0, 255,
0, 0, -1, 0, 255,
0, 0, 0, 1, 0
}));
//颜色增强,就是原来的倍数
filter = new ColorMatrixColorFilter(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.3f, 0
}));
//黑白 同一个通道中R+G+B=1且三个通道相同即可
filter = new ColorMatrixColorFilter(new ColorMatrix(new float[]{
0.2f, 0.7f, 0.1f, 0, 0,
0.2f, 0.7f, 0.1f, 0, 0,
0.2f, 0.7f, 0.1f, 0, 0,
0, 0, 0, 1, 0
}));
//复古效果
filter = new ColorMatrixColorFilter(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
}));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
mPaint.setColorFilter(filter);
canvas.drawBitmap(mTempBitmap, getMeasuredWidth() - mBitmap.getWidth(), 0, mPaint);
}
}
4.Xfermode的使用
- 关于PorterDuff.Mode
-
DST_IN 只在src和dst相交的地方绘制dst
-
DST_ATOP 只在src和dst相交的地方绘制dst,不相交的地方绘制src
-
DST_OUT 只在src和dst不相交的地方绘制dst
-
SRC_IN 只在src和dst相交的地方绘制src
-
SRC_ATOP 只在src和dst相交的地方绘制src,不相交的地方绘制dst
-
SRC_OUT 只在src和dst不相交的地方绘制src
public class WaveView extends View { private Bitmap mSrc, mDest; private Paint mPaint; private PorterDuffXfermode mXfermode; private int currentX; public WaveView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); mDest = BitmapFactory.decodeResource(getResources(), R.mipmap.wav);//波浪图 mSrc = BitmapFactory.decodeResource(getResources(), R.mipmap.circle);//圆形 mPaint = new Paint(); mXfermode = new PorterDuffXfermode(PorterDuff.Mode.DST_IN); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); if (mSrc.getWidth() > getMeasuredWidth() || mSrc.getHeight() > getMeasuredHeight()) { mSrc = createScaledBitmap(mSrc, getMeasuredWidth(), getMeasuredWidth(), false); } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); //首先保存当前的状态信息 int i = canvas.saveLayer(0, 0, getWidth(), getHeight(), mPaint, Canvas.ALL_SAVE_FLAG); //画目标图 canvas.drawBitmap(mDest, currentX, 0, mPaint); mPaint.setXfermode(mXfermode); //话源图 canvas.drawBitmap(mSrc, 0, 0, mPaint); //清理混合模式 mPaint.setXfermode(null); //还原状态信息 canvas.restoreToCount(i); currentX -= 20; if (Math.abs(currentX) > mDest.getWidth() - mSrc.getWidth()) { currentX = 0; } postInvalidateDelayed(10); } }
-
上一篇: 缩放图片
下一篇: JAVA获取多个经纬度的中心点