博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 画图(自定义坐标轴控件的拖动实现)
阅读量:6274 次
发布时间:2019-06-22

本文共 5216 字,大约阅读时间需要 17 分钟。

  最近需要做一个坐标轴相关的程序,之前一直在查找网上的相关资料,本想找一个之后调用一下就完事的,后来发现很少有相关的程序。找到了一个开源软件Achartengine功能太多,代码看着也很多,一时间不好消化,对于我这个程序来说也有点,杀鸡用牛刀的味道。最后决定自己先琢磨写一个。

  本文通过这个简单的例子说明了(具体可以看代码中的注释):

    1. 自定义控件

    2. 画图

    3. 拖动事件

  CoordinatesView是一个自定义的坐标控件,用于显示坐标轴和要显示的图形。但光光显示坐标轴和图形还不能满足要求,还得让里面的数据适应拖动,这样再多的数据都能显示在手机这样的小屏幕内了。看不见的只要拖动一下就OK了。

下面看代码:

package com.zgx.android; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.Point; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.view.View; /**  * @ClassName : CoordinatesView  * @author : ZGX zhangguoxiao_happy@163.com  * */ public class CoordinatesView extends View {
/* * 自定义控件一般写两个构造方法 CoordinatesView(Context context)用于java硬编码创建控件 * 如果想要让自己的控件能够通过xml来产生就必须有第2个构造方法 CoordinatesView(Context context, * AttributeSet attrs) 因为框架会自动调用具有AttributeSet参数的这个构造方法来创建继承自View的控件 */ public CoordinatesView(Context context) {
super(context, null); } public CoordinatesView(Context context, AttributeSet attrs) {
super(context, attrs); } /* * 两个外部数据 */ Point pa = new Point(10, 10); Point pb = new Point(20, 40); /* * 圆心(坐标值是相对与控件的左上角的) */ Point po = new Point(); /* * 控件的中心点 */ int centerX, centerY; /* * 控件创建完成之后,在显示之前都会调用这个方法,此时可以获取控件的大小 并得到中心坐标和坐标轴圆心所在的点。 */ @Override public void onSizeChanged(int w, int h, int oldw, int oldh) {
centerX = w / 2; centerY = h / 2; po.set(centerX, centerY); super.onSizeChanged(w, h, oldw, oldh); } /* * 自定义控件一般都会重载onDraw(Canvas canvas)方法,来绘制自己想要的图形 */ @Override public void onDraw(Canvas canvas) {
super.onDraw(canvas); Paint paint = new Paint(); paint.setColor(Color.BLACK); // 画坐标轴 if (canvas != null) {
canvas.drawColor(Color.WHITE); // 画直线 canvas.drawLine(0, centerY, 2 * centerX, centerY, paint); canvas.drawLine(centerX, 0, centerX, 2 * centerY, paint); // 画X轴箭头 int x = 2 * centerX, y = centerY; drawTriangle(canvas, new Point(x, y), new Point(x - 10, y - 5), new Point(x - 10, y + 5)); canvas.drawText("X", x - 15, y + 18, paint); // 画Y轴箭头 x = centerX; y = 0; drawTriangle(canvas, new Point(x, y), new Point(x - 5, y + 10), new Point(x + 5, y + 10)); canvas.drawText("Y", x + 12, y + 15, paint); // 画中心点坐标 // 先计算出来当前中心点坐标的值 String centerString = "(" + (centerX - po.x) / 2 + "," + (po.y - centerY) / 2 + ")"; // 然后显示坐标 canvas.drawText(centerString, centerX - 25, centerY + 15, paint); } if (canvas != null) {
/* * TODO 画数据 所有外部需要在坐标轴上画的数据,都在这里进行绘制 */ canvas.drawCircle(po.x + 2 * pa.x, po.y - 2 * pa.y, 2, paint); canvas.drawCircle(po.x + 2 * pb.x, po.y - 2 * pb.y, 2, paint); canvas.drawLine(po.x + 2 * pa.x, po.y - 2 * pa.y, po.x + 2 * pb.x, po.y - 2 * pb.y, paint); // canvas.drawPoint(pa.x+po.x, po.y-pa.y, paint); } } /** * 画三角形 用于画坐标轴的箭头 */ private void drawTriangle(Canvas canvas, Point p1, Point p2, Point p3) {
Path path = new Path(); path.moveTo(p1.x, p1.y); path.lineTo(p2.x, p2.y); path.lineTo(p3.x, p3.y); path.close(); Paint paint = new Paint(); paint.setColor(Color.BLACK); paint.setStyle(Paint.Style.FILL); // 绘制这个多边形 canvas.drawPath(path, paint); } /* * 用于保存拖动时的上一个点的位置 */ int x0, y0; /* * 拖动事件监听 */ @Override public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction(); /* * (x,y)点为发生事件时的点,它的坐标值为相对于该控件左上角的距离 */ int x = (int) event.getX(); int y = (int) event.getY(); switch (action) {
case MotionEvent.ACTION_DOWN: // 按下 x0 = x; y0 = y; Log.i("down", "(" + x0 + "," + y0 + ")"); break; case MotionEvent.ACTION_MOVE: // 拖动 /* * 拖动时圆心坐标相对运动 (x0,y0)保存先前一次事件发生的坐标 * 拖动的时候只要计算两个坐标的delta值,然后加到圆心中,即移动了圆心。 * 然后调用invalidate()让系统调用onDraw()刷新以下屏幕,即实现了坐标移动。 */ po.x += x - x0; po.y += y - y0; x0 = x; y0 = y; Log.i("move", "(" + x0 + "," + y0 + ")"); invalidate(); break; case MotionEvent.ACTION_UP: // 弹起 break; } /* * 注意:这里一定要返回true * 返回false和super.onTouchEvent(event)都会本监听只能检测到按下消息 * 这是因为false和super.onTouchEvent(event)的处理都是告诉系统该控件不能处理这样的消息, * 最终系统会将这些事件交给它的父容器处理。 */ return true; } }

控件的使用

1. 在xml中定义控件

ContractedBlock.gif
ExpandedBlockStart.gif
View Code
1 
2
5
7 8

2. Activity代码很简单

ContractedBlock.gif
ExpandedBlockStart.gif
View Code
1 public class TestCoordinates extends Activity {
2 @Override 3 public void onCreate(Bundle savedInstanceState) {
4 super.onCreate(savedInstanceState); 5 setContentView(R.layout.coordinates); 6 } 7 }

3. 运行结果截图

4. 小结

  OK,本程序很简单,大家只需拷贝里面的代码到新建的工程里面就可以看一下效果了。

  本文可以作为自定义View的入门参考,也算是给想在自定义View上大干一番的抛砖引玉一下。o(∩_∩)o

转载于:https://www.cnblogs.com/zgx2012/archive/2011/10/09/2203705.html

你可能感兴趣的文章
Git使用教程
查看>>
使用shell脚本自动监控后台进程,并能自动重启
查看>>
Flex&Bison手册
查看>>
java对象--继承的好处和特点
查看>>
MySQL 5.6 for Windows 解压缩版配置安装
查看>>
solrCloud+tomcat+zookeeper集群配置
查看>>
/etc/fstab,/etc/mtab,和 /proc/mounts
查看>>
Apache kafka 简介
查看>>
socket通信Demo
查看>>
技术人员的焦虑
查看>>
js 判断整数
查看>>
建设网站应该考虑哪些因素
查看>>
mongodb $exists
查看>>
js实现页面跳转的几种方式
查看>>
sbt笔记一 hello-sbt
查看>>
常用链接
查看>>
pitfall override private method
查看>>
springMVC数据绑定
查看>>
!important 和 * ----hack
查看>>
聊天界面图文混排
查看>>