使用Android事件实现连续两次按下“返回键“退出,长按图片收藏,移动帽子

1 概述

物理按键事件:按下,抬起和长按。
触摸事件:按下,抬起,滑动和双击。

1.1 基于监听的事件处理(setOnTouchListener())

做法是绑定特定的事件监听器

1.2 基于回调的事件处理(onTouchEvent())

做法是重写回调方法。View类事件处理的回调方法如下:

方法

说明

onKeyDown()

按下按键

okKeyLongPress()

长按

onKeyShortCut()

按下键盘快捷键

onKeyUp()

松开按键

onTouchEvent()

触摸

表9-1 View类事件处理的回调方法
对于某些事件,无法采用基于回调的事件处理方式处理,只能采用基于监听的事件处理方式。

2 使用物理按键事件实现连续两次按下"返回键"退出

物理按键

KeyEvent

电源键

KEYCODE_POWER

返回键

KEYCODE_BACK

菜单键

KEYCODE_MENU

Home键

KEYCODE_HOME

查找键

KEYCODE_SEARCH

音量键

KEYCODE_VOLUME_UP

KEYCODE_VOLUME_DOWN

方向键

KEYCODE_DPAD_CENTER

KEYCODE_DPAD_UP

KEYCODE_DPAD_DOWN

KEYCODE_DPAD_LEFT

KEYCODE_DPAD_RIGHT

表9-2 Android设备可用物理按键
KeyDown:
MainActivity.java

public class MainActivity extends AppCompatActivity {
    private long exitTime = 0;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            exit();
            Log.d("MainActivity","return false");
            return false;
        }
        return super.onKeyDown(keyCode, event);
    }
    public void exit() {
        // 计算按键时间差是否大于两秒
        if ((System.currentTimeMillis() - exitTime) > 2000) {
            Toast.makeText(getApplicationContext(), "再按一次退出程序", Toast.LENGTH_SHORT).show();
            exitTime = System.currentTimeMillis();
        } else {
            // 连续按键两次退出
            finish();
            System.exit(0);
        }
    }
}

https://github.com/hanyuhang-hz/android-demos

3 使用触摸屏事件实现长按图片收藏,移动帽子

触摸屏事件:
单击事件:setOnClickListener()
长按事件:setOnLongClickListener()
触摸事件:setOnTouchListener()

LongClick:
MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ImageView imageView = (ImageView) findViewById(R.id.imageView);
        imageView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                registerForContextMenu(v); // 将长按事件注册菜单中
                openContextMenu(v); // 打开菜单
                // 表示用户消耗此事件,现象为收藏菜单显示后一直存在
                return true;
                // 表示系统消耗此事件,现象为收藏菜单显示后立刻消失
                // return false;
            }
        });
    }
    // 创建菜单
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
        super.onCreateContextMenu(menu, v, menuInfo);
        menu.add("收藏");
    }
}

https://github.com/hanyuhang-hz/android-demos

MoveHat
MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);
        final HatView hat = new HatView(MainActivity.this); // 创建并实例化HatView类
        hat.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                hat.bitmapX = event.getX()-10; // 设置帽子显示位置的X坐标
                hat.bitmapY = event.getY()-50; // 设置帽子显示位置的Y坐标
                hat.invalidate(); // 重绘hat组件
                return true;
            }
        });
        relativeLayout.addView(hat);
    }
}

当触摸事件onTouch发生后,会产生一个MotionEvent事件对象,可以通过该对象获取当前的x和y坐标。
HatView.java

public class HatView extends View {
    public float bitmapX; // 帽子显示位置的X坐标
    public float bitmapY; // 帽子显示位置的Y坐标

    public HatView(Context context) {
        super(context);
        bitmapX = 30;
        bitmapY = 0;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Paint paint = new Paint();
        Bitmap bitmap = BitmapFactory.decodeResource(this.getResources(), R.drawable.hat);
        Log.d("HatView", "bitmapX: " + bitmapX + " bitmapY: " + bitmapY);
        // 绘制帽子
        canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint);
        if (bitmap.isRecycled()) {
            bitmap.recycle(); // 强制回收图片
        }
    }
}

https://github.com/hanyuhang-hz/android-demos

4 区分触摸事件和单击事件

在Android中,一次用户操作可以被不同的View按次序分别处理,我们将响应了用户的一次UI操作称之为消耗了该事件。对于一个View组件,Android如何区分触摸事件和单击事件呢?
TouchAndClick
MainActivity.java

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button button= (Button) findViewById(R.id.btn);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.i("MainActivity","onClick 单击事件");
            }
        });
        button.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction()==MotionEvent.ACTION_DOWN){
                    Log.i("MainActivity","onTouch 按下");
                }else if (event.getAction()==MotionEvent.ACTION_UP){
                    Log.i("MainActivity","onTouch 抬起");
                }
                return false;  // 表示未消耗掉这个事件
                //return true; // 表示消耗掉这个事件
            }
        });
    }
}

未消耗掉这个事件时,单击事件可以获取到,触摸事件优先级高于单击事件:

 消耗掉这个事件时,单击事件不能获取到:

 https://github.com/hanyuhang-hz/android-demos

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值