监听器在 OnUiThread 中不起作用
Listeners don't work in OnUiThread
所以我有一个带有 RunOnUiThread 的 AsyncTask 以交互方式更改 ui 元素并添加 TableRows 问题出在 TableRows 中的侦听器上。只有一个有效,但其他无效。这是我的代码中的一个简单的
public class SearchAsync extends AsyncTask<String, String, String> {
private Context mContext;
private Activity mAct;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
public void mytask(Context context, Activity act) {
mContext = context;
mAct = act;
}
@Override
protected String doInBackground(final String... arg0) {
String sc2 = "Alpha";
mAct.runOnUiThread(new Runnable() {
@Override
public void run() {
GridLayout gey = (GridLayout) mAct.findViewById(R.id.greylayout);
TableLayout tbly = (TableLayout) mAct.findViewById(R.id.listviewtable);{
final TableRow tbro = new TableRow(mContext);
TextView tev = new TextView(mContext);
tbro.setBackground(mAct.getResources().getDrawable(R.drawable.mybgbg));
tev.setTextColor(Color.WHITE);
tev.setText(sc2);
tbro.addView(tev);
tbro.setOnClickListener(new View.OnClickListener() { // this listener doesn't work.
public void onClick(View v) {
System.out.println("yey! it works");
}
});
tbro.setOnLongClickListener(new View.OnLongClickListener(){ // this listener doesn't work too.
@Override
public boolean onLongClick(View v){
System.out.println("yey! it works too!");
return true;
}
});
tbro.setOnTouchListener(new View.OnTouchListener() { // this listener works perfectly.
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
tbro.setBackground(mAct.getResources().getDrawable(R.drawable.mybgi));
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
tbro.setBackground(mAct.getResources().getDrawable(R.drawable.mybgbg));
}
return true;
}
});
tbro.setId(R.id.layoutx1);
tbro.setLongClickable(true);
tbro.setClickable(true);
tbly.addView(tbro);
}
}
}
TableRow tete = (TableRow)mAct.findViewById(R.id.layoutx1);
});
}
catch(JSONException e){
Log.e(TAG, "Json parsing error: " + e.getMessage());
);
}
}
return null;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(null);
final String rslt;
rslt = result;
mAct.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast toast = Toast.makeText(mContext, rslt, Toast.LENGTH_SHORT);
toast.show();
}
});
}
所以只有 OnTouchListener 有效,但其他的无效.. 我不知道为什么。
这只是 runOnUiThread 和 runonmainthread 中的一个问题。
我尝试了 onPreExecute() 方法和 onPostExecute 代码。没有任何效果。
但在 MainActivity 中它工作得很好。
感谢阅读我的问题。
发生这种情况是因为您正在从 onClick()
中 returning true
,这向系统表明您有 "consumed" 事件。
View.OnTouchListener | Android Developers
触摸事件会在点击事件之前发生,因为ACTION_DOWN
会触发触摸事件,但是在点击事件之前你还需要有一个ACTION_UP
。
当你从 onTouch()
return true
时,这会消耗触摸事件,防止 ACTION_UP
触发点击事件。
一般来说,您不应同时使用 OnTouchListener
和 OnClickListener
。
您似乎只是在使用 OnTouchListener
来更改背景。 StateListDrawable
会好得多。您设置一次背景,其余的由状态列表处理:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/mybgi"
android:state_pressed="true"/>
<item
android:drawable="@drawable/mybgbg"/>
</selector>
所以我有一个带有 RunOnUiThread 的 AsyncTask 以交互方式更改 ui 元素并添加 TableRows 问题出在 TableRows 中的侦听器上。只有一个有效,但其他无效。这是我的代码中的一个简单的
public class SearchAsync extends AsyncTask<String, String, String> {
private Context mContext;
private Activity mAct;
@Override
protected void onPreExecute() {
super.onPreExecute();
}
public void mytask(Context context, Activity act) {
mContext = context;
mAct = act;
}
@Override
protected String doInBackground(final String... arg0) {
String sc2 = "Alpha";
mAct.runOnUiThread(new Runnable() {
@Override
public void run() {
GridLayout gey = (GridLayout) mAct.findViewById(R.id.greylayout);
TableLayout tbly = (TableLayout) mAct.findViewById(R.id.listviewtable);{
final TableRow tbro = new TableRow(mContext);
TextView tev = new TextView(mContext);
tbro.setBackground(mAct.getResources().getDrawable(R.drawable.mybgbg));
tev.setTextColor(Color.WHITE);
tev.setText(sc2);
tbro.addView(tev);
tbro.setOnClickListener(new View.OnClickListener() { // this listener doesn't work.
public void onClick(View v) {
System.out.println("yey! it works");
}
});
tbro.setOnLongClickListener(new View.OnLongClickListener(){ // this listener doesn't work too.
@Override
public boolean onLongClick(View v){
System.out.println("yey! it works too!");
return true;
}
});
tbro.setOnTouchListener(new View.OnTouchListener() { // this listener works perfectly.
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
tbro.setBackground(mAct.getResources().getDrawable(R.drawable.mybgi));
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
tbro.setBackground(mAct.getResources().getDrawable(R.drawable.mybgbg));
}
return true;
}
});
tbro.setId(R.id.layoutx1);
tbro.setLongClickable(true);
tbro.setClickable(true);
tbly.addView(tbro);
}
}
}
TableRow tete = (TableRow)mAct.findViewById(R.id.layoutx1);
});
}
catch(JSONException e){
Log.e(TAG, "Json parsing error: " + e.getMessage());
);
}
}
return null;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(null);
final String rslt;
rslt = result;
mAct.runOnUiThread(new Runnable() {
@Override
public void run() {
Toast toast = Toast.makeText(mContext, rslt, Toast.LENGTH_SHORT);
toast.show();
}
});
}
所以只有 OnTouchListener 有效,但其他的无效.. 我不知道为什么。 这只是 runOnUiThread 和 runonmainthread 中的一个问题。
我尝试了 onPreExecute() 方法和 onPostExecute 代码。没有任何效果。
但在 MainActivity 中它工作得很好。
感谢阅读我的问题。
发生这种情况是因为您正在从 onClick()
中 returning true
,这向系统表明您有 "consumed" 事件。
View.OnTouchListener | Android Developers
触摸事件会在点击事件之前发生,因为ACTION_DOWN
会触发触摸事件,但是在点击事件之前你还需要有一个ACTION_UP
。
当你从 onTouch()
return true
时,这会消耗触摸事件,防止 ACTION_UP
触发点击事件。
一般来说,您不应同时使用 OnTouchListener
和 OnClickListener
。
您似乎只是在使用 OnTouchListener
来更改背景。 StateListDrawable
会好得多。您设置一次背景,其余的由状态列表处理:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:drawable="@drawable/mybgi"
android:state_pressed="true"/>
<item
android:drawable="@drawable/mybgbg"/>
</selector>