自定义View
来源:互联网 发布:淘宝美工练手 编辑:程序博客网 时间:2024/04/30 02:45
Android自定义View实现很简单
继承View,重写构造函数、onDraw,(onMeasure)等函数。
如果自定义的View需要有自定义的属性,需要在values下建立attrs.xml。在其中定义你的属性。
在使用到自定义View的xml布局文件中需要加入xmlns:前缀=”http://schemas.android.com/apk/res/你的自定义View所在的包路径”.
1、制作简易手表
先写一个类继承View,重写onMeasure(),onDraw()
public class MyView extends View { private int width; private int height; private Paint mPaintDuan; private Paint mPaintLine; private Paint mPaintSecond; private Paint mPaintCircle; private Paint mPaintText; private Calendar mCalendar; public static final int NEED_INVALIDATE=0X23; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { switch (msg.what){ case NEED_INVALIDATE: mCalendar = Calendar.getInstance();//每次要刷新时间 invalidate();//告诉主线程重新绘制 handler.sendEmptyMessageDelayed(NEED_INVALIDATE, 1000); break; } } }; public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); mCalendar =Calendar.getInstance(); mPaintDuan = new Paint();//设置直线的参数 mPaintDuan.setColor(Color.RED); mPaintDuan.setStrokeWidth(8); mPaintLine = new Paint();//设置直线的参数 mPaintLine.setColor(Color.GREEN); mPaintLine.setStrokeWidth(10); mPaintSecond= new Paint();//设置秒针线的参数 mPaintSecond.setColor(Color.GREEN); mPaintSecond.setStrokeWidth(5); mPaintCircle = new Paint();//设置圆的参数 mPaintCircle.setColor(Color.LTGRAY); mPaintCircle.setStrokeWidth(10); mPaintCircle.setStyle(Paint.Style.STROKE); mPaintText = new Paint(); mPaintText.setColor(Color.BLACK); mPaintText.setTextSize(30); mPaintText.setTextAlign(Paint.Align.CENTER); 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); //是由UI主线程自动调用,只需要在此绘制即可 // canvas.drawLine(0,0,300,300,mPaintLine);//画直线 // canvas.drawCircle(350,350,100,mPaintCircle);//画圆 canvas.drawCircle(width / 2, height / 2, 300, mPaintCircle); canvas.drawCircle(width / 2, height / 2, 10, mPaintCircle); for (int i = 1; i <= 12; i++) {//用FOR循环画12条短线 canvas.save();//保存画布当前的状态 canvas.rotate(360 / 12 * i, width / 2, height / 2);//旋转画布,每次转30度 canvas.drawLine(width / 2, height / 2 - 300, width / 2, height / 2 - 280, mPaintDuan); canvas.drawText("" + i, width / 2, height / 2 - 250, mPaintText); canvas.restore(); } //获得分钟数,小时数 int minute = mCalendar.get(Calendar.MINUTE); int hour = mCalendar.get(Calendar.HOUR); float minuteDegree = minute / 60f * 360;//获得分针的旋转度 canvas.save(); canvas.rotate(minuteDegree, width / 2, height / 2); canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 200, mPaintLine); canvas.restore(); float hourDegree = (hour*60+minute)/12f/60*360;//计算时针所占表盘的度数 canvas.save(); canvas.rotate(hourDegree, width / 2, height / 2); canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 150, mPaintLine); canvas.restore(); int second = mCalendar.get(Calendar.SECOND); float secondDegree = second/60f*360;//计算秒针此刻的位置 canvas.save(); canvas.rotate(secondDegree, width / 2, height / 2); canvas.drawLine(width / 2, height / 2, width / 2, height / 2 - 230, mPaintSecond); canvas.restore(); }}
然后再布局文件下添加这个view
<LinearLayout 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:orientation="vertical" tools:context=".MainActivity"> <com.my.administrator.zdyview.MyView//这里的MyView要和上面写的类名一致 android:id="@+id/tiaoxingview" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
在Activity中只需要 setContentView(R.layout.activity_main);即可。
简易手表如下:
2、往容器中倒满水案例
public class TiaoxingView extends View { private int width; private int height; private Paint lineLeft; private Paint lineRight; private Paint lineButtom; private Paint lineNewRight; private Paint mPaintText; private int progress=100; private int progressCurrent; public int getProgress() { return progress; } public void setProgress(int progress) { this.progress = progress; } public int getProgressCurrent() { return progressCurrent; } public void setProgressCurrent(int progressCurrent) { this.progressCurrent = progressCurrent; invalidate();//告诉主线程重新绘制 } public TiaoxingView(Context context) { super(context); } public TiaoxingView(Context context, AttributeSet attrs) { super(context, attrs); lineLeft=new Paint(); lineLeft.setColor(Color.BLACK); lineLeft.setStrokeWidth(5); lineRight=new Paint(); lineRight.setColor(Color.BLACK); lineRight.setStrokeWidth(5); lineButtom=new Paint(); lineButtom.setColor(Color.BLACK); lineButtom.setStrokeWidth(5); lineNewRight=new Paint(); lineNewRight.setColor(Color.GREEN); lineNewRight.setStrokeWidth(300); mPaintText = new Paint(); mPaintText.setColor(Color.BLUE); mPaintText.setTextSize(60); mPaintText.setTextAlign(Paint.Align.CENTER);//设置文本在给定坐标中间 } @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.drawLine(50, 100, 50, 500, lineLeft); canvas.drawLine(50,500,350,500,lineButtom); canvas.drawLine(350,500,350,100,lineRight); canvas.drawLine(200,500,200,500-progressCurrent*400f/progress,lineNewRight);//progressCurrent*400f/progress是此时应该画的长度,progressCurrent从activity中获得 canvas.drawText(progressCurrent*100f/progress+"%",200,300,mPaintText);//给定文本坐标,写入文本 }}
布局问价:
<LinearLayout 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:orientation="vertical" tools:context=".MainActivity"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="开始" /> <com.my.administrator.zdyview.TiaoxingView android:id="@+id/tiaoxingview" android:layout_width="match_parent" android:layout_height="match_parent" /></LinearLayout>
Activity
public class MainActivity extends AppCompatActivity { private TiaoxingView view; private Button mButton; private int progress; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); switch (msg.what) { case 0x21: progress++; if (progress <= 100) { view.setProgressCurrent(progress);//设置当前的进度 handler.sendEmptyMessageDelayed(0x21, 200); } break; } } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); view = (TiaoxingView) findViewById(R.id.tiaoxingview); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { handler.sendEmptyMessage(0x21); } }); }}
运行如下:
弧形进度条案例
其他代码和上面相同,view类如下:
public class ArcView extends View { private int width; private int height; private int progress=100; private int progressCurrent; private Paint mCircle; private Paint mArc; private RectF mRectf; private Paint mText; public int getProgress() { return progress; } public void setProgress(int progress) { this.progress = progress; } public int getProgressCurrent() { return progressCurrent; } public void setProgressCurrent(int progressCurrent) { this.progressCurrent = progressCurrent; invalidate(); } public ArcView(Context context) { super(context); } public ArcView(Context context, AttributeSet attrs) { super(context, attrs); mArc = new Paint(); mArc.setColor(Color.GREEN); mArc.setStrokeWidth(50); mArc.setStyle(Paint.Style.STROKE); mCircle = new Paint(); mCircle.setColor(Color.GRAY); mCircle.setStyle(Paint.Style.STROKE); mCircle.setStrokeWidth(10); mText = new Paint(); mText.setColor(Color.BLUE); mText.setTextSize(60); mText.setTextAlign(Paint.Align.CENTER); } @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.drawCircle(width / 2, height / 2, 300, mCircle); canvas.drawCircle(width / 2, height / 2, 250, mCircle); mRectf = new RectF(width/2-275,height/2-275,width/2+275,height/2+275);//设置画弧度的矩形框 canvas.drawArc(mRectf,0,progressCurrent*360f/progress,false,mArc); canvas.drawText(progressCurrent * 100f / progress + "%", width / 2, height / 2, mText); }}
运行如下;
0 0
- 自定义view
- 自定义View
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义View
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义view
- 自定义View
- 自定义View
- Processing 主题(20)Modulo函数的改造
- iOS 窗口抖动效果代码及解释
- hdu1253胜利大逃亡bfs
- CentOS7安装JDK
- eclipse错误: 找不到或无法加载主类 main.Main
- 自定义View
- java 编程思想 阅读笔记(1)
- C++Primer第五版 10.4.1节练习
- git在实际开发中的运用-基本操作
- ios超精细论证数据库管理基础
- 安全感与真实自我的关系
- docker私有仓库连接的问题
- JavaScript:propetry 与 attribute 的区别
- 小菜鸟-我的第一篇博客