問題描述
我制作了一個(gè)非常簡單的測試應(yīng)用程序,其中包含一個(gè)活動(dòng)和一個(gè)布局.onClick
在第一次按下時(shí)不會(huì)觸發(fā),因?yàn)樗鼞?yīng)該觸發(fā).
I made a very simple test application with one activity and one layout. The onClick
doesn't trigger the first time it is pressed, as it should.
活動(dòng):
package com.example.mytest;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final EditText ed1 = (EditText) findViewById(R.id.editText1);
ed1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(getApplicationContext(), "1", Toast.LENGTH_LONG)
.show();
}
});
}
}
布局:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<EditText
android:id="@+id/editText1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:ems="10" >
<requestFocus />
</EditText>
<EditText
android:id="@+id/editText2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/editText1"
android:ems="10" />
</RelativeLayout>
如果你運(yùn)行這個(gè)應(yīng)用程序,然后點(diǎn)擊第二個(gè)editText
,然后再點(diǎn)擊第一個(gè),它不會(huì)觸發(fā)onClick
.您可以繼續(xù)來回選擇,它根本不會(huì)觸發(fā) onClick
.我需要這個(gè)基本功能,但一直想不出一種讓它工作的方法.想法?
If you run this application, and click on the second editText
and then back on the first one, it will not trigger the onClick
. You can keep selecting back and forth and it will not trigger the onClick
at all. I need this basic functionality, but haven't been able to think of a way to get it to work. Ideas?
我在我的 API 級別 16 物理設(shè)備和我的 API 級別 8 模擬器上嘗試了所有推薦的方法,但我遇到了同樣的問題.
I have tried all of the methods recommended on my API level 16 physical device and my API level 8 emulator, but I get the same problem.
當(dāng) editText1
獲得焦點(diǎn)并被點(diǎn)擊時(shí),onClick
方法就會(huì)觸發(fā).如果聚焦 editText2
,然后單擊 editText1
,它不會(huì)觸發(fā).大問題.
When editText1
is focused and is clicked on, then the onClick
method fires. If editText2
is focussed, and then editText1
is clicked, it doesn't fire. Big problem.
推薦答案
概述,當(dāng)用戶與任何 UI 組件交互時(shí),各種偵聽器按自上而下的順序調(diào)用.如果較高優(yōu)先級的偵聽器之一消耗事件",則不會(huì)調(diào)用較低的偵聽器.
Overview, when a user interacts with any UI component the various listeners are called in a top-down order. If one of the higher priority listeners "consumes the event" then the lower listeners will not be called.
在您的情況下,這三個(gè)偵聽器按順序調(diào)用:
In your case these three listeners are called in order:
- OnTouchListener
- OnFocusChangeListener
- OnClickListener
用戶第一次觸摸 EditText 時(shí),它會(huì)獲得焦點(diǎn),以便用戶可以鍵入.操作在這里被消耗.因此較低優(yōu)先級的 OnClickListener 不會(huì)被調(diào)用.每次連續(xù)觸摸都不會(huì)改變焦點(diǎn),因此這些事件會(huì)向下傳遞到 OnClickListener.
The first time the user touches an EditText it receives focus so that the user can type. The action is consumed here. Therefor the lower priority OnClickListener is not called. Each successive touch doesn't change the focus so these events trickle down to the OnClickListener.
按鈕(和其他此類組件)不會(huì)從觸摸事件中獲得焦點(diǎn),這就是每次調(diào)用 OnClickListener 的原因.
Buttons (and other such components) don't receive focus from a touch event, that's why the OnClickListener is called every time.
基本上,您有三個(gè)選擇:
自己實(shí)現(xiàn)一個(gè) OnTouchListener:
Implement an OnTouchListener by itself:
ed1.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if(MotionEvent.ACTION_UP == event.getAction())
editTextClicked(); // Instead of your Toast
return false;
}
});
每次觸摸 EditText 時(shí)都會(huì)執(zhí)行此操作.請注意,偵聽器返回 false
,這允許事件向下傳遞到內(nèi)置的 OnFocusChangeListener,它會(huì)更改焦點(diǎn),以便用戶可以鍵入 EditText.
This will execute every time the EditText is touched. Notice that the listener returns false
, this allows the event to trickle down to the built-in OnFocusChangeListener which changes the focus so the user can type in the EditText.
與 OnClickListener 一起實(shí)現(xiàn) OnFocusChangeListener:
Implement an OnFocusChangeListener along with the OnClickListener:
ed1.setOnFocusChangeListener(new OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if(hasFocus)
editTextClicked(); // Instead of your Toast
}
});
當(dāng)您的 OnClickListener 捕獲所有其他事件時(shí),此偵聽器會(huì)在焦點(diǎn)更改時(shí)捕獲第一個(gè)觸摸事件.
This listener catches the first touch event when the focus is changed while your OnClickListener catches every other event.
(這不是一個(gè)有效的答案,但知道這是一個(gè)很好的技巧.)在你的 XML 中將 focusable 屬性設(shè)置為 false
:
(This isn't a valid answer here, but it is a good trick to know.) Set the focusable attribute to false
in your XML:
android:focusable="false"
現(xiàn)在 OnClickListener 將在每次被點(diǎn)擊時(shí)觸發(fā).但這使得 EditText 無用,因?yàn)橛脩魺o法再輸入任何文本...
Now the OnClickListener will fire every time it is clicked. But this makes the EditText useless since the user can no longer enter any text...
注意:
getApplicationContext()
會(huì)造成內(nèi)存泄漏.一個(gè)好習(xí)慣是避免使用它,除非絕對必要.您可以安全地改用 v.getContext()
.
希望有幫助!
這篇關(guān)于onClick 事件未觸發(fā) |安卓的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網(wǎng)!