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



我有一个textView,我已经设置了onClickListener。当用户按住手指7秒,然后抬起时,会显示一个对话框,当单击正按钮时会触发意图,如果单击负按钮则会取消操作。当用户按住textView足够长的时间时,我想要一个视觉提示,所以我创建了一个处理程序和一个可运行程序,它在7000ms后触发,并稍微更改根视图的背景色。一开始效果很好。如果用户按住7秒钟,背景就会改变,您可以抬起手指来显示对话框。如果取消,一切都会恢复正常,包括背景色。问题是我不知道如何取消MotionEvent上的处理程序。ACTION_UP(如果用户在7秒内抬起手指)。这是我的代码:

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(可运行);是答案,但没有奏效。和现在一样,如果你在7秒内按下文本View并将手指移开,对话框不会弹出,但7秒后背景颜色仍会改变。我怎样才能取消那个手术?我需要以不同的方式来实现吗?

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

在方法范围之外声明Runnable,并仅在down时初始化它。

我还添加了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);

您可以尝试不使用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);
}

最新更新