xsmile
You can fly higher
xsmile's Blog
Android笔记四

交通违章查询软件写完之后,不可避免的遇到了一些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方法来捕捉和处理用户按下返回键之后的操作。

首页      技术      Android      Android笔记四

发表回复

textsms
account_circle
email

xsmile's Blog

Android笔记四
交通违章查询软件写完之后,不可避免的遇到了一些bug,而且在功能上也迫切需要改善,比如增加后台自动查询功能,有违章发出提醒;比如增加手势放大查看违章图片功能,增加保存图片功能等…
扫描二维码继续阅读
2011-09-13