
[英]Cancel pause/wait on a postdelayed handler/runnable and still activate the paused code
[英]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.