Path
借助path类画一些几何图形
画一个三角形、画一个圆,沿着圆写文字,画贝塞尔曲线
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
path.moveTo(300, 300);
path.lineTo(200, 400);
path.lineTo(400, 400);
path.close();
path.addCircle(width/2,height/2,300, Path.Direction.CCW);
canvas.drawPath(path, mPaint);
canvas.drawTextOnPath("文字文字文字文字文字文字文字",path,50,0,mPaint);
path.moveTo(200,200);
path.quadTo(300,300, 400, 200);
canvas.drawPath(path, mPaint);
canvas.drawPoint(200, 200, mPaintPoint);
}
贝塞尔曲线
所谓贝塞尔曲线,是连接两个点的圆滑曲线,它由三个点确定,一个起始点,一个终点,第三个是控制点。
如何画一个贝塞尔曲线:
path.moveTo(200,200);//起始点
path.quadTo(300,300, 400, 200);//控制点 结束点
canvas.drawPath(path, mPaint);
下面的程序可以达到水面波动的效果
package com.example.administrator.mywidgetdemo.MyView;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.view.View;
import java.util.Calendar;
/**
* Created by Administrator on 2015/9/17.
*/
public class MyPathView extends View {
private int width;
private int height;
private Paint mPaint;
private Paint mPaintPoint;
private Path path;
public static final int NEED_INVALIDATE = 0X23;
private int count = 0;
private Handler handler = new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
case NEED_INVALIDATE:
count+=5;
if (count>80){
count=0;
}
invalidate();//告诉UI主线程重新绘制
handler.sendEmptyMessageDelayed(NEED_INVALIDATE,100);
break;
}
}
};
public MyPathView(Context context) {
super(context);
}
public MyPathView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setTextSize(50);
mPaint.setAntiAlias(true);
mPaint.setStyle(Paint.Style.STROKE);
path = new Path();
mPaintPoint = new Paint();
mPaintPoint.setColor(Color.GREEN);
mPaintPoint.setStyle(Paint.Style.STROKE);
mPaintPoint.setStrokeWidth(3);
handler.sendEmptyMessage(NEED_INVALIDATE);
}
@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);
path.reset();
path.moveTo(count, 100);
for (int i = 0;i<10;i++){
path.rQuadTo(20,5,40,0);//rQuadTo是以moveTo到的点为原点,接着确定两个点
path.rQuadTo(20,-5,40,0);
}
canvas.drawPath(path,mPaint);
canvas.drawCircle(400,100,80,mPaintPoint);
}
}
Bitmap
Bitmap,位图
借助矩阵Matrix可以对位图进行操作:平移、旋转、缩放、倾斜、对称
package com.example.administrator.mywidgetdemo.MyView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.example.administrator.mywidgetdemo.R;
/**
* Created by Administrator on 2015/9/17.
*/
public class MyBitmapView extends View {
private int width;
private int height;
private Bitmap mBitmap;
private Paint mPaint;
private Matrix matrix;
private int mBitmapWidth;
private int mBitmapHeight;
public MyBitmapView(Context context) {
super(context);
}
public MyBitmapView(Context context, AttributeSet attrs) {
super(context, attrs);
mBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.aa);
Log.d("","图片相关信息 宽:"+mBitmap.getWidth()+"高:"+mBitmap.getHeight());
mBitmapWidth = mBitmap.getWidth();
mBitmapHeight = mBitmap.getHeight();
mPaint = new Paint();
matrix = new Matrix();
}
@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);//放大缩小
canvas.drawBitmap(mBitmap, matrix, mPaint);
matrix.reset();
canvas.drawBitmap(mBitmap, matrix, mPaint);
matrix.postTranslate(0, mBitmapHeight * 2);//平移
canvas.drawBitmap(mBitmap, matrix, mPaint);
matrix.reset();
matrix.postRotate(180);//旋转
matrix.postTranslate(mBitmapWidth * 2, mBitmapHeight * 3);
canvas.drawBitmap(mBitmap, matrix, mPaint);
matrix.reset();
matrix.postSkew(0,1);//侧切(倾斜)
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, mBitmapHeight * 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(width*2,0);
canvas.drawBitmap(mBitmap,matrix,mPaint);
}
}
Xfermode
示例图:
package com.example.administrator.mywidgetdemo.MyView;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.util.AttributeSet;
import android.view.View;
/**
* Created by Administrator on 2015/9/17.
*/
public class MyBitmapView2 extends View {
private int width;
private int height;
private Bitmap mBitmap;
private Paint mPaintCricle;
private Paint mPaintRect;
public MyBitmapView2(Context context) {
super(context);
}
public MyBitmapView2(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintCricle = new Paint();
mPaintRect = new Paint();
mPaintCricle.setColor(Color.YELLOW);
mPaintRect.setColor(Color.BLUE);
PorterDuffXfermode mode = new PorterDuffXfermode(PorterDuff.Mode.XOR);//通过改变参数可以达到不同的效果
mPaintRect.setXfermode(mode);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width, height);
mBitmap = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
canvasBit = new Canvas(mBitmap);
}
private Canvas canvasBit;
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(Color.RED);
canvasBit.drawCircle(width/2,height/2,width/2,mPaintCricle);
canvasBit.drawRect(0,height/2-width/2,width/2,height/2,mPaintRect);
canvas.drawBitmap(mBitmap,0,0,null);
}
}
onTouchEvent
示例是模拟电话薄中的联系人右侧的字母栏,可以点击,可以滑动。
package com.example.administrator.mywidgetdemo.MyView;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
/**
* Created by Administrator on 2015/9/17.
*/
public class MySlider extends View {
private int width;
private int height;
private Paint mPaintText;
private Paint mPaintClick;
private int index = -1;
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 OnItemSelect onItemSelectListener;
public void setOnItemSelectListener(OnItemSelect onItemSelectListener) {
this.onItemSelectListener = onItemSelectListener;
}
public interface OnItemSelect{
public void onItemSelect(int index,String stringIndex);
}
public MySlider(Context context) {
super(context);
}
public MySlider(Context context, AttributeSet attrs) {
super(context, attrs);
mPaintText = new Paint();
mPaintText.setTextAlign(Paint.Align.CENTER);
mPaintClick = new Paint();
mPaintClick.setTextAlign(Paint.Align.CENTER);
mPaintClick.setColor(Color.BLUE);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = getDefaultSize(getSuggestedMinimumWidth(),widthMeasureSpec);
height = getDefaultSize(getSuggestedMinimumHeight(),heightMeasureSpec);
setMeasuredDimension(width, height);
mPaintText.setTextSize(height / 26f);
mPaintClick.setTextSize(height/26f);
}
private float x;
private float 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-mPaintText.measureText("M")*2){
index = (int) (y/(height/26));
Log.d("onTouch","点击到了:"+array[index]);
onItemSelectListener.onItemSelect(index,array[index]);
invalidate();
return true;
}
break;
case MotionEvent.ACTION_UP:
index = -1;
invalidate();
break;
}
return super.onTouchEvent(event);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for (int i=0;i<array.length;i++){
if (index==i){
canvas.drawText(""+array[i],width-mPaintText.measureText("M"),height/26*(i+1),mPaintClick);
}else {
canvas.drawText(""+array[i],width-mPaintText.measureText("M"),height/26*(i+1),mPaintText);
}
}
}
}
public class MainActivity extends Activity {
private MySlider mySlider;
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmapview);
mySlider = (MySlider) findViewById(R.id.myslider);
textView = (TextView) findViewById(R.id.textview);
mySlider.setOnItemSelectListener(new MySlider.OnItemSelect(){
@Override
public void onItemSelect(int index, String stringIndex) {
textView.setText(stringIndex);
}
});
}
}
观察者设计模式
private OnItemSelect onItemSelectListener;
public void setOnItemSelectListener(OnItemSelect onItemSelectListener) {
this.onItemSelectListener = onItemSelectListener;
}
public interface OnItemSelect{
public void onItemSelect(int index,String stringIndex);
}