内容太多,尚未完工,估计得写到这个周末
得知道16ms一帧的问题,如果渲染一帧超过16ms,如用了20ms渲染,下一帧的切换就来不及,这一帧就持续了32ms,就出现了掉帧,掉帧多了,用户就会感觉到界面卡顿
/**
* 自定义控件:绘制一个圆环
*/
public class CustomView1 extends View{
private Paint mPaint;
public CustomView1(Context context) {
super(context);
initPaint();
}
public CustomView1(Context context, AttributeSet attrs) {
super(context, attrs);
initPaint();
}
public CustomView1(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaint();
}
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public CustomView1(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initPaint();
}
private void initPaint(){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
/*
* 设置画笔样式为描边,圆环嘛……当然不能填充不然就么意思了
*
* 画笔样式分三种:
* 1.Paint.Style.STROKE:描边
* 2.Paint.Style.FILL_AND_STROKE:描边并填充
* 3.Paint.Style.FILL:填充
*/
mPaint.setStyle(Paint.Style.STROKE);
// 设置画笔颜色为浅灰色
mPaint.setColor(Color.LTGRAY);
/*
* 设置描边的粗细,单位:像素px
* 注意:当setStrokeWidth(0)的时候描边宽度并不为0而是只占一个像素
*/
mPaint.setStrokeWidth(10);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// 绘制圆环
canvas.drawCircle(Display.screenWidth / 2, Display.screenHeight / 2, radius, mPaint);
}
private float radius = 50;
public void setRadius(float r){
this.radius = r;
if(this.radius >= 150) this.radius = 50;
postInvalidate();
}
}
如果你在外部用动画或者其他方式不断调用setRadius,圆环就动起来了
这里注意invalidate和postInvalidate,还有requestLayout
可惜这里没图
canvas是纸,paint是笔
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(); //just demo
paint.setAntiAlias(true);
}
canvas.drawARGB();
canvas.drawColor();
canvas.drawPaint();
canvas.drawPoint();
canvas.drawPoints();
canvas.drawLine();
canvas.drawLines();
canvas.drawPath();
canvas.drawArc();
canvas.drawCircle();
canvas.drawOval();
canvas.drawRect();
canvas.drawRoundRect();
canvas.drawText();
canvas.drawTextOnPath();
canvas.drawTextRun();
canvas.drawBitmap();
canvas.drawPicture();
canvas.drawVertices();
canvas.translate();
canvas.scale();
canvas.rotate();
canvas.skew();
canvas.setDrawFilter();
canvas.setMatrix();
canvas.setDensity();
canvas.setBitmap();
canvas.save();
canvas.saveLayer();
canvas.restore();
canvas.restoreToCount();
canvas.clipPath();
canvas.clipRect();
canvas.concat();
canvas.isHardwareAccelerated();
canvas.isOpaque();
canvas.quickReject();
Paint paint = new Paint();
paint.setAntiAlias(true);
或者mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
抗锯齿,让图像边缘显得更圆滑光泽动感的算法
抗锯齿,锯齿是依赖于算法的,算法决定抗锯齿的效率,在我们绘制棱角分明的图像时,比如一个矩形、一张位图,我们不需要打开抗锯齿
mPaint.setDither(false);
抗抖动,使颜色的过渡更柔和
mPaint.set(Paint src);
把另一个画笔的属性设置Copy过来
mPaint.setAlpha(255); //[0..255]
mPaint.setARGB(a, r, g, b); // 和setColor一样,这里每个值都是(0..255)
mPaint.setColor(Color.BLUE);
mPaint.setFlags(int flags);
mPaint.setStyle(Paint.Style style);
Paint.Style.FILL 填充
Paint.Style.STROKE 画边框
Paint.Style.FILL_AND_STROKE 即填充,也画边框
//边框样式
mPaint.setStrokeCap(Cap cap);
mPaint.setStrokeJoin(Join join);
mPaint.setStrokeMiter(float miter);
mPaint.setStrokeWidth(float width);
//什么
mPaint.setFilterBitmap(false);
//颜色矩阵:对颜色进行过滤,即对颜色进行变换,可以实现滤镜
//ColorMatrixColorFilter
//LightingColorFilter:光照颜色过滤
//PorterDuffColorFilter:画布图像和指定颜色的混合模式
mPaint.setColorFilter();
//BlurMaskFilter,模糊处理,阴影效果; EmbossMaskFilter,浮雕处理,使图像凸起,有立体感
mPaint.setMaskFilter(MaskFilter mf);
//路径
mPaint.setPathEffect(PathEffect pe);
//图像混合:画两层图像,指定二者的混合算法,就能得到各种效果
mPaint.setXfermode(Xfermode xfermode);
//BitmapShader:使用一个位图作为画刷,用这个位图来画图形
//LinearGradient:线性渐变
//RadialGradient:辐射渐变
//SweepGradient:扫描渐变
//可以画阴影,遮罩等,功能也很强大
mPaint.setShader(Shader shader);
//已废弃
//设置光栅,光栅这东西涉及太多太多物理知识,而且该方法同样不支持HW在API 21中遗弃了
mPaint.setRasterizer(Resterizer rasterizer);
mPaint.setShadowLayer(float radius, float dx, float dy, int shadowColor);
///画文字相关的,后面会单独分析字体相关
mPaint.setTextAlign(Align align);
mPaint.setTextLocale(Locale.CHINESE);
mPaint.setTextScaleX(float scaleX);
mPaint.setTextSize(float textSize);
mPaint.setTextSkewX(float skewZ);
mPaint.setTypeface(Typeface typeface);
mPaint.setFakeBoldText(false);
mPaint.setLinearText(false);
mPaint.setStrikeThruText(false);
mPaint.setUnderlineText(false);
mPaint.setSubpixelText(false);
mPaint.setHinting(int mode);
大家看到的这张七彩渐变图是一张RGB565模式下图片,即便图片不是很大我们依然可以很清晰地看到在两种颜色交接的地方有一些色块之类的东西感觉很不柔和,因为在RGB模式下只能显示2^16=65535种色彩,因此很多丰富的色彩变化无法呈现,而Android呢为我们提供了抗抖动这么一个方法,它会将相邻像素之间颜色值进行一种“中和”以呈现一个更细腻的过渡色
放大来看,其在很多相邻像素之间插入了一个“中间值”
抗抖动不是Android的专利,是图形图像领域的一种解决位图精度的技术
AvoidXfermode和PixelXorXfermode已被废弃(因为不支持硬件加速在API 16已经过时了)
常用的就是PorterDuffXfermode(图形混合模式)
LinearGradient:线性渐变
RadialGradient:辐射渐变
SweepGradient:扫描渐变
渐变可以给图像加浮层,周围最模糊,中间最清楚
BlurMaskFilter和EmbossMaskFilter
网格化
下面自定义一个圆角显示图片的Drawable,可以作为ImageView的src,或者作为background
package com.ayoview.sample.deepmind;
import android.graphics.Bitmap;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.RectF;
import android.graphics.Shader;
import android.graphics.drawable.Drawable;
import org.ayo.jlog.JLog;
/**
* 圆角drawable
* 实现方式是将Bitmap作为BitmapShader,来画一个圆角矩形
* 注意draw方法里的canvas.drawRoundRect()方法,这里canvas画个什么形状,就可以显示什么形状的图片
*/
public class RoundImageDrawable extends Drawable{
private Paint mPaint;
private Bitmap mBitmap;
private RectF rectF;
public RoundImageDrawable(Bitmap bitmap){
this.mBitmap = bitmap;
//初始化paint
BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setShader(shader);
}
/**
这个方法由外部父控件调用,这里把drawable对象设置给谁,谁就是其父控件
这里是由外部来定义Drawable的最终大小,这是可以理解的,因为Drawable作为View的附属,
虽然可以通过getIntrinsicWidth和getIntrinsicHeight来作为View的宽高为wrap_content
时的参考,但并不具有决定作用
大多数情况下,Drawable大小是由其所属View决定
所以这里设置的四个值,必须得到你足够的重视,在draw时,要根据这四个值来
你可以认为这里的值是控件被测量和layout之后的结果
*/
@Override
public void setBounds(int left, int top, int right, int bottom) {
super.setBounds(left, top, right, bottom);
JLog.i("RoundImageDrawable", "setBounds--" + left + ", " + top + ", " + right + ", " + bottom);
rectF = new RectF(left, top, right, bottom);
}
@Override
public void draw(Canvas canvas)
{
canvas.drawRoundRect(rectF, 30, 30, mPaint);
}
//getIntrinsicWidth、getIntrinsicHeight主要是为了在View使用wrap_content的时候,提供一下尺寸,默认为-1可不是我们希望的。
@Override
public int getIntrinsicWidth()
{
JLog.i("RoundImageDrawable", "getIntrinsicWidth--bitmap宽-" + mBitmap.getWidth());
return mBitmap.getWidth();
}
@Override
public int getIntrinsicHeight()
{
JLog.i("RoundImageDrawable", "getIntrinsicHeight--bitmap高-" + mBitmap.getHeight());
return mBitmap.getHeight();
}
@Override
public void setAlpha(int alpha)
{
mPaint.setAlpha(alpha);
}
/**
* Specify a color and Porter-Duff mode to be the color filter for this
* drawable.
*/
@Override
public void setColorFilter(ColorFilter cf)
{
mPaint.setColorFilter(cf);
}
@Override
public int getOpacity()
{
return PixelFormat.TRANSLUCENT;
}
}