绘制简单图形
下面是Canvas类常用的方法:
drawRect(RectF rect, Paint paint) //绘制区域,参数一为RectF一个区域
drawPath(Path path, Paint paint) //绘制一个路径,参数一为Path路径对象
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint) //贴图,参数一就是我们常规的Bitmap对象,参数二是源区域(这里是bitmap),参数三是目标区域(应该在canvas的位置和大小),参数四是Paint画刷对象,因为用到了缩放和拉伸的可能,当原始Rect不等于目标Rect时性能将会有大幅损失。
drawLine(float startX, float startY, float stopX, float stopY, Paintpaint) //画线,参数一起始点的x轴位置,参数二起始点的y轴位置,参数三终点的x轴水平位置,参数四y轴垂直位置,最后一个参数为Paint 画刷对象。
drawPoint(float x, float y, Paint paint) //画点,参数一水平x轴,参数二垂直y轴,第三个参数为Paint对象。
drawText(String text, float x, floaty, Paint paint) //渲染文本,Canvas类除了上面的还可以描绘文字,参数一是String类型的文本,参数二x轴,参数三y轴,参数四是Paint对象。
drawOval(RectF oval, Paint paint)//画椭圆,参数一是扫描区域,参数二为paint对象;
drawCircle(float cx, float cy, float radius,Paint paint)// 绘制圆,参数一是中心点的x轴,参数二是中心点的y轴,参数三是半径,参数四是paint对象;
drawArc(RectF oval, float startAngle, float sweepAngle, boolean useCenter, Paint paint)//画弧,
参数一是RectF对象,一个矩形区域椭圆形的界限用于定义在形状、大小、电弧,参数二是起始角(度)在电弧的开始,
参数三扫描角(度)开始顺时针测量的,参数四是如果这是真的话,包括椭圆中心的电弧,并关闭它,如果它是假这将是一个弧线,参数五是Paint对象;
还要理解一个paint类:
Paint 代表了Canvas上的画笔、画刷、颜料等等;
Paint类常用方法:
setARGB(int a, int r, int g, int b) // 设置 Paint对象颜色,参数一为alpha透明值
setAlpha(int a) // 设置alpha不透明度,范围为0~255
setAntiAlias(boolean aa) // 是否抗锯齿
setColor(int color) // 设置颜色,这里Android内部定义的有Color类包含了一些常见颜色定义
setTextScaleX(float scaleX) // 设置文本缩放倍数,1.0f为原始
setTextSize(float textSize) // 设置字体大小
setUnderlineText(booleanunderlineText) // 设置下划线
MyPath.java
public class MyPath extends View{
private int width;
private int height;
private Paint mPaint;
private Paint mPaintText;
private Path mPath;
private Path mPathCircle;
private Path mPathLine;
private Paint mPaintLine;
private Path mPathWave;
private Paint mPaintWave;
private static final int WAVE_LINE=0x23;
private int count=0;
private Bitmap mBitmap;
private Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch(msg.what){
case WAVE_LINE:
count+=10;
if (count>160) {
count = 0;
}
invalidate();// 刷新
handler.sendEmptyMessageDelayed(WAVE_LINE,100);
break;
}
}
};
public MyPath(Context context) {
super(context);
}
public MyPath(Context context, AttributeSet attrs) {
super(context, attrs);
//设置绘制文字的画笔
mPaintText=new Paint();
mPaintText.setColor(Color.BLUE);
mPaintText.setTextSize(50);//设置画笔大小
mPaintText.setStyle(Paint.Style.STROKE);//消除锯齿
//设置绘制画笔的属性
mPaint=new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(10);//设置画笔宽度
mPaint.setStyle(Paint.Style.STROKE);
//设置绘画线段的画笔
mPaintLine=new Paint();
mPaintLine.setColor(Color.RED);
mPaintLine.setStyle(Paint.Style.STROKE);
mPaintLine.setStrokeWidth(10);
//设置绘画波浪线的画笔属性
mPaintWave=new Paint();
mPaintWave.setColor(Color.YELLOW);
mPaintWave.setStrokeWidth(10);
mPaintWave.setStyle(Paint.Style.STROKE);
//设置路径
mPathWave=new Path();//设置波浪线的路径
mPath=new Path();//设置路径
mPathCircle=new Path();//设置圆形的路径
mPathLine=new Path();//设置线段的路径
handler.sendEmptyMessageDelayed(WAVE_LINE, 100);
//设置初始化位图Bitmap,
mBitmap= BitmapFactory.decodeResource(getResources(), R.mipmap.zun);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height=getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width,height);//设置画布的大小,长和宽
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPath.moveTo(100, 100);//设置路径的第一个点坐标
mPath.lineTo(150,150);//设置下一个点的坐标
mPath.lineTo(100,150);//设置下一个点的坐标
mPath.close();//封闭路径
canvas.drawBitmap(mBitmap,width/2,height/2,mPaint);
//设置圆形路径,Path.Direction设置转动方向,CW是顺时针,CCW是逆时针
mPathCircle.addCircle(width/2,height/2,width/4,Path.Direction.CW);
// canvas.drawPath绘制特定的路径,第一个参数传具体的路径Path实例对象,第二参数传画笔
canvas.drawPath(mPath,mPaint);//设置路径
canvas.drawPath(mPathCircle,mPaint);
//canvas.drawTextOnPath设置文字沿路径排列,第一个参数是文字内容,第二个参数是沿的路径Path实例对象
//第三个参数和第四个参数是横纵偏移量,最后一个是画笔
canvas.drawTextOnPath("我是沿着路径走的一行字",mPathCircle,10,50,mPaintText);
//Path.quadTo用来绘制贝赛尔曲线,前两个参数是控制点的横纵坐标,后两个参数是后一个点的横纵坐标
mPathLine.moveTo(width/8*3,height/8*3);
mPathLine.quadTo(width/2,height/2+width/4,width/8*5,height/8*3);
canvas.drawPath(mPathLine,mPaintLine);
mPathWave.reset();
mPathWave.moveTo(count,height/2+width/16);
//Path.rQuadTo()方法绘制曲线时,会把上一点的坐标当做是原点坐标,依次往后
for (int i=0;i<10;i++){
mPathWave.rQuadTo(40,30,80,0);
mPathWave.rQuadTo(40,-30,80,0);
}
canvas.drawPath(mPathWave,mPaintWave);
}
}
activity_path.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/imagebac">
<com.example.administrator.canvas.widget.MyPath
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MyPathActivity.java
public class MyPathActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_path);
}
}
Bitmap、Matrix
位于android.graphics.Matrix包下的Matrix是拥有3 x3的坐标变换矩阵的矩阵类。用于对位图进行一些变化
1、Translate—平移变换
matrix.postTranslate(0,mBitmapHeigtht*2);//沿y轴向下平移Bitmap高的2倍
2、Scale—缩放变换
matrix.postScale(2,2);//放大2倍
3、Rotate—旋转变换
matrix.postRotate(180);//旋转180度
4、Skew—错切变换
matrix.postSkew(1,0);//x轴上的值不变,拉伸y轴上的值
5、Values—-对称
float matrix_values[]={1f,0f,0f,0f,-1f,0f,0f,0f,1f};//关于x轴对称,倒影效果
matrix.setValues(matrix_values);
float matrix_values2[]={-1f,0f,0f,0f,1f,0f,0f,0f,1f};//关于y轴对称,镜面效果
matrix.setValues(matrix_values2);
Bitmap实现在android.graphics包中。Bitmap类的构造函数是私有的,外面并不能实例化.BitmapFactory类提供了创建Bitmap的接口,而JNI接口来实例化Bitmap的.如下:
mBitmap= BitmapFactory.decodeResource(getResources(), R.mipmap.betterfly);//decodeResource能够从给定的资源中解析出新的位图,第一个参数是包含图像数据的资源对象,第二个参数是图像数据的资源标识
得到位图Bitmap的宽和高
mBitmapWidth=mBitmap.getWidth();//得到位图的宽
mBitmapHeigtht =mBitmap.getHeight();//得到位图的高
将位图绘制到画布上,canvas.drawBitmap()方法,第一个参数是位图实例对象Bitmap,第二个和第三个参数是位图得左上角位于画布中的位置,最后一个是画笔
canvas.drawBitmap(mBitmap,0,0,mPaint);
MyBitmap.java
public class MyBitmap extends View {
private int width;
private int height;
private Paint mPaint;
private Bitmap mBitmap;
private Matrix matrix;
private int mBitmapWidth;
private int mBitmapHeigtht;
public MyBitmap(Context context) {
super(context);
}
public MyBitmap(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint=new Paint();
mPaint.setColor(Color.GREEN);
mPaint.setStrokeWidth(10);
mPaint.setStyle(Paint.Style.STROKE);
mBitmap= BitmapFactory.decodeResource(getResources(), R.mipmap.betterfly);
matrix=new Matrix();
mBitmapWidth=mBitmap.getWidth();
mBitmapHeigtht =mBitmap.getHeight();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height=getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width,height);//设置画布的大小,长和宽
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mBitmap,0,0,mPaint);
matrix.reset();
matrix.postScale(2,2);//放大2倍
canvas.drawBitmap(mBitmap,matrix,mPaint);
matrix.reset();;
canvas.drawBitmap(mBitmap,matrix,mPaint);
matrix.postTranslate(0,mBitmapHeigtht*2);//平移
canvas.drawBitmap(mBitmap,matrix,mPaint);
matrix.reset();
matrix.postRotate(180);//旋转
matrix.postTranslate(mBitmapWidth*2,mBitmapHeigtht*3);
canvas.drawBitmap(mBitmap,matrix,mPaint);
matrix.reset();
float matrix_values[]={1f,0f,0f,0f,-1f,0f,0f,0f,1f};//关于x轴对称,倒影效果
matrix.setValues(matrix_values);
matrix.postTranslate(0,mBitmapHeigtht*2);
canvas.drawBitmap(mBitmap,matrix,mPaint);
matrix.reset();;
float matrix_values2[]={-1f,0f,0f,0f,1f,0f,0f,0f,1f};//关于y轴对称,镜面效果
matrix.setValues(matrix_values2);
matrix.postTranslate(mBitmapWidth*2,0);
canvas.drawBitmap(mBitmap,matrix,mPaint);
matrix.reset();
matrix.postSkew(1,0);//拉伸
matrix.postTranslate(0,mBitmapHeigtht*3);
canvas.drawBitmap(mBitmap,matrix,mPaint);
}
}
activity_bitmap.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.administrator.canvas.widget.MyBitmap
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MyBitmapActivity.java
public class MyBitmapActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmap);
}
}
位图相交
MyBitmapView.java
public class MyBitmapView extends View {
private int width;
private int height;
private Paint mPaintCircle;
private Paint mPaintRect;
private Bitmap mBitmap;
private Canvas canvasBit;
public MyBitmapView(Context context) {
super(context);
}
public MyBitmapView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintCircle=new Paint();
mPaintCircle.setColor(Color.YELLOW);
mPaintRect=new Paint();
mPaintRect.setColor(Color.GREEN);
//PorterDuffXfermode(PorterDuff.Mode.XOR)创建一个xfermode使用指定的波特达夫模式。参数为运用波特达夫模式
PorterDuffXfermode modeXOR=new PorterDuffXfermode(PorterDuff.Mode.XOR);
//setXfermode()方法设置或清除xfermode对象。参数为xfermode的实例对象
mPaintRect.setXfermode(modeXOR);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height=getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width,height);//设置画布的大小,长和宽
//Bitmap.createBitmap()返回与指定的宽度和高度可变的位图。
//Bitmap.Config描述了一个位图结构如何存储像素 mBitmap=Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
//Canvas(mBitmap)方法用指定的位图构造一个画布来绘制。
canvasBit=new Canvas(mBitmap);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvasBit.drawCircle(width/4,height/4,width/4,mPaintCircle);
canvasBit.drawRect(0,0,width/4,width/4,mPaintRect);
canvas.drawBitmap(mBitmap,0,0,null);
}
}
activity_bitmapview.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<com.example.administrator.canvas.widget.MyBitmapView
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
MyBitmapView.java
public class MyBitmapViewActivity extends Activity{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmapview);
}
}
MySilder.java
public class MySilder extends View {
private int width;
private int height;
private Paint mPaint;
private Paint mPaintMove;
private String []array={"A","B","C","D","E","F","G",
"H","I","J","K","L","M","N","O","P","Q","R",
"S","T","U","V","W","X","Y","Z"};
private int count=1;
private int index;
private OnItemOnClick listener;
public void setListener(OnItemOnClick listener) {
this.listener = listener;
}
public interface OnItemOnClick{
public void onItemOnClickListener(int index,String indexString);
}
public MySilder(Context context) {
super(context);
}
public MySilder(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint=new Paint();
mPaint.setTextAlign(Paint.Align.CENTER);
mPaintMove=new Paint();
mPaintMove.setTextAlign(Paint.Align.CENTER);
mPaintMove.setColor(Color.RED);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width=getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height=getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width,height);//设置画布的大小,长和宽
//设置字体的大小
mPaint.setTextSize(height/26);
mPaintMove.setTextSize(height/26);
}
private float x,y;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()){
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_DOWN:
x=event.getX();
y=event.getY();
if (x>width-mPaint.measureText("M")*2) {
index = (int) (y / (height / 26));
invalidate();
if (listener!=null){
listener.onItemOnClickListener(index ,array[index]);
}
return true;
}
break;
case MotionEvent.ACTION_UP:
count=-1;
invalidate();
return true;
}
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i=0;i<26;i++){
canvas.drawText(array[i],width-mPaint.measureText("M"),height/26*(i+1),mPaint);
if (count==1){
canvas.drawText(array[index],width-mPaint.measureText("M"),height/26*(index+1),mPaint);
}else{
canvas.drawText(array[index],width-mPaint.measureText("M"),height/26*(index+1),mPaintMove);
}
}
}
}
MySilderActivity.java
public class MySilderActivity extends Activity {
private TextView mTextView;
private MySilder mySilder;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_silder);
mTextView= (TextView) findViewById(R.id.textview);
mySilder= (MySilder) findViewById(R.id.silder);
mySilder.setListener(new MySilder.OnItemOnClick() {
@Override
public void onItemOnClickListener(int index,String indexString) {
mTextView.setText(indexString);
}
});
}
}
activity_silder.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:textSize="100dp"
android:text="A"
android:textAlignment="center"/>
<com.example.administrator.canvas.widget.MySilder
android:id="@+id/silder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
</RelativeLayout>