易解自定义view
来源:互联网 发布:2016十大网络用语 编辑:程序博客网 时间:2024/05/21 11:49
首先,我们来看看最简单的自定view
public class ClockView extends View { private String TGA="ClockView"; public ClockView(Context context) { super(context); Log.i(TGA, "ClockView(Context context)"); } public ClockView(Context context, AttributeSet attrs) { super(context, attrs); Log.i(TGA,"ClockView(Context context, AttributeSet attrs)"); } @Override protected void onDraw(Canvas canvas) { Log.i(TGA,"onDraw()"); Paint circle=new Paint(); circle.setColor(Color.BLACK); circle.setStyle(Paint.Style.STROKE); canvas.drawCircle(getWidth()/2, getHeight()/2, 100,circle); super.onDraw(canvas); }}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <com.example.myclockwrite.ClockView android:id="@+id/clockView1" android:layout_width="200dp" android:layout_height="200dp" /></RelativeLayout>
值得一提的是,这个自定义view有两个构造方法。
public View (Context context)是在java代码创建视图的时候被调用,如果是从xml填充的视图,就不会调用这个
public View (Context context, AttributeSet attrs)这个是在xml创建时候被调用
结果如图:
这个view只画了一个最简单的圆形。
让我们做得更好点
下一步给这个圆添加两条直线做成时钟的样式
在此之前介绍两个方法。
save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。
restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。
有save()和restore(),那么平移、缩放、旋转等操作只对save()和restore()作用域之间的代码有效。为了代码逻辑更清晰美观给ClockView添加一个surface内部类。
public class ClockView extends View { private Surface surface; private String TGA="ClockView"; public ClockView(Context context) { super(context); Log.i(TGA, "ClockView(Context context)"); } public ClockView(Context context, AttributeSet attrs) { super(context, attrs); Log.i(TGA,"ClockView(Context context, AttributeSet attrs)"); } public ClockView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); Log.i(TGA,"ClockView(Context context, AttributeSet attrs, int defStyle)"); } @Override protected void onDraw(Canvas canvas) { Log.i(TGA,"onDraw()"); surface=new Surface(); //画圆 canvas.drawCircle(getWidth()/2, getHeight()/2, 100,surface.circle); //画指针 canvas.save(); canvas.rotate(2 / 12.0f * 360.0f,getWidth()/2, getHeight()/2); canvas.drawPath(surface.hour_path, surface.hour_pointer); canvas.rotate((0/60.0f-2 / 12.0f) * 360.0f,getWidth()/2, getHeight()/2); canvas.drawPath(surface.minute_path, surface.minute_pointer); canvas.rotate((50/60.0f-0/60.0f) * 360.0f,getWidth()/2, getHeight()/2); canvas.drawPath(surface.second_path, surface.second_pointer); canvas.restore(); super.onDraw(canvas); } private class Surface{ //圆画笔 public Paint circle; //时针画笔和路径 public Paint hour_pointer; public float hour_pointer_width; public float hour_lenght=60; public Path hour_path; //分针画笔和路径 public Path minute_path; public Paint minute_pointer; public float minute_poiner_width; public float minute_lenght=80; //秒针画笔和路径 public Paint second_pointer; public float second_lenght=95; public Path second_path; public float second_poiner_width; public Surface() { Init(); } public void Init(){ circle=new Paint(); circle.setColor(Color.BLACK); circle.setStyle(Paint.Style.STROKE); circle.setAntiAlias(true); hour_pointer=new Paint(); hour_pointer.setColor(Color.BLACK); hour_pointer.setAntiAlias(true); hour_pointer_width= (float) (0.5 * 10); hour_pointer.setStyle(Paint.Style.STROKE); hour_pointer.setStrokeWidth(hour_pointer_width); hour_path=new Path(); hour_path.moveTo(getWidth()/2, getHeight()/2+5); hour_path.rLineTo(0,-hour_lenght); minute_path=new Path(); minute_path.moveTo(getWidth()/2, getHeight()/2+8); minute_path.rLineTo(0, -minute_lenght); minute_pointer=new Paint(); minute_pointer.setColor(Color.BLACK); minute_pointer.setAntiAlias(true); minute_poiner_width= (float) (0.5 * 10); minute_pointer.setStyle(Paint.Style.STROKE); minute_pointer.setStrokeWidth(minute_poiner_width); second_path=new Path(); second_path.moveTo(getWidth()/2, getHeight()/2+11); second_path.rLineTo(0, -second_lenght); second_pointer=new Paint(); second_pointer.setColor(Color.BLACK); second_pointer.setAntiAlias(true); second_poiner_width= (float) (0.5 * 10); second_pointer.setStyle(Paint.Style.STROKE); second_pointer.setStrokeWidth(second_poiner_width); } }}
这时候我们的时钟稍微有点样子了
让我们做得更好点
做钟的话肯定要要钟动起来,先去百度个倒计时方法,添加到MainActivity
public class MainActivity extends Activity { private ClockView clockView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); clockView=(ClockView) findViewById(R.id.clockView1); } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); handler.post(runnable); } @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); handler.removeCallbacks(runnable); } Handler handler=new Handler(); Runnable runnable = new Runnable() { @Override public void run() { Log.i("test", "run"); clockView.updateTime(); handler.postDelayed(this, 1000); } }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; }}
再ClockView实现updateTime()
public void updateTime(){ Date now=new Date(); curtime.setTime(now); invalidate(); }
此时这个自定义view终于有点feel了
让我们做得更好点
虽然这时候clock已经可以像真正的钟一样动了,但是感觉还是太粗糙了。现在代码逻辑基本都实现了,接下来替换些图片,让clock显得高端大气些。
去网上找了一个时钟的背景图片,画图片代码很简单
Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.clock); canvas.drawBitmap(bmp ,0 ,0,null);比较麻烦的是适配问题,自定义view要能根据布局大小自动调节图画比例。
主要思路是根据图片原始大小与布局大小的比例—》对每个部位按各种比例缩放。
package com.example.myclockwrite;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Path;import android.graphics.RectF;import android.graphics.drawable.BitmapDrawable;import android.util.AttributeSet;import android.util.Log;import android.view.View;import java.util.Calendar;import java.util.Date;public class ClockView extends View { private Surface surface; private Calendar curtime; private String TGA="ClockView"; private float hours; private float minutes; private float seconds; private Context context; public ClockView(Context context) { super(context); Log.i(TGA, "ClockView(Context context)"); curtime=Calendar.getInstance(); this.context=context; } public ClockView(Context context, AttributeSet attrs) { super(context, attrs); Log.i(TGA,"ClockView(Context context, AttributeSet attrs)"); curtime=Calendar.getInstance(); this.context=context; } public ClockView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); Log.i(TGA,"ClockView(Context context, AttributeSet attrs, int defStyle)"); curtime=Calendar.getInstance(); this.context=context; } @Override protected void onDraw(Canvas canvas) { Log.i(TGA,"onDraw()"); //画背景图片 Bitmap bmp = BitmapFactory.decodeResource(context.getResources(), R.drawable.clock); float xs=(float)getWidth()/(float)bmp.getWidth(); float ys=(float)getHeight()/(float)bmp.getHeight(); Matrix matrix=new Matrix(); matrix.postScale(xs,ys);//对图片进行缩放 Bitmap dstbmp=Bitmap.createBitmap(bmp,0,0,bmp.getWidth(),bmp.getHeight(),matrix,true); canvas.drawBitmap(dstbmp,0 ,0,null); //初始化时间 hours=curtime.get(Calendar.HOUR); minutes=curtime.get(Calendar.MINUTE); seconds=curtime.get(Calendar.SECOND); //画指针 surface=new Surface(getWidth(),getHeight(),xs,ys); canvas.save(); canvas.rotate((hours+(minutes/60.0f))/ 12.0f * 360.0f,getWidth()/2, getHeight()/2); canvas.drawPath(surface.hour_path, surface.hour_pointer); canvas.rotate((minutes/60.0f-(hours+(minutes/60.0f)) / 12.0f) * 360.0f,getWidth()/2, getHeight()/2); canvas.drawPath(surface.minute_path, surface.minute_pointer); canvas.rotate((seconds/60.0f-minutes/60.0f) * 360.0f,getWidth()/2, getHeight()/2); canvas.drawPath(surface.second_path, surface.second_pointer); canvas.restore(); super.onDraw(canvas); } private class Surface{ //圆画笔// public Paint circle; public Paint pic; //时针画笔和路径 public Paint hour_pointer; public float hour_pointer_width; public float hour_lenght; public Path hour_path; //分针画笔和路径 public Path minute_path; public Paint minute_pointer; public float minute_poiner_width; public float minute_lenght; //秒针画笔和路径 public Paint second_pointer; public float second_lenght; public Path second_path; public float second_poiner_width; public int width; public int height; public float scale; public Surface(int width,int height,float xs,float ys) { this.width=width; this.height=height; if(xs>ys){ this.scale=ys; }else{ this.scale=xs; } second_lenght=width*0.7f/2; minute_lenght=width*0.6f/2; hour_lenght=width*0.4f/2; Init(); } public void Init(){ // circle=new Paint();// circle.setColor(Color.BLACK);// circle.setStyle(Paint.Style.STROKE);// circle.setAntiAlias(true); hour_pointer=new Paint(); hour_pointer.setColor(Color.BLACK); hour_pointer.setAntiAlias(true); hour_pointer_width= (float) (scale* 6); hour_pointer.setStyle(Paint.Style.STROKE); hour_pointer.setStrokeWidth(hour_pointer_width); hour_path=new Path(); hour_path.moveTo(width/2, height/2+scale*5); hour_path.rLineTo(0,-hour_lenght); minute_path=new Path(); minute_path.moveTo(width/2, height/2+scale*8); minute_path.rLineTo(0, -minute_lenght); minute_pointer=new Paint(); minute_pointer.setColor(Color.BLACK); minute_pointer.setAntiAlias(true); minute_poiner_width= (float) (scale* 4); minute_pointer.setStyle(Paint.Style.STROKE); minute_pointer.setStrokeWidth(minute_poiner_width); second_path=new Path(); second_path.moveTo(width/2, height/2+scale*11); second_path.rLineTo(0, -second_lenght); second_pointer=new Paint(); second_pointer.setColor(Color.BLACK); second_pointer.setAntiAlias(true); second_poiner_width= (float) (scale * 2); second_pointer.setStyle(Paint.Style.STROKE); second_pointer.setStrokeWidth(second_poiner_width); Log.i(TGA, hour_lenght+" "+minute_lenght+" "+second_lenght); } } public void updateTime() { Date now=new Date(); curtime.setTime(now); invalidate(); }}
源码:http://download.csdn.net/detail/u013122203/6738791
0 0
- 易解自定义view
- android自定义View全解
- 自定义view
- 自定义View
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义View
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- CALayer3-层的属性
- 关联规则之apriori算法
- POJ 3422 Kaka's Matrix Travels 最小费用流
- jQuery 遍历
- CALayer4-自定义层
- 易解自定义view
- 用户10秒就关闭网站的25种原因
- Eclipse显示空格,Tab,回车和行号
- Linq SelectionMany用法
- 计算机科学相关刊物
- C++读写二进制文件块
- Emoji表情符号兼容方案
- Ubuntu13.10安装jdk1.7.0步骤
- Settings模块分析(一)