第一类 通过R 生成 id的 文件
第二类 assert 原文件
Android 应用资源目录:
/res/animator/ 存放属性动画xml
/res/anim/ 存放补间动画
/res/color
/res/drawable
/res/menu :存放 各种菜单 资源
/res/raw : 存放原生 文件,会被R引用
/res/xml : 存储xml原生文件
LoadImageView
// 1. 基本资源
Resources res= getResources();
res.getXXX() // 根据资源清单ID 来获取资源 getString() 、getDrawable
getAssets() // 获取assert 下 AssertManager 对象
//2. 数组资源
代码实现:
package mk.denganzhi.com.shapemodel;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.graphics.drawable.shapes.RectShape;
import android.graphics.drawable.shapes.RoundRectShape;
import android.graphics.drawable.shapes.Shape;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by denganzhi on 2020/3/2.
*/
public class MyView extends View {
public MyView(Context context) {
super(context);
}
ShapeDrawable shapeDrawable=null;
Paint paint=null;
public MyView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
/**
* ArcShape: 圆弧
* OvalShape: 椭圆形 默认
* RectShape 矩形
* RoundRectShape 圆角矩形
*/
// 绘制一个矩形
shapeDrawable=new ShapeDrawable(new OvalShape());
// 指定背景颜色
shapeDrawable.getPaint().setColor(Color.RED);
// 指定路径在View中的
// int left, int top, int right, int bottom
// right,bottom是右下角相对于左边,上边距离
shapeDrawable.setBounds(10,10,100,100);
//设置画笔
paint=new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(20);
paint.setTypeface(Typeface.DEFAULT_BOLD); // 设置粗体
paint.setAntiAlias(true); // 消除锯齿
}
public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// canvas 画板,背景色
canvas.drawColor(Color.GREEN);
// 这个坐标点的镇正确理解:
// 文字"hello.viwe"的 左小角 相对于 canvas 右上角的的距离
canvas.drawText("hello.view",10,120,paint);
// 可以自己把自己画到画布上去
shapeDrawable.draw(canvas);
}
}
使用:
效果图:
绘图api归纳:
// 重写onDraw 方法api // 1. canvas 用于绘制图片 、 图片到 View 上 2. canvas 变换api // Paint 画笔,设置 绘图样式 // path 绘图路径
2.1 绘制 直线
2.2. 文本api 绘制测量, 每一个文本都有一个文本矩形区域
2.3. 基线问题:
https://blog.csdn.net/dreams_deng/article/details/104858115
DrawText基线问题;
代码:
Java代码实现:
package com.denganzhi.cusomerwidget.View;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Administrator on 2018/10/23.
*/
public class PaintView extends View {
Paint paint;
private String str = "牛叔fbcdef";
// 在代码中使用空间的时候New
public PaintView(Context context) {
super(context);
}
// 在布局文件中配置的时候New
public PaintView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
// -----------------1.画笔API--------------------
paint =new Paint();
// 重置
paint.reset();
paint.setTextSize(40);
paint.setColor(Color.RED);
//其中,参数x为透明度,取值范围为0~255,数值越小越透明。直接setAlpha是改变整个view的透明度
paint.setAlpha(255);
// 1. 设置画笔样式
// paint.setStyle(Paint.Style.FILL); //填充
// 填充和描边,填充是填充圆内部区域
// 描边是边 圆的半径= 填充/2+描边/2
// paint.setStyle(Paint.Style.FILL_AND_STROKE);
paint.setStyle(Paint.Style.STROKE); //描边
// paint.setStrokeWidth(10);
// 2. 线帽,比如进度条
// paint.setStrokeCap(Paint.Cap.BUTT);//没有
paint.setStrokeCap(Paint.Cap.ROUND);//圆形
// paint.setStrokeCap(Paint.Cap.SQUARE);//方形
// 3. 两个线条交接地方
// paint.setStrokeJoin(Paint.Join.MITER);//锐角
// paint.setStrokeJoin(Paint.Join.ROUND);//圆弧
paint.setStrokeJoin(Paint.Join.BEVEL);//直线
//4. 防锯齿,会损失一定的性能
paint.setAntiAlias(true);
// //设置是否使用图像抖动处理。会使绘制的图片等颜色更加的清晰以及饱满。(也是损失性能)
// paint.setDither(true);
}
public PaintView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// -----------------2.绘制 直线--------------------
// 1.画圆
// canvas.drawCircle(100,100,100,paint);
// 2.画线 实心 -| 效果
// canvas.drawLine(100,100,400,100,paint);
// canvas.drawLine(400,100,400,400,paint);
//3. 使用path绘制 绘制大于符号
// 使用paint绘制矩形,要绘制4次
Path path1 = new Path();
path1.moveTo(100, 100); // 坐标(100,100)
path1.lineTo(300, 100); // 坐标(300,100) 直线
path1.lineTo(100, 300); // 坐标(100,300)
paint.setStrokeJoin(Paint.Join.ROUND);
canvas.drawPath(path1, paint);
// 使用path绘制圆角矩形,一个角的圆角大一点
// RectF r = new RectF(100, 100, 400, 500);
// Path path = new Path();
// float radii[] = {10,10,10,10,10,10,50,60}; // 这里要绘制圆角矩形,四个角,每个角一个椭圆(x,y)指定长轴和短轴
// path.addRoundRect(r, radii, Direction.CCW);
// path.addArc(oval, startAngle, sweepAngle)
// canvas.drawPath(path, paint);
// -----------------3.文本api 绘制测量, 每一个文本都有一个文本矩形区域--------------------
//获得字符行间距
paint.getFontSpacing();
//获得字符之间的间距
// paint.getLetterSpacing();
// paint.setLetterSpacing(letterSpacing)//设置
//设置文本删除线
paint.setStrikeThruText(true);
//是否设置下划线
paint.setUnderlineText(true);
//设置文本大小
paint.setTextSize(80);
// paint.getTextSize();
paint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));//设置字体类型,加粗
// Typeface.ITALIC
// Typeface.create(familyName, style)//加载自定义字体
//文字倾斜 默认0,官方推荐的-0.25f是斜体
paint.setTextSkewX(-0.25f);
//文本对齐方式
paint.setTextAlign(Paint.Align.LEFT);
// paint.setTextAlign(Paint.Align.CENTER);
// paint.setTextAlign(Align.RIGHT);
paint.setColor(Color.RED);
// 这个坐标点的镇正确理解:
// 文字"hello.viwe"的 左小角 相对于 canvas 右上角的的距离
canvas.drawText(str,200,200,paint);
// 获取文字的宽、高
float[] measuredWidth = new float[1];
// 参数: 字符串、是否从头开始测量、最大值测量的(超过不测量)、测量结果
int breakText = paint.breakText(str, true, Integer.MAX_VALUE, measuredWidth);
Log.e("denganzhi1", "字符个数="+breakText+", 字符串长度="+str.length()+", measredWidth:"+measuredWidth[0]);
//获取文本的宽度,和上面类似,但是是一个比较粗略的结果
float measureText = paint.measureText(str);
Log.e("denganzhi1", "measureText="+measureText);
// //measuredWidth得到每一个字符的宽度;textWidths字符数
float[] measuredWidth2 = new float[10];
int textWidths = paint.getTextWidths(str, measuredWidth2);
mPaint.getTextWidths(text, start, end, widths)
Log.e("denganzhi1", "字符个数:"+textWidths+" measuredWidth2:"+measuredWidth2[0]);
// Rect bounds获取文本的矩形区域(宽高),获取指定区域文字的宽、高 index:文字开始 count:文字后面数量
// mPaint.getTextBounds(text, index, count, bounds)
// mPaint.getTextBounds(text, start, end, bounds)
}
}
效果:
1. 画线
2. 画点
3. 画矩形
4. 画圆弧
5. 矩形运算、合并
6. canvas图层变换:
xml布局:
Java代码归纳:
package com.denganzhi.cusomerwidget.canvas;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.graphics.RegionIterator;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
/**
* Created by Administrator on 2020/3/15.
*/
public class CanvasView extends View {
public CanvasView(Context context) {
super(context);
}
Paint paint=null;
public CanvasView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
paint=new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setAntiAlias(true);
paint.setStrokeWidth(5);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// -------------------- Canvas 绘制基础图形使用 --------------------
// 1.画线
//canvas.drawLine(0,0,100,100,paint);
float []pts = {0,0,100,100,200,200,300,300};
// canvas.drawLines(pts, paint); //绘制线,线条之间有间隔
// canvas.drawLines(pts, 20, 2, paint);//通过offset设置线的间隔距离,可以实现虚线效果 ??无法使用
// path 画线条
Path pathLien=new Path();
pathLien.moveTo(100, 100);//画笔落笔的位置
pathLien.lineTo(200, 100);
pathLien.lineTo(200, 200); // 通过path绘制横竖 -|
// canvas.drawPath(pathLien, paint);
// 2.画点
canvas.drawPoint(500,500,paint);
//画多个点
// canvas.drawPoints(pts,paint);
//3. 画矩形
//Rect 和 RectF 一个参数为Int 一个参数为float
RectF rect=new RectF(10,10,200,200);
// canvas.drawRect(rect,paint);
// 圆角矩形 , 四个圆角 半径30,30
// canvas.drawRoundRect(rect,30,30,paint);
// 通过path制定 圆角矩形各个 叫的弧度 , 四个角x,y路径
float radii[] = {10,10,10,10,10,10,50,60};
Path path = new Path(); // 使用path绘制矩形
path.addRoundRect(rect, radii, Path.Direction.CCW);
// canvas.drawPath(path, paint);
// 4. 画圆弧 true 是否闭合
// canvas.drawArc(rect,0,30,true,paint);
// 画圆
// canvas.drawOval(rect,paint);
// 5、 矩形合并
Rect rectF1=new Rect(100,100,300,300);
Region region=new Region(200,300,400,400);
region.union(rectF1);
// region.op(rectF1, Path.Op.DIFFERENCE) 集合运行,合并、交集、减去
RegionIterator regionIterator=new RegionIterator(region);
Rect r2=new Rect();
while(regionIterator.next(r2)){
// canvas.drawRect(r2,paint);
}
// -------------------- Canvas 变化 --------------------
RectF canvasF1=new RectF(0,0,200,200);
// canvas.drawRect(canvasF1,paint);
// 1.画布平移, 会创建一个新的画布,进行平移绘制
// canvas.translate(50,50);
// canvas.drawRect(canvasF1,paint);
// 2. 缩放
// 下面绘制的,在画布上绘制了
// canvas.scale(2,2);
// 导致里面绘制的东西有一个缩放效果2.0倍
// canvas.drawRect(canvasF1,paint);
// 3. 旋转
// 画板选择,坐标系选择,绘制内容也变化
// 0,0 旋转坐标
// canvas.rotate(60,0,0);
// canvas.drawRect(canvasF1,paint);
// 4. 画布斜拉
//float sx, float sy 这里如何计算 tan60 = 1.73
// canvas.skew(1.73f,0);
// canvas.drawRect(canvasF1,paint);
// 5. 画布裁剪
// canvas.clipRect(new Rect(0,0,50,50));
// 画布填充背景色
// canvas.drawColor(Color.BLUE);
}
}
3.1. res/values/attrs.xml 属性设置
3.2. onDraw
初始化画笔,画圆,圆的 半径 末点指向 圆弧的一半
画文本
画圆弧
3.3. postInvalidate 属性UI
4.4. 提供回调刷新UI
3.1. res/values/attrs.xml 属性设置
3.2. onDraw [MyCircleView.java类]
3.3. postInvalidate 属性UI
package com.denganzhi.cusomerwidget.View;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.FontMetrics;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import com.denganzhi.cusomerwidget.R;
/**
* Created by Administrator on 2018/10/24.
*/
public class MyCircleView extends View {
private Paint paint;
int context_text= 0;
private int max;
private int roundColor;
private int roundProgressColor;
private int textColor;
private float textSize;
private float roundWidth;
private boolean textShow;
private int style;
private int progress;
public interface ListenerLoaingStatus{
void showLoadingStatus(float value);
};
ListenerLoaingStatus listenerLoaingStatus;
public void setListenerLoaingStatus(ListenerLoaingStatus listenerLoaingStatus) {
this.listenerLoaingStatus = listenerLoaingStatus;
}
public MyCircleView(Context context) {
super(context);
}
public MyCircleView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
paint=new Paint();
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyCircleView);
max = typedArray.getInteger(R.styleable.MyCircleView_max, 100);
roundColor = typedArray.getColor(R.styleable.MyCircleView_roundColor, Color.RED);
roundProgressColor = typedArray.getColor(R.styleable.MyCircleView_roundProgressColor, Color.BLUE);
textColor = typedArray.getColor(R.styleable.MyCircleView_textColor, Color.GREEN);
textSize = typedArray.getDimension(R.styleable.MyCircleView_textSize, 55);
roundWidth = typedArray.getDimension(R.styleable.MyCircleView_roundWidth, 50);
textShow = typedArray.getBoolean(R.styleable.MyCircleView_textShow, true);
style = typedArray.getInt(R.styleable.MyCircleView_style, 0);
typedArray.recycle();
}
public MyCircleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//圆的半径包括圆弧厚度的一半,所以rondWidth/2
// 画圆, 圆的 半径 末点指向 圆弧的一半
float radious = getWidth()/2 - roundWidth/2;
// Log.e("denganzhi1","getWidth:"+getWidth()+" radious: "+radious);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(roundWidth);
canvas.drawCircle(getWidth()/2,getHeight()/2,radious,paint);
// 绘制文本内容
// 如何水平、垂直居中:https://blog.csdn.net/dreams_deng/article/details/104858115
paint.setStrokeWidth(0);
paint.setColor(textColor);
paint.setTextSize(100);
paint.setTypeface(Typeface.DEFAULT_BOLD);
// 内容居中
FontMetrics fontMetrics = paint.getFontMetrics();
//float viewBaseLineY= getHeight()/2+ ((fontMetrics.bottom-fontMetrics.top)/2- fontMetrics.bottom);
context_text= (int)((getProgress()*1.0/max)*100);
// Log.e("denganzhi1","context_text--->:"+context_text+"%");
float baseLineX = getWidth()/2 - paint.measureText(context_text+"%")/2;
float baseLineY = getHeight()/2 + ((fontMetrics.bottom-fontMetrics.top)/2-fontMetrics.bottom);
canvas.drawText(context_text+"%",baseLineX,baseLineY,paint);
// 画圆弧 RectF的理解,RectF必须相交圆圆弧的roundWidth/2处
// 不是 内切矩形、也是圆的外切矩形
paint.setStrokeWidth(roundWidth);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
RectF oval = new RectF(roundWidth/2,roundWidth/2, getWidth()-roundWidth/2, getHeight()-roundWidth/2);
// canvas.drawRect(oval,paint);
float progressValue= getProgress()*3.6f;
canvas.drawArc(oval , 0, progressValue, false, paint);
listenerLoaingStatus.showLoadingStatus(progressValue);
}
public synchronized int getProgress() {
return progress;
}
public synchronized void setProgress(int progress) {
if(progress>max){
progress=100;
}
this.progress = progress;
// 这里会不断的调用onDraw方法绘制UI
postInvalidate();
}
}
RectF的理解:
3.4. 提供回调刷新UI
package com.denganzhi.cusomerwidget;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import com.denganzhi.cusomerwidget.View.MyCircleView;
import com.denganzhi.cusomerwidget.View.MyView1;
public class NormalApiActivity extends AppCompatActivity {
MyCircleView myarc;
int progress = 0;
MyView1 mynew2;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_normal_api);
myarc = (MyCircleView)findViewById(R.id.myarc);
// 不断调用 postValidate ,不断onDraw方法 绘制UI
myarc.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
new Thread(new Runnable() {
@Override
public void run() {
while (progress <= 100) {
progress += 2;
myarc.setProgress(progress);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
});
// 回调 监听内部传递出来的值
myarc.setListenerLoaingStatus(new MyCircleView.ListenerLoaingStatus() {
@Override
public void showLoadingStatus(float value) {
Log.e("denganzhi1","value:"+value);
};
});
}
}
UI 效果图: