交通违章查询软件写完之后,不可避免的遇到了一些bug,而且在功能上也迫切需要改善,比如增加后台自动查询功能,有违章发出提醒;比如增加手势放大查看违章图片功能,增加保存图片功能等等。在这个过程中,发现先前写的软件要想增加这样那样的功能简直比登天还难,各种函数之间高耦合,就像一块根本咬不动的大烧饼,牵一发而动全身。所以不可避免的,我重构了这款软件,已适应功能上的变化。
现在已经全部改良完毕,在这里记录一些我在这个过程中的经历。
1、关于后台自动查询
本想做成PUSH的,这样的话就需要开发服务器端,无奈精力时间实在有限,况且牵涉到个人数据保存问题,只有放弃,改成定时PULL了。在定时启动任务方面,无可争议的采用Alarmmanager类,关于使用方法网上一大堆,但是要注意这个方法
setRepeating(AlarmManager.RTC_WAKEUP, trigger, time, pendingIntent)中的第二个参数的含义是触发时间,第三个参数的含义是重复间隔时间。即当这个函数执行之后,将在trigger时间段触发pendingIntent一次,然后在间隔time时长之后再次触发,之后再次间隔time时长之后再次触发…如此循环。所以,如果你不想立即执行一次pendingIntent的话,注意trigger的取值!
2、关于手势缩放图片
如果要很方便的设计多点操作,那么Android2.2及以上版本将是最好的选择,这里我直接拿来主义了。给出以下代码:
/** * @Title: MulitPointTouchListener.java * @Package org.example.touch * @Description: TODO * @author fengcunhan [email]fengcunhan@gmail.com[/email] * @date 2010-7-18 上午10:41:22 * @version V1.0 */ public class MulitPointTouchListener implements OnTouchListener { // These matrices will be used to move and zoom image Matrix matrix = new Matrix(); Matrix savedMatrix = new Matrix(); // We can be in one of these 3 states static final int NONE = 0; static final int DRAG = 1; static final int ZOOM = 2; int mode = NONE; // Remember some things for zooming PointF start = new PointF(); PointF mid = new PointF(); float oldDist = 1f; @Override public boolean onTouch(View v, MotionEvent event) { ImageView view = (ImageView) v; // Log.e("view_width", // view.getImageMatrix()..toString()+"*"+v.getWidth()); // Dump touch event to log dumpEvent(event); // Handle touch events here... switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: matrix.set(view.getImageMatrix()); savedMatrix.set(matrix); start.set(event.getX(), event.getY()); //Log.d(TAG, "mode=DRAG"); mode = DRAG; /* * float scaleWidth=180f/320; float scaleHeight=240f/480; * matrix.reset(); matrix.postScale(scaleWidth, scaleHeight); */ //Log.d(TAG, "mode=NONE"); break; case MotionEvent.ACTION_POINTER_DOWN: oldDist = spacing(event); //Log.d(TAG, "oldDist=" + oldDist); if (oldDist > 10f) { savedMatrix.set(matrix); midPoint(mid, event); mode = ZOOM; //Log.d(TAG, "mode=ZOOM"); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: mode = NONE; //Log.e("view.getWidth", view.getWidth() + ""); //Log.e("view.getHeight", view.getHeight() + ""); break; case MotionEvent.ACTION_MOVE: if (mode == DRAG) { // ... matrix.set(savedMatrix); matrix.postTranslate(event.getX() - start.x, event.getY() - start.y); } else if (mode == ZOOM) { float newDist = spacing(event); //Log.d(TAG, "newDist=" + newDist); if (newDist > 10f) { matrix.set(savedMatrix); float scale = newDist / oldDist; matrix.postScale(scale, scale, mid.x, mid.y); } } break; } view.setImageMatrix(matrix); return true; // indicate event was handled } private void dumpEvent(MotionEvent event) { String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" }; StringBuilder sb = new StringBuilder(); int action = event.getAction(); int actionCode = action & MotionEvent.ACTION_MASK; sb.append("event ACTION_").append(names[actionCode]); if (actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP) { sb.append("(pid ").append( action >> MotionEvent.ACTION_POINTER_ID_SHIFT); sb.append(")"); } sb.append("["); for (int i = 0; i < event.getPointerCount(); i++) { sb.append("#").append(i); sb.append("(pid ").append(event.getPointerId(i)); sb.append(")=").append((int) event.getX(i)); sb.append(",").append((int) event.getY(i)); if (i + 1 < event.getPointerCount()) sb.append(";"); } sb.append("]"); //Log.d(TAG, sb.toString()); } /** Determine the space between the first two fingers */ private float spacing(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return FloatMath.sqrt(x * x + y * y); } /** Calculate the mid point of the first two fingers */ private void midPoint(PointF point, MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); point.set(x / 2, y / 2); } }
将需要缩放的view的ScaleType设置成Matrix,然后setOnTouchListener(new MulitPointTouchListener())即可实现手势缩放。
这里我要说的是,当设置ScaleType的属性为Matrix之后,图片将自动显示在ImageView的左上角,可是我需要类似FIT_CENTER一样显示在ImageView的正中,我尝试了布局文件中的所有可能属性,都以失败告中。最后的解决方法是,人为计算新的Matrix,利用postScale方法和postTranslate方法,将图片从左上角移动到ImageView的正中央,然后计算比例放大(或者缩小),最后imageView.setImageMatrix的方法重置图片。
3、关于setResult的方法
在Activity之间传递和处理数据,不可避免的会使用到startActivityForResult和setResult这两个函数。在设计中,我想在用户按下返回键之后,调用setResult向目标activity返回相关数据,很自然的就在onDestory函数中做了处理,结果发现setResult根本没有起作用,后来知道,当用户按下返回键之后,将会触发finish()函数,继而执行onDestory函数(之前还有stop等),然而,在触发finish()函数之后,setResult将自动标志为RESULT_CANCELED,并返回给目标Activity,所以在onDestroy函数中的操作已经无效了。解决方法就是,捕捉用户按下返回键的操作,然后从中处理数据setResult。在Android2.0之后的方法中,可通过覆写onBackPressed方法来捕捉和处理用户按下返回键之后的操作。
发表回复