用户界面事件(一)

用户界面包括两方面内容:屏幕布局和事件处理。
事件处理主要包括两个方式来进行,一个是事件处理器,一个是事件监听器。对于事件处理器,一般是事件触发,调用相应的回调函数来进行事件的处理,这些都是系统自发完成的。而事件监听器,则是你需要注册相应的事件,并定义相应 的事件处理函数。
先看事件处理器,一般系统的key事件主要有:

  1. KEYCODE_POWER
  2. KEYCODE_BACK
  3. KEYCODE_MENU
  4. KEYCODE_HOME
  5. KEYCODE_SERACH
  6. KEYCODE_CAMERA
  7. KEYCODE_VOLUME_UP
  8. KEYCODE_VOLUME_DOWN
    …….
    系统会将KeyEvent事件发送给获得焦点的Activity的回调函数。相应的回调函数为
  9. onKeyUp()
  10. onKeyDown()
  11. onKeyLongPress()
  12. onTrackballEvent()
  13. onTouchEvent()
  14. onFocusChanged()
    此处还有一些由于设备版本不同,一些处理需要注意的地方,相关知识可以参考《Android开发揭秘》。

现在考虑这样一个问题:
我在照相机里选择一张图片,然后进行显示。并完成以下功能:

  1. 放大
  2. 缩小
  3. 双击恢复原始 大小

    先把部分代码贴出来(还没实现第三个功能):

public class Photo extends AppCompatActivity implements View.OnTouchListener{

    private static final String TAG = "AppCompatActivity";

    Matrix mMatrix = new Matrix();
    Matrix rawMatrix  = new Matrix();
    ImageView photo;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_photo);
        Intent i  = getIntent();
        String tmp = i.getExtras().getString("photo");
        Bitmap bitmap = BitmapFactory.decodeFile(tmp);
        Bitmap bitmap1 = Bitmap.createScaledBitmap(bitmap, 300, 400, false);
        photo = (ImageView)findViewById(R.id.photo);
        photo.setImageBitmap(bitmap1);
        photo.setOnTouchListener(this);
        rawMatrix.set(photo.getImageMatrix());
    }

    private static final float DOUBLE_CLICKED_DIS = 10;

    private static final int NONE_MODE = 0;
    private static final int DRAG_MODE = 1;
    private static final int ZOOM_MODE = 2;
    private static int eventMode  = NONE_MODE;

    float two_dis = 0;

    private float beginX = 0;
    private float beginY = 0;

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                Log.d(TAG,"ACTION_DOWN Pressed...");
                beginX = event.getX();
                beginY = event.getY();
                Log.d(TAG,"beginX: "+beginX);
                Log.d(TAG, "beginY: " + beginY);
                eventMode = DRAG_MODE;
                Log.d(TAG, rawMatrix.toString());
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                Log.d(TAG,"ACTION_POINTER_DOWN pressed...");
                two_dis = (float)calDis(event);
                eventMode = ZOOM_MODE;
                break;
            case MotionEvent.ACTION_MOVE:

                if(eventMode==DRAG_MODE) {
                    float dx  = event.getX()-beginX;
                    float dy = event.getY()-beginY;
                    float len = (float)Math.sqrt(dx*dx+dy*dy);

                    if(len<20)
                        break;

                    Log.d(TAG,"ACTION_MOVE Pressed...");
                    mMatrix.set(rawMatrix);
                    mMatrix.postTranslate(dx, dy);

                    rawMatrix.set(mMatrix);

                    beginX = event.getX();
                    beginY = event.getY();
                }else if(eventMode==ZOOM_MODE) {
                    mMatrix.set(rawMatrix);
                    float dis = (float)calDis(event);
                    float scale = dis / two_dis;
                    float[] values = new  float[9];
                    mMatrix.getValues(values);

                    if(scale*values[Matrix.MSCALE_X]>6)
                        scale = scale/values[Matrix.MSCALE_X];

                    two_dis = dis;
                    mMatrix.postScale(scale,scale,v.getWidth()/2,v.getHeight()/2);
                    rawMatrix.set(mMatrix);
                }
                photo.setImageMatrix(mMatrix);
                break;
            case MotionEvent.ACTION_POINTER_UP:
                Log.d(TAG,"ACTION_POINTER_UP...");
                eventMode = NONE_MODE;
                break;
            case MotionEvent.ACTION_UP:
                Log.d(TAG,"ACTION_IP...");
                eventMode = NONE_MODE;
                break;
            default:
                break;
        }
        return true;
    }

    double calDis(MotionEvent event) {
        if(event.getPointerCount()<2)
            return 0;
        double xDis = event.getX(1) - event.getX(0);
        double yDis = event.getY(1) - event.getY(0);
        return Math.sqrt(xDis*xDis+yDis*yDis);
    }

函数calDis(MotionEvent event)是用来计算两个接触点之间的距离,此时必须保证具有两个接触点。
值得注意的是:第一,在XML布局文件中要设置 android:scaleType=”matrix”(或者在onCreate方法中设置),这样你的图才可以进行按照Matrix方式放大或者缩小 。
第二,要明白几个Matrix方法的区别,开始我就将public boolean postTranslate(float dx, float dy)用成了setTranslate(float dx, float dy)方法,结果得到的图像老是从左上角重置。
第三,要明白整个案件触发流程,可以把真个lifecycle看做是一个状态机。
首先,一个手指接触屏幕,会触发MotionEvent.ACTION_DOWN事件,两个手指会触发MotionEvent.ACTION_POINTER_DOWN事件 。一般MotionEvent.ACTION_POINTER_DOWN事件之前一定会触发MotionEvent.ACTION_DOWN事件的。当以上两个事件有一个触发时,接着就进入了MotionEvent.ACTION_MOVE事件。然后依次执行MotionEvent.ACTION_POINTER_UP,MotionEvent.ACTION_UP事件。
当没有MotionEvent.ACTION_POINTER_DOWN事件触发时,是不会触发MotionEvent.ACTION_POINTER_UP事件的。
举个列子,在触发MotionEvent.ACTION_DOWN后,并没有按下 第二个手指,此时会直接进入MotionEvent.ACTION_MOVE事件,然后一直重复触发此事件,直到你手指离开,因此你可以将此过程以状态机的形式进行编程。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值