一个Android应用
在 30天敏捷生活(1):意识你的生活方向盘 、 敏捷个人:你有自己的生活方向盘吗? 中提到生活方向盘是 敏捷个人 的一个重要工具,之前发不过图片和Excel格式的方向盘工具。
但现在是移动时代,所以利用空闲时间也编写了一个Android应用,效果图如下。这是我在Android下开发的第一个应用,所以本篇将介绍一下如何从0开始在Android开发这个应用。
下载SDK http://developer.android测试数据/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测试数据/android/eclipse/ 下载,具体如何使用Eclipse这里就不说了
以上把开发环境都准备好了,现在开始新建一个项目,取名AgileMe。Android的基本概念和常识这里也不介绍了,大家网上可以找到很多。在开始之前,简单介绍一下方向盘应用的需求。
需求
方向盘分为8个维度,每个维度采用10分制打分,每个维度的分值区域是我们生活的饱满度。程序初始化后,我们可以通过直接在各维度点击来设定维度的分值,系统自动重绘方向盘图形。当然,支持数据保存是必要地:)
思路
之前找过有没有直接的雷达图控件,发现还没有发现好用的。因为绘制这个图也简单,所以干脆自己操刀从头开始。这个图元也少,所以可以不必像工作中那样关注性能。
绘制静态的雷达格线 绘制文字:这里需要按照角度来设定文字的对齐方式,否则左边的文字可能就要压线了 绘制分值点 对分值区域进行着色绘制 为了能够响应点击操作,对每一个分值刻度周围都条件一个小矩形Region,这样可以响应onTouch事件来判断打几分代码也不复杂,主要就是根据想绘制的点进行计算,然后再drawText、drawLine等参数中传递正确即可。数据上主要是通过设定了很多对应的数组(维度点、刻度值、区域等)。具体代码如下:
1 public class LifeWheelRadarGraph extends View {
2 private int count = 8 ;
3 private float angle = 360/ count;
4 private int point_radius = 5; // 画点的半径
5 private int regionwidth = 40; // 选择分值小区域宽度
6 private int valueRulingCount = 5; // 画等分值线
7 private int radius;
8 private int centerX;
9 private int centerY;
10 private String[] titles = {"工作","财富","健康","娱乐","家庭","社交","精神","贡献" };
11
12 private Point[] pts; // 维度端点
13 private Region[] regions; // 打分点区域
14 private float [] regionValues; // 打分点分数
15 private Path valuePath;
16 private float [] values = {8,6,8,6,6,6,4,5}; // 各维度分值
17 private int maxValue = 10 ;
18 private Point[] value_pts; // 维度端点
19 private Paint paint;
20 private Paint valuePaint;
21
22 public float [] getValues() {
23 return values;
24 }
25
26 public void setValues( float [] values) {
27 Assert.assertTrue("传递的values数组大小不是"+count, values.length == count);
28 this .values = values;
29 }
30
31 public LifeWheelRadarGraph(Context context) {
32 super (context);
33 init();
34 }
35
36 private void init() {
37 paint = new Paint();
38 valuePaint = new Paint();
39 pts = new Point[count];
40 value_pts = new Point[count];
41 valuePath = new Path();
42 for ( int i=0; i<count; i++ ) {
43 pts[i] = new Point();
44 value_pts[i] = new Point();
45 }
46
47 regionValues = new float [count*valueRulingCount*2 ];
48 regions = new Region[count*valueRulingCount*2 ];
49 for ( int i=0; i<regions.length; i++ ) {
50 regions[i] = new Region();
51 }
52
53 }
54
55 public LifeWheelRadarGraph(Context context, AttributeSet attrs) {
56 super (context, attrs);
57 init();
58 }
59
60 public LifeWheelRadarGraph(Context context, AttributeSet attrs, int defStyle) {
61 super (context, attrs, defStyle);
62 init();
63 }
64
65 @Override
66 protected void onSizeChanged( int w, int h, int oldw, int oldh) {
67 radius = Math.min(h, w)/2 - 40 ;
68 centerX = w/2 ;
69 centerY = h/2 ;
70
71 for ( int i=0; i<count; i++ )
72 {
73 pts[i].x = centerX+( int )(radius*Math.cos(Math.toRadians(angle* i)));
74 pts[i].y = centerY-( int )(radius*Math.sin(Math.toRadians(angle* i)));
75
76 for ( int j=1; j<=valueRulingCount*2; j++ )
77 {
78 int x = centerX + (pts[i].x-centerX)/(valueRulingCount*2)* j;
79 int y = centerY + (pts[i].y-centerY)/(valueRulingCount*2)* j;
80 regions[i*valueRulingCount*2+j-1].set(x-regionwidth/2, y-regionwidth/2, x+regionwidth/2, y+regionwidth/2 );
81 regionValues[i*valueRulingCount*2+j-1] = j;
82 }
83 }
84 postInvalidate();
85 super .onSizeChanged(w, h, oldw, oldh);
86 }
87
88 @Override
89 public boolean onTouchEvent(MotionEvent event) {
90 int action = event.getAction();
91 float x = event.getX();
92 float y = event.getY();
93
94 switch (event.getAction())
95 {
96 case MotionEvent.ACTION_DOWN:
97 for ( int i = 0; i<regions.length; i++ )
98 {
99 if (regions[i].contains(( int )x, ( int )y))
100 {
101 values[( int )(i/(valueRulingCount*2))] = regionValues[i];
102 break ;
103 }
104 }
105 invalidate();
106 break ;
107 case MotionEvent.ACTION_MOVE:
108
109 break ;
110 case MotionEvent.ACTION_UP:
111
112 break ;
113 }
114 return super .onTouchEvent(event);
115 }
116
117
118 @Override
119 public boolean onKeyLongPress( int keyCode, KeyEvent event) {
120 // TODO Auto-generated method stub
121 return super .onKeyLongPress(keyCode, event);
122 }
123
124 @Override
125 protected void onDraw(Canvas canvas) {
126 /* 设置画布的颜色 */
127 canvas.drawColor(Color.WHITE);
128
129 paint.setAntiAlias( true );
130 // 画边框线
131 paint.setColor(Color.GRAY);
132 paint.setStyle(Paint.Style.FILL_AND_STROKE);
133 for ( int i=0; i<count; i++ )
134 {
135 int end = i+1 == count? 0:i+1 ;
136
137 for ( int j=1; j<=valueRulingCount; j++ )
138 {
139 canvas.drawLine(centerX+(pts[i].x-centerX)/5*j, centerY+(pts[i].y-centerY)/5* j,
140 centerX+(pts[end].x-centerX)/5*j, centerY+(pts[end].y-centerY)/5* j, paint);
141 }
142
143 canvas.drawLine(centerX, centerY, pts[i].x, pts[i].y, paint);
144 }
145
146 // 写文字
147 paint.setTextSize(20 );
148 paint.setColor(Color.BLACK);
149 FontMetrics fontMetrics = paint.getFontMetrics();
150 float fontHegiht = - fontMetrics.ascent;
151 for ( int i=0; i<count; i++ )
152 {
153 if ((angle * i == 90.0) || (angle * i == 270.0 ))
154 paint.setTextAlign(Align.CENTER);
155 else if ((angle * i < 90) || (angle * i > 270 ))
156 paint.setTextAlign(Align.LEFT);
157 else if ((angle * i > 90) || (angle * i < 270 ))
158 paint.setTextAlign(Align.RIGHT);
159
160 if (angle * i == 270.0 )
161 canvas.drawText(titles[i], pts[i].x, pts[i].y+ fontHegiht, paint);
162 else
163 canvas.drawText(titles[i], pts[i].x, pts[i].y, paint);
164 }
165
166 // 画方向盘分值区域
167 for ( int i=0; i<count; i++ )
168 {
169 value_pts[i].x = ( int )(centerX + (pts[i].x-centerX) * values[i]/ maxValue);
170 value_pts[i].y = ( int )(centerY + (pts[i].y-centerY) * values[i]/ maxValue);
171 }
172
173 valuePath.reset();
174 valuePaint.setAntiAlias( true );
175 valuePaint.setColor(Color.BLUE);
176 valuePaint.setStyle(Paint.Style.FILL_AND_STROKE);
177 for ( int i = 0; i< pts.length; i++ )
178 {
179 // 给valuePath赋值
180 if (i == 0 )
181 valuePath.moveTo(value_pts[i].x, value_pts[i].y);
182 else
183 valuePath.lineTo(value_pts[i].x, value_pts[i].y);
184 // 画取分圆圈
185 canvas.drawCircle(value_pts[i].x, value_pts[i].y, point_radius, paint);
186 }
187 valuePaint.setAlpha(150 );
188 canvas.drawPath(valuePath, valuePaint);
189 }
190 }
保存方向盘分值
最后我们还要保存分值,这里使用了简单的SharedPreferences
public 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测试数据mit();
}
}
应用下载
#敏捷个人# 生活方向盘 #工具# Android应用提供下载 通过 @微盘 分享文件"AgileMe.apk" http://t.cn/zWvgPgO
推荐: 你可能需要的在线电子书
我的微博: http://weibo测试数据/openexpressapp
敏捷个人sina围裙: http://q.t.sina测试数据.cn/135484
欢迎转载,转载请注明:转载自 敏捷个人网站
作者: Leo_wl
出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息