从0开始在Android下开发生活方向盘应用(自绘雷达图)
2012-06-12 15:23
351 查看
在30天敏捷生活(1):意识你的生活方向盘、敏捷个人:你有自己的生活方向盘吗?中提到生活方向盘是敏捷个人的一个重要工具,之前发不过图片和Excel格式的方向盘工具。
但现在是移动时代,所以利用空闲时间也编写了一个Android应用,效果图如下。这是我在Android下开发的第一个应用,所以本篇将介绍一下如何从0开始在Android开发这个应用。
以上把开发环境都准备好了,现在开始新建一个项目,取名AgileMe。Android的基本概念和常识这里也不介绍了,大家网上可以找到很多。在开始之前,简单介绍一下方向盘应用的需求。
绘制静态的雷达格线
绘制文字:这里需要按照角度来设定文字的对齐方式,否则左边的文字可能就要压线了
绘制分值点
对分值区域进行着色绘制
为了能够响应点击操作,对每一个分值刻度周围都条件一个小矩形Region,这样可以响应onTouch事件来判断打几分
代码也不复杂,主要就是根据想绘制的点进行计算,然后再drawText、drawLine等参数中传递正确即可。数据上主要是通过设定了很多对应的数组(维度点、刻度值、区域等)。具体代码如下:
[b]推荐:你可能需要的在线电子书[/b]
[b]我的微博:http://weibo.com/openexpressapp[/b]
敏捷个人sina围裙:http://q.t.sina.com.cn/135484
欢迎转载,转载请注明:转载自敏捷个人网站
但现在是移动时代,所以利用空闲时间也编写了一个Android应用,效果图如下。这是我在Android下开发的第一个应用,所以本篇将介绍一下如何从0开始在Android开发这个应用。
下载SDK http://developer.android.com/sdk/index.html
我是在windows下开发,所以下载了installer_r18-windows.exe安装SDK
运行上一步下载的installer_r18-windows.exe,然后运行SDK Manager下载你需要版本的SDK。2.3的是常用的 ,我手机是2.2的,所以我还下载了一个2.2版本的。安装ADT Plugin for Eclipse
在https://dl-ssl.google.com/android/eclipse/下载,具体如何使用Eclipse这里就不说了
以上把开发环境都准备好了,现在开始新建一个项目,取名AgileMe。Android的基本概念和常识这里也不介绍了,大家网上可以找到很多。在开始之前,简单介绍一下方向盘应用的需求。
需求
方向盘分为8个维度,每个维度采用10分制打分,每个维度的分值区域是我们生活的饱满度。程序初始化后,我们可以通过直接在各维度点击来设定维度的分值,系统自动重绘方向盘图形。当然,支持数据保存是必要地:)思路
之前找过有没有直接的雷达图控件,发现还没有发现好用的。因为绘制这个图也简单,所以干脆自己操刀从头开始。这个图元也少,所以可以不必像工作中那样关注性能。绘制静态的雷达格线
绘制文字:这里需要按照角度来设定文字的对齐方式,否则左边的文字可能就要压线了
绘制分值点
对分值区域进行着色绘制
为了能够响应点击操作,对每一个分值刻度周围都条件一个小矩形Region,这样可以响应onTouch事件来判断打几分
代码也不复杂,主要就是根据想绘制的点进行计算,然后再drawText、drawLine等参数中传递正确即可。数据上主要是通过设定了很多对应的数组(维度点、刻度值、区域等)。具体代码如下:
public class LifeWheelRadarGraph extends View { private int count = 8; private float angle = 360/count; private int point_radius = 5; //画点的半径 private int regionwidth = 40; //选择分值小区域宽度 private int valueRulingCount = 5; //画等分值线 private int radius; private int centerX; private int centerY; private String[] titles = {"工作","财富","健康","娱乐","家庭","社交","精神","贡献"}; private Point[] pts; //维度端点 private Region[] regions; //打分点区域 private float[] regionValues; //打分点分数 private Path valuePath; private float[] values = {8,6,8,6,6,6,4,5}; //各维度分值 private int maxValue = 10; private Point[] value_pts; //维度端点 private Paint paint; private Paint valuePaint; public float[] getValues() { return values; } public void setValues(float[] values) { Assert.assertTrue("传递的values数组大小不是"+count, values.length == count); this.values = values; } public LifeWheelRadarGraph(Context context) { super(context); init(); } private void init() { paint = new Paint(); valuePaint = new Paint(); pts = new Point[count]; value_pts = new Point[count]; valuePath = new Path(); for(int i=0; i<count; i++) { pts[i] = new Point(); value_pts[i] = new Point(); } regionValues = new float[count*valueRulingCount*2]; regions = new Region[count*valueRulingCount*2]; for(int i=0; i<regions.length; i++) { regions[i] = new Region(); } } public LifeWheelRadarGraph(Context context, AttributeSet attrs) { super(context, attrs); init(); } public LifeWheelRadarGraph(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { radius = Math.min(h, w)/2 - 40; centerX = w/2; centerY = h/2; for(int i=0; i<count; i++) { pts[i].x = centerX+(int)(radius*Math.cos(Math.toRadians(angle*i))); pts[i].y = centerY-(int)(radius*Math.sin(Math.toRadians(angle*i))); for(int j=1; j<=valueRulingCount*2; j++) { int x = centerX + (pts[i].x-centerX)/(valueRulingCount*2)*j; int y = centerY + (pts[i].y-centerY)/(valueRulingCount*2)*j; regions[i*valueRulingCount*2+j-1].set(x-regionwidth/2, y-regionwidth/2, x+regionwidth/2, y+regionwidth/2); regionValues[i*valueRulingCount*2+j-1] = j; } } postInvalidate(); super.onSizeChanged(w, h, oldw, oldh); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); float x = event.getX(); float y = event.getY(); switch(event.getAction()) { case MotionEvent.ACTION_DOWN: for(int i = 0; i<regions.length; i++) { if (regions[i].contains((int)x, (int)y)) { values[(int)(i/(valueRulingCount*2))] = regionValues[i]; break; } } invalidate(); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: break; } return super.onTouchEvent(event); } @Override public boolean onKeyLongPress(int keyCode, KeyEvent event) { // TODO Auto-generated method stub return super.onKeyLongPress(keyCode, event); } @Override protected void onDraw(Canvas canvas) { /* 设置画布的颜色 */ canvas.drawColor(Color.WHITE); paint.setAntiAlias(true); //画边框线 paint.setColor(Color.GRAY); paint.setStyle(Paint.Style.FILL_AND_STROKE); for(int i=0; i<count; i++) { int end = i+1 == count? 0:i+1; for(int j=1; j<=valueRulingCount; j++) { canvas.drawLine(centerX+(pts[i].x-centerX)/5*j, centerY+(pts[i].y-centerY)/5*j, centerX+(pts[end].x-centerX)/5*j, centerY+(pts[end].y-centerY)/5*j, paint); } canvas.drawLine(centerX, centerY, pts[i].x, pts[i].y, paint); } //写文字 paint.setTextSize(20); paint.setColor(Color.BLACK); FontMetrics fontMetrics = paint.getFontMetrics(); float fontHegiht = -fontMetrics.ascent; for(int i=0; i<count; i++) { if ((angle * i == 90.0) || (angle * i == 270.0)) paint.setTextAlign(Align.CENTER); else if ((angle * i < 90) || (angle * i > 270)) paint.setTextAlign(Align.LEFT); else if ((angle * i > 90) || (angle * i < 270)) paint.setTextAlign(Align.RIGHT); if (angle * i == 270.0) canvas.drawText(titles[i], pts[i].x, pts[i].y+fontHegiht, paint); else canvas.drawText(titles[i], pts[i].x, pts[i].y, paint); } //画方向盘分值区域 for(int i=0; i<count; i++) { value_pts[i].x = (int)(centerX + (pts[i].x-centerX) * values[i]/maxValue); value_pts[i].y = (int)(centerY + (pts[i].y-centerY) * values[i]/maxValue); } valuePath.reset(); valuePaint.setAntiAlias(true); valuePaint.setColor(Color.BLUE); valuePaint.setStyle(Paint.Style.FILL_AND_STROKE); for(int i = 0; i< pts.length; i++) { //给valuePath赋值 if (i == 0) valuePath.moveTo(value_pts[i].x, value_pts[i].y); else valuePath.lineTo(value_pts[i].x, value_pts[i].y); //画取分圆圈 canvas.drawCircle(value_pts[i].x, value_pts[i].y, point_radius, paint); } valuePaint.setAlpha(150); canvas.drawPath(valuePath, valuePaint); } }
保存方向盘分值
最后我们还要保存分值,这里使用了简单的SharedPreferencespublic class AgileMeActivity extends Activity { private LifeWheelRadarGraph graph = null; private SharedPreferences settings; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); graph = (LifeWheelRadarGraph)findViewById(R.id.lifeWheelRadarGraph1); // Restore preferences settings = getSharedPreferences("LifeWheel", 0); String valueStr = settings.getString("values", "8,6,8,6,6,6,4,5"); try { String[] valuesStr = valueStr.split(","); float[] values = new float[valuesStr.length]; for(int i = 0; i <valuesStr.length; i++) values[i] = Float.parseFloat(valuesStr[i]); graph.setValues(values); } catch (Exception e) { } } protected void onStop(){ super.onStop(); SharedPreferences.Editor editor = settings.edit(); float[] values = graph.getValues(); String valueStr= ""; for(int i=0; i <values.length; i++) valueStr = valueStr + "," + values[i]; valueStr = valueStr.substring(1); editor.putString("values", valueStr); editor.commit(); } }
应用下载
#敏捷个人# 生活方向盘#工具#Android应用提供下载 通过@微盘 分享文件"AgileMe.apk" http://t.cn/zWvgPgO[b]推荐:你可能需要的在线电子书[/b]
[b]我的微博:http://weibo.com/openexpressapp[/b]
敏捷个人sina围裙:http://q.t.sina.com.cn/135484
欢迎转载,转载请注明:转载自敏捷个人网站
相关文章推荐
- 从0开始在Android下开发生活方向盘应用(自绘雷达图)
- 单片机程序员开始学android应用开发
- 从头开始构建开源的Android应用研发ALM解决方案(二)建立个人桌面开发环境
- Android应用开发之快速开始
- Android TV开发(—)开始电视应用
- Android开发自学笔记(Android Studio1.3.1)—2.开始第一个Android应用
- android应用开发(1)
- Android应用开发的插件化 模块化
- 浅谈android系统架构及其应用开发特色
- Android OpenGL ES 开发教程(7):创建实例应用OpenGLDemos程序框架
- Android应用开发中如何使用隐藏API
- Android应用开发原理之从源码分析看Linearlayout、Relativelayout,Framelayout的布局差别(Framelayout分析)
- Android应用开发之(字符串替换与文本颜色改变方案)
- Android应用开发高效工具集1---ant构建简单Android项目
- Android应用开发Scroller详解及源码浅析
- 禁止Eclipse中xml文件Run as的XSL Transformation生成out.xml以方便Android应用开发
- [High]android应用开发之intent的妙用一
- Android应用开发之(android:imeOptions)
- android应用开发:音乐播放器(2)--技术细节
- 第二篇 android应用开发模式之模板模式