【我的Android进阶之旅】自定义一个Dialog, 设置setOnKeyListener方法监听返回键, 按下返回键的时候会执行两次的bug

一、问题描述

项目中有段代码被其他同事修改了,然后出现了一个bug,bug描述如下所示:
项目收到某个推送的时候,弹出一个对话框,让用户处理。只有两个选项“同意”或者是“拒绝”。

在这里插入图片描述
如果用户不想当即处理,可以点击返回键,然后这个时候再弹一个弹框出来,有两个选项“”取消“”和“暂不处理”。用户点击了“暂不处理”的话,两个弹框都消失,用户可以通过其他的途径来处理这个推送。
在这里插入图片描述
如上所示的功能,在某段代码被其他同事修改之后,第一个弹框出现的时候点击返回键,第二个弹框会出现两个。

二、问题分析

查看问题代码,如下所示:
在这里插入图片描述
源代码如下所示:

//自定义的第一个Dialog弹框
final Dialog bindDialog = DialogUtil.makeDoubleBtnConfirmDialog(activity, bean, false);
//第一个Dialog弹框 监听返回键
bindDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
            //展示第二个Dialog弹框
            showTipDialog(bindDialog, activity);
            return true;
        }
        return false;
    }
});
//展示第一个Dialog弹框
DialogUtil.showDialog(bindDialog);

这代码又没有日志打印,所以在onKey()方法回调中,加入日志打印。
在这里插入图片描述

然后发现,这个日志打印按一下返回键,被回调两次,如下所示:
在这里插入图片描述

查看 android.view.KeyEvent#getAction 源代码如下所示:

 /**
     * Retrieve the action of this key event.  May be either
     * {@link #ACTION_DOWN}, {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
     *
     * @return The event action: ACTION_DOWN, ACTION_UP, or ACTION_MULTIPLE.
     */
    public final int getAction() {
        return mAction;
    }

   /**
     * {@link #getAction} value: the key has been pressed down.
     */
    public static final int ACTION_DOWN             = 0;
    /**
     * {@link #getAction} value: the key has been released.
     */
    public static final int ACTION_UP               = 1;
    /**
     * {@link #getAction} value: multiple duplicate key events have
     * occurred in a row, or a complex string is being delivered.  If the
     * key code is not {#link {@link #KEYCODE_UNKNOWN} then the
     * {#link {@link #getRepeatCount()} method returns the number of times
     * the given key code should be executed.
     * Otherwise, if the key code is {@link #KEYCODE_UNKNOWN}, then
     * this is a sequence of characters as returned by {@link #getCharacters}.
     */
    public static final int ACTION_MULTIPLE         = 2;

在这里插入图片描述
在这里插入图片描述

因此,可以判断出来,日志打印出的效果就是:按一下返回键,onKey方法回调两次的原因就是处理了android.view.KeyEvent#ACTION_DOWNandroid.view.KeyEvent#ACTION_UP两个事件。

因此我们处理一下,只需要处理其中一个事件(android.view.KeyEvent#ACTION_DOWNandroid.view.KeyEvent#ACTION_UP其中的一个),然后弹第二个框即可。

三、解决方案

在这里插入图片描述

//自定义的第一个Dialog弹框
final Dialog bindDialog = DialogUtil.makeDoubleBtnConfirmDialog(activity, bean, false);
//第一个Dialog弹框 监听返回键
bindDialog.setOnKeyListener(new DialogInterface.OnKeyListener() {
    @Override
    public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
         //按一次返回键会触发KeyEvent.ACTION_DOWN和KeyEvent.ACTION_UP两个事件导致弹了两次框,所以只处理KeyEvent.ACTION_UP即可。
         if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
               //展示第二个Dialog弹框
               showTipDialog(bindDialog, activity);
               return true;
          }
          return false;
    }
});
//展示第一个Dialog弹框
DialogUtil.showDialog(bindDialog);

这样就修复了该bug。


作者:欧阳鹏 欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:https://blog.csdn.net/qq446282412/article/details/96966136
☞ 本人QQ: 3024665621
☞ QQ交流群: 123133153
☞ github.com/ouyangpeng
☞ oypcz@foxmail.com


发布了469 篇原创文章 · 获赞 1452 · 访问量 356万+
展开阅读全文

自定义View,用外部类定义OnKeyListener监听器,但是在AVD打不开,内部类的方式可以

12-16

public class MainActivity extends Activity { private int speed = 10; PlaneView planeView = new PlaneView(null); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); //final PlaneView planeView = new PlaneView(this); setContentView(planeView); planeView.setBackgroundResource(R.drawable.back); WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); DisplayMetrics metrics = new DisplayMetrics(); display.getMetrics(metrics); planeView.currentX = metrics.widthPixels / 2; planeView.currentY = metrics.heightPixels - 400; onKeyListener listener = new onKeyListener(); planeView.setOnKeyListener(listener); /******************外部类作为事件监听器*********************/ } /******************外部类作为事件监听器*********************/ class onKeyListener implements OnKeyListener{ /*private PlaneView plane; public onKeyListener(PlaneView planeView){ this.plane = planeView; }*/ @Override public boolean onKey(View source, int keycode, KeyEvent event) { // TODO Auto-generated method stub switch(event.getKeyCode()){ case KeyEvent.KEYCODE_S: planeView.currentY += speed; break; case KeyEvent.KEYCODE_W: planeView.currentY -= speed; break; case KeyEvent.KEYCODE_A: planeView.currentX -= speed; break; case KeyEvent.KEYCODE_D: planeView.currentX += speed; break; } planeView.invalidate(); return true; } } ``` 这是自定义View public class PlaneView extends View{ public float currentX; public float currentY; Bitmap plane; Paint p = new Paint(); public PlaneView(Context context) { super(context); // TODO Auto-generated constructor stub plane = BitmapFactory.decodeResource(context.getResources(), R.drawable.plane); setFocusable(true); } public void onDraw(Canvas canvas){ super.onDraw(canvas); canvas.drawBitmap(plane, currentX, currentY, p); } } ``` 问答

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 数字20 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览