繁体   English   中英

在执行之前取消可运行/处理程序

[英]cancel a runnable/handler before execution

我有一个设置了onClickListener的textView。 当用户按住手指7秒钟然后抬起时,会弹出一个对话框,单击“确定”按钮时会激发意图,如果单击“否定”按钮,则会取消操作。 当用户按住textView足够长的时间时,我想要一个视觉提示,因此我创建了一个处理程序和一个可运行的控件,该控件在7000ms之后触发,并稍微更改了根视图的背景颜色。 起初效果不错。 如果用户按住7秒钟,背景将发生变化,您可以抬起手指以显示对话框。 如果取消,则一切都会恢复正常,包括背景色。 问题是,如果用户在7秒之前抬起手指,我不知道如何取消MotionEvent.ACTION_UP上的处理程序。 这是我的代码:

View.OnTouchListener listener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                final Handler handler = new Handler();
                final Runnable runnable = new Runnable(){
                    @Override
                    public void run(){
                        Toast.makeText(mContext, "This is working", Toast.LENGTH_SHORT).show();
                        mMainContainer.setBackgroundColor(getResources().getColor(R.color.alert_color));
                    }
                };

                View rootView = LayoutInflater.from(mContext).inflate(R.layout.admin_dialog, null);

                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    // get the first touch in the series
                        start = System.currentTimeMillis();


                    handler.postDelayed(runnable, 7000);

                }
                if (event.getAction() == MotionEvent.ACTION_UP) {

                    handler.removeCallbacks(runnable);

                    stop += System.currentTimeMillis();

                    if ((stop - start) > 7000){

                        // reset values
                        start = 0;
                        stop = 0;

                        final EditText password = (EditText)rootView.findViewById(R.id.admin_password_et);

                        AlertDialog.Builder dialog = new AlertDialog.Builder(mContext)
                                .setView(rootView)
                                .setTitle("Edit Configuration?")
                                .setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        int counter = 1;
                                        if(password.getText().toString().equalsIgnoreCase("mq")){
                                            Intent intent = new Intent(mContext, MainActivity.class);
                                            startActivity(intent);
                                        } else {
                                            mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light));
                                            Toast.makeText(mContext, "Wrong password, Access denied", Toast.LENGTH_SHORT)
                                            .show();
                                            dialog.dismiss();
                                        }
                                    }
                                })
                                .setNegativeButton(R.string.no_button, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light));
                                        dialog.dismiss();
                                    }
                                });
                        dialog.create();
                        dialog.show();
                    } else {

                        // reset values
                        start = 0;
                        stop = 0;
                    }
                }

                return true;
            }
        };
        mAppTitle.setOnTouchListener(listener);

我以为对handler.removeCallbacks(runnable);的调用; 是答案,但是没有用。 现在,如果您按下textView并在7秒钟之前将手指拉开,对话框将不会弹出,但是7秒钟后背景颜色仍然会改变。 如何取消该操作? 我是否需要以其他方式实施?

您可以尝试不使用7000作为重复项,而可以做一个更小的间隔,而是执行时间差异,因此在处理程序中检查差异是否已超过7000ms。 一旦满足条件,就可以执行操作。 希望我能正确理解您的问题。

   Handler handler = new Handler();
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    if (diff >7000) {
                        handler.removeCallbacks(runnable);
                    } else {
                        handler.postDelayed(runnable, 500);
                    }
                }
            };

我想到了! 谢谢大家的帮助,但我想出了我认为是最佳的解决方案。 我在OnTouchListener外部创建了CountDownTimer对象。 在MotionEven.ACTION_UP上,我取消了计时器。 以下代码可帮助其他人:

final CountDownTimer timer = new CountDownTimer(7000, 1000) {
            @Override
            public void onTick(long millisUntilFinished) {

            }

            @Override
            public void onFinish() {
                mMainContainer.setBackgroundColor(getResources().getColor(R.color.alert_color));
            }
        };

        View.OnTouchListener listener = new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {

                View rootView = LayoutInflater.from(mContext).inflate(R.layout.admin_dialog, null);

                if (event.getAction() == MotionEvent.ACTION_DOWN) {
                    // get the first touch in the series
                    start = System.currentTimeMillis();
                    timer.start();

                }
                if (event.getAction() == MotionEvent.ACTION_UP) {

                    timer.cancel();

                    stop += System.currentTimeMillis();

                    if ((stop - start) > 7000) {

                        // reset values
                        start = 0;
                        stop = 0;

                        final EditText password = (EditText) rootView.findViewById(R.id.admin_password_et);

                        AlertDialog.Builder dialog = new AlertDialog.Builder(mContext)
                                .setView(rootView)
                                .setTitle("Edit Configuration?")
                                .setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        int counter = 1;
                                        if (password.getText().toString().equalsIgnoreCase("mq")) {
                                            Intent intent = new Intent(mContext, MainActivity.class);
                                            startActivity(intent);
                                        } else {
                                            mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light));
                                            Toast.makeText(mContext, "Wrong password, Access denied", Toast.LENGTH_SHORT)
                                                    .show();
                                            dialog.dismiss();
                                        }
                                    }
                                })
                                .setNegativeButton(R.string.no_button, new DialogInterface.OnClickListener() {
                                    @Override
                                    public void onClick(DialogInterface dialog, int which) {
                                        mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light));
                                        dialog.dismiss();
                                    }
                                });
                        dialog.create();
                        dialog.show();
                    } else {

                        // reset values
                        start = 0;
                        stop = 0;
                    }
                }

                return true;
            }
        };
        mAppTitle.setOnTouchListener(listener);
    }

您的实际问题是,每个onTouch都会创建一个Runnable的新实例,因此removeCallback将与您之前发布的实例不匹配,一种解决方案是:

将Runnable声明在方法范围之外,仅在关闭时将其初始化。

我还添加了ACTION_CANCEL作为UP,导致此行为可能发生。

        View.OnTouchListener listener = new View.OnTouchListener() {
        Runnable runnable;
        @Override
        public boolean onTouch(View v, MotionEvent event) {

            final Handler handler = new Handler();

            View rootView = LayoutInflater.from(mContext).inflate(R.layout.admin_dialog, null);

            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                // get the first touch in the series
                    start = System.currentTimeMillis();


             runnable = new Runnable(){
                @Override
                public void run(){
                    Toast.makeText(mContext, "This is working", Toast.LENGTH_SHORT).show();
                    mMainContainer.setBackgroundColor(getResources().getColor(R.color.alert_color));
                }
            };
                handler.postDelayed(runnable, 7000);

            }
            if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {

                handler.removeCallbacks(runnable);

                stop += System.currentTimeMillis();

                if ((stop - start) > 7000){

                    // reset values
                    start = 0;
                    stop = 0;

                    final EditText password = (EditText)rootView.findViewById(R.id.admin_password_et);

                    AlertDialog.Builder dialog = new AlertDialog.Builder(mContext)
                            .setView(rootView)
                            .setTitle("Edit Configuration?")
                            .setPositiveButton(R.string.yes_button, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    int counter = 1;
                                    if(password.getText().toString().equalsIgnoreCase("mq")){
                                        Intent intent = new Intent(mContext, MainActivity.class);
                                        startActivity(intent);
                                    } else {
                                        mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light));
                                        Toast.makeText(mContext, "Wrong password, Access denied", Toast.LENGTH_SHORT)
                                        .show();
                                        dialog.dismiss();
                                    }
                                }
                            })
                            .setNegativeButton(R.string.no_button, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    mMainContainer.setBackgroundColor(getResources().getColor(android.R.color.background_light));
                                    dialog.dismiss();
                                }
                            });
                    dialog.create();
                    dialog.show();
                } else {

                    // reset values
                    start = 0;
                    stop = 0;
                }
            }

            return true;
        }
    };
    mAppTitle.setOnTouchListener(listener);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM