Android 自定义坐标轴控件

  在上一篇中,我们见到了一个很简单的坐标轴,并且可以实现拖动等效果。本文在此基础上进行进一步深入探讨。仅供初学者学习,大牛看了请别乱喷哦~~谢谢~~

  图为放大前和放大并拖动后

控件功能

1.       支持坐标轴单位长度的放大缩小

2.       放大缩小基于坐标轴中间位置缩放,即中间位置的那个点为参考点,在程序中需要记录它的物理坐标和逻辑坐标,并且逻辑坐标随着拖动和缩放而不断变化,其他所有坐标的物理逻辑坐标之间的转换都是以此作为参考点的,这样可以使得缩放的时候让人感觉在用google地图(夸张了点)。

3.       支持内容拖动

4.       支持坐标轴名称和单位设置

5.       支持标题设置

6.       支持边距和标题高度设置

7.       支持添加任意多条不同折线,且可以由用户决定用什么样的Paint

实现缩放和移动的关键为参考点的变化和坐标转换。

1.       坐标轴密度K

    /*

* 横轴纵轴密度、长度和比例。

*/

private float mXValuePerPix, mYValuePerPix;

private float mXScale, mYScale;

mXValuePerPix / mXScale 为X轴的密度

mYValuePerPix / mYScale 为Y轴的密度

2.       移动的时候参考点的变化

    /*

* 用于保存拖动时的上一个点的位置

*/

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: // 拖动

/*

* (x-x0, y-y0)为物理坐标相对运动矢量

* mXValuePerPix / mXScale 为X轴的密度

* mYValuePerPix / mYScale 为Y轴的密度

* 即每个像素长度代表的长度

*

* 向右和向上移动的时候,坐标值都是变大的,而参考点是不动的所以相对来说是变小的

* 但是物理Y轴的矢量应该先取反,因为物理坐标点的坐标轴是向下Y增大的。

*/

mPointBaseValue.x -= (x - x0) * mXValuePerPix / mXScale;

mPointBaseValue.y -= -(y - y0) * mYValuePerPix / mYScale;

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;

}

3.       坐标转换

    /**

* 逻辑坐标转化为屏幕坐标

* 将逻辑坐标logPointF点转换为物理坐标

*/

private PointF point2Physical(PointF logPointF) {

PointF physicalPointF = new PointF();

physicalPointF.set((logPointF.x - mPointBaseValue.x) * mXScale

/ mXValuePerPix + mPointBase.x,

-(logPointF.y - mPointBaseValue.y) * mYScale / mYValuePerPix

+ mPointBase.y);

return physicalPointF;

}



/**

* 物理坐标转化为逻辑坐标

* 将物理坐标phyPointF点转换为逻辑坐标

*/

private PointF point2Logical(PointF phyPointF) {

float x = (phyPointF.x - mPointBase.x) * mXValuePerPix / mXScale

+ mPointBaseValue.x;

float y = (mPointBase.y - phyPointF.y) * mYValuePerPix / mYScale

+ mPointBaseValue.y;

PointF logicalPointF = new PointF(x, y);

return logicalPointF;

}

 4.       程序中所用的成员变量一览

    /*

* 颜料

*/

private Paint mPaint;

/*

* 数据集合

*/

private List<PointF[]> mPointsList;

private List<Paint> mPaintList;

/*

* 标题

*/

private boolean mHasTitle;

private String mTitle;

private int mTitleHeight;

private PointF mTitlePoint;

/*

* 边距

*/

private int mLeftPad, mRightPad, mBottomPad, mTopPad;

/*

* 横轴纵轴密度、长度和比例。

*/

private float mXValuePerPix, mYValuePerPix;

private int mXLen, mYLen;

private float mXScale, mYScale;

/*

* 横轴纵轴标识和单位

*/

private String mXAxisPrickle, mYAxisPrickle;

private String mXAxisName = "X", mYAxisName = "Y";

/*

* 圆心(坐标值是相对与控件的左上角的)

*/

// private PointF mPointZero = new PointF();

/*

* 参考坐标

*/

private PointF mPointBase = new PointF();

private PointF mPointBaseValue = new PointF();

/*

* 交叉点坐标中心点

*/

private PointF mPointOrigin = new PointF();

源码下载:CoordinatesTest.zip


转载于:https://www.cnblogs.com/zgx2012/archive/2011/10/12/2208720.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值