I have an EditText that has a ListPopupWindow attached to it with recent search queries listed. When a user clicks the EditText, the popup should show, then when the user starts typing, the popup should disappear.
This is mostly working using OnFocusChangeListener, OnTextChangedListener, and OnEditorActionListener. However, if a user has clicked on the EditText, began to type, then clicks the EditText again, I need the popup to come back up. I have tried using an OnClickListener instead of an OnFocusChangeListener but can never get the popup to show with an OnClickListener.
How can I get the ListPopUpWindow to show when the use clicks the EditText if it already has focus?
searchBox.setOnFocusChangeListener(new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean gainFocus) {
//onFocus
if (gainFocus) {
popUpWindow.show();
}
}
});
To dismiss popup once user start typing in EditText field
searchBox.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void afterTextChanged(Editable s) {
popUpWindow.dismiss();
}
});
To clear focus, dismiss popup, and execute search
searchBox.setOnEditorActionListener(new TextView.OnEditorActionListener() {
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if ((actionId & v.getImeOptions()) == actionId) {
if (event != null && event.getAction() == KeyEvent.ACTION_DOWN) {
if (searchBox.getText().toString().length() == 0) return true;
searchBox.clearFocus();
popUpWindow.dismiss();
fetchResults();
Util.hideKeyboard(v);
return true;
}
}
return false;
}
});
You can try replacing the focus change listener with an on touch listener and showing the popup when a MOTION_UP event occurs:
editText.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if ((event.getAction() == MotionEvent.ACTION_UP) {
// Show popup here
}
return false;
}
});
I found the problem. It turns out I wasn't actually using an EditText object, but rather a custom class called MaterialEditText that provides a wrapper around an EditText object to give it Material UI features. The class passes the listeners I had been using onto it's EditText member, however, it was not doing so for either OnClickListener or OnTouchListener, so these listeners were never getting set for the EditText object. Once I added methods to pass these listeners on to the EditText object, I fixed my issue by keeping the code listed above and adding the following:
searchBox.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Show Popup
}
});
Related
I have Two EditTexts. I want On First EditTexts click clear the second and on second edittext click clear the first one. So I have tried OnClickListener and OnTouchListener. But it is not working properly.
et_email.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (!(et_email.getText().toString().equalsIgnoreCase("") && et_mobile.getText().toString().equalsIgnoreCase(""))) {
if (MotionEvent.ACTION_UP == event.getAction()) {
et_mobile.setText("");
et_mobile.setFocusableInTouchMode(true);
et_mobile.setFocusable(true);
et_mobile.requestFocus();
}
return true; // return is important...
} else
return false;
}
});
et_mobile.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (!(et_email.getText().toString().equalsIgnoreCase("") && et_mobile.getText().toString().equalsIgnoreCase(""))) {
if (MotionEvent.ACTION_UP == event.getAction()) {
et_email.setText("");
et_mobile.setFocusableInTouchMode(true);
et_mobile.setFocusable(true);
et_mobile.requestFocus();
}
return true; // return is important...
}
else
return false;
}
});
But the problem is Focus is not setting on first touch and while clicking and unable to clear EditText.
First add this to your Edittext layouts:
android:focusableInTouchMode="false"
Without this line, the EditText will react to touch-mode, and only listen to your onClick() the second time you click your EditText bar.
This will disable touch-mode for EditText, and fire onClick() in first time
focusableInTouchMode
Note: boolean that controls whether a view can take focus while in touch mode. If this is true for a view, that view can gain focus when clicked on, and can keep focus if another view is clicked on that doesn't have this attribute set to true.
than do as follows:
EditText1
EditText et_email = (EditText) findViewById(R.id.yourEditText1);
et_email.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do this
et_mobile.setText("");
//or this
et_mobile.getText().clear();
}
});
EditText2
EditText et_mobile = (EditText) findViewById(R.id.yourEditText2);
et_mobile.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//do this
et_email.setText("");
//or this
et_email.getText().clear();
}
});
This should help u out.
you are clearing the first one one touching the first one, change your variable names in first listener like this
if (!(et_email.getText().toString().equalsIgnoreCase("") && et_mobile.getText().toString().equalsIgnoreCase(""))) {
if (MotionEvent.ACTION_UP == event.getAction()) {
et_mobile.setText("");
et_email.setFocusableInTouchMode(true);
et_email.setFocusable(true);
et_email.requestFocus();
}
return true; // return is important...
} else
I hope this code helps you (it works for me)
edit1 = (EditText) findViewById(R.id.edit1);
edit2 = (EditText) findViewById(R.id.edit2);
edit1.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
edit2.setText("");
}
});
edit2.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
edit1.setText("");
}
});
I'm having a really hard time getting the OnKey event to trigger on my EditText view. I've been Googling for over an hour now and it seems everyone says all you have to do is add a OnKeyListener to the view but it's not triggering it. I tried adding it to the entire Activity and also tried adding it to the view itself but neither way is triggering the function.
My code:
XML:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/interests_editText" />
Java:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.add_post);
interests_editText = (EditText) findViewById(R.id.interests_editText);
interests_editText.setOnKeyListener(new OnKeyListener(){
public boolean onKey( View view, int keyCode, KeyEvent event){
Log.i("DEBUG","TeST");
if (keyCode == KeyEvent.KEYCODE_ENTER) {
return true;
}
else {
return false;
}
}
}
);
Update:
My final goal is to get it to recognize when you press space while in that editText view. I added to the XML
android:inputType="text"
and then changed the code to
public boolean onKey( View view, int keyCode, KeyEvent event){
Log.i("DEBUG","Outside");
if (keyCode == KeyEvent.KEYCODE_SPACE) {
Log.i("DEBUG","Space");
return true;
}
else {
return false;
}
Now the keyboard shows a Next button that when pressed logs "Outside" but it doesn't log "Space"
Do you wanna capture Enter event? If so, try setOnEditorActionListener
For your Update Info: capture space key, try addTextChangedListener
Following up on #BNK's answer I got it to work using the following code:
interests_editText.addTextChangedListener(new TextWatcher() {
#Override
public void afterTextChanged(Editable s) {
String str = s.toString();
if(str.substring(str.length()-1, str.length()).equals(" "))
Log.i("DEBUG","Space pressed");
else if(str.substring(str.length()-1, str.length()).equals("\n"))
Log.i("DEBUG", "Enter pressed");
else
Log.i("DEBUG", "Pressed : " +str.substring(str.length()-1, str.length()) );
}}
I am new to Android and working through a to do list example from a book. I have one Activity which is displaying an EditText and a ListView beneath it. There is an onKey event which should add the text from the EditText to the ListView and clear the EditText. However, when I hit Enter on the keyboard all that happens is a new line is added to the EditText and nothing is added to the ListView.
The onCreate code is:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_to_do_list);
// Get UI references
ListView myListView = (ListView)findViewById(R.id.myListView);
final EditText myEditText = (EditText)findViewById(R.id.myEditText);
myEditText.setText("test");
// Create ArrayList to store To Do items
final ArrayList<String> toDoItems = new ArrayList<String>();
// Create ArrayAdapter to bind items to List View
final ArrayAdapter<String> aa;
aa = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1,
toDoItems);
// Bind Adapter to List View
myListView.setAdapter(aa);
myEditText.setOnKeyListener(new View.OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN)
if ((keyCode == KeyEvent.KEYCODE_DPAD_CENTER) ||
(keyCode == KeyEvent.KEYCODE_ENTER)) {
toDoItems.add(0, myEditText.getText().toString());
aa.notifyDataSetChanged();
myEditText.setText("");
return true;
}
return false;
}
});
}
I've added the myEditText.setText("test"); just to ensure the reference to myEditText is working, which it is. I've tried removing the if statements from the onKey event and it just doesn't appear to be registering key events at all. Can anyone advise what I'm doing wrong here?
You could try using a OnEditorActionListener instead:
http://developer.android.com/reference/android/widget/TextView.html#setOnEditorActionListener(android.widget.TextView.OnEditorActionListener)
You could set on the edittext in XML:
android:imeOptions="actionDone"
and then in code:
myEditText.setOnEditorActionListener(new EditText.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
// your action here
return true;
}
return false;
}
)};
Are you using the virtual keyboard?
In that case the problem is that an OnKeyListener only gets called by hardware buttons. Take a look here:
http://developer.android.com/reference/android/view/View.OnKeyListener.html
The first line says: Interface definition for a callback to be invoked when a hardware key event is dispatched to this view.
Perpaps something line this will solve your problem: Validating edittext in Android
I was able to get that same example to work by adding the following attribute to the EditText element android:inputType="text". This changed the software keyboard that came up for the user and included a Send button.
In the setOnKeyListener code, I changed it to the following:
myEditText.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP)
if (keyCode == KeyEvent.KEYCODE_ENTER)
{
todoItems.add(0, myEditText.getText().toString());
aa.notifyDataSetChanged();
myEditText.setText("");
return true;
}
return false;
}
});
Don't use KEYCODE_DPAD_CENTER as that's a hardware button for devices that had up, down, left, right arrows.
Following code solved such problem:
You just need to need to add addTextChangedListener like this.Rest is self- explanatory
editabltText.addTextChangedListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
#Override
public void afterTextChanged(Editable editable)
{
}
});
Instead of setOnKeyListener, try to implement setOnEditorActionListener. Hope this helps.
<EditText
android:id="#+id/search"
android:singleLine="true"
android:imeOptions="actionSearch">
try to add singleLine and imeOption attributes.
How do I know when my edit text is done being edited? Like when the user selects the next box, or presses the done button on the soft keyboard.
I want to know this so I can clamp the input. It looks like text watcher's afterTextChanged happens after each character is entered. I need to do some calculations with the input, so I would like to avoid doing the calculation after each character is entered.
thanks
By using something like this
meditText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
switch (actionId){
case EditorInfo.IME_ACTION_DONE:
case EditorInfo.IME_ACTION_NEXT:
case EditorInfo.IME_ACTION_PREVIOUS:
yourcalc();
return true;
}
return false;
}
});
EditText inherits setOnFocusChangeListener which takes an implementation of OnFocusChangeListener.
Implement onFocusChange and there's a boolean parameter for hasFocus. When this is false, you've lost focus to another control.
EDIT
To handle both cases - edit text losing focus OR user clicks "done" button - create a single method that gets called from both listeners.
private void calculate() { ... }
btnDone.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
calculate();
}
});
txtEdit.setOnFocusChangeListener(new OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if(!hasFocus)
calculate();
}
});
Using an EditText object xml defined like this:
<EditText
android:id="#+id/create_survey_newquestion_editText_minvalue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:ems="4"
android:imeOptions="actionDone"
android:inputType="number" />
We can capture its text i) when the user clicks the Done button on the soft keyboard (OnEditorActionListener) or ii) when the EditText has lost the user focus (OnFocusChangeListener) which now is on another EditText:
/**
* 3. Set the min value EditText listener
*/
editText= (EditText) this.viewGroup.findViewById(R.id.create_survey_newquestion_editText_minvalue);
editText.setOnEditorActionListener(new OnEditorActionListener()
{
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event)
{
String input;
if(actionId == EditorInfo.IME_ACTION_DONE)
{
input= v.getText().toString();
MyActivity.calculate(input);
return true; // consume.
}
return false; // pass on to other listeners.
}
});
editText.setOnFocusChangeListener(new View.OnFocusChangeListener()
{
#Override
public void onFocusChange(View v, boolean hasFocus)
{
String input;
EditText editText;
if(!hasFocus)
{
editText= (EditText) v;
input= editText.getText().toString();
MyActivity.calculate(input);
}
}
});
This works for me. You can hide the soft keyboard after made the calculations using a code like this:
private void hideKeyboard(EditText editText)
{
InputMethodManager imm= (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(editText.getWindowToken(), 0);
}
Edit: added return values to onEditorAction
I have done this simple thing, when focus is shifted from edit text get the text. This will work if user shifts the focus to select other views like a button or other EditText or any view.
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
EditText editText = (EditText) v;
String text = editText.getText().toString();
}
}
});
To be more highlevel you may use TextWatcher's afterTextChanged() method.
I would like to be able to close the editpreference dialog (as shown here http://twitpic.com/18ttdp) by pressing the 'Done' button on the keyboard.
Currently, pressing 'Done' just dismisses the keyboard but leaves the dialog.
In other parts of my application I use code similar to the following to intercept the 'Done' key press and execute actions in my activity:
text.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
//do stuff here
return true;
}
return false;
}
});
However, I am unsure of how to do achieve this same effect in my preference activity or layout xml.
Instead of adding the listener there, you should do something similar to this:
getDialog().setOnKeyListener(new OnKeyListener() {
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
dialog.dismiss();
return true;
}
});
This code will dismiss the dialog when a key is pressed.
I had the same problem, this is how I solved it:
// edit text to get input
final EditText input = new EditText(this);
//input.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL);
input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_IME_MULTI_LINE);
alert.setView(input);
// ok button
alert.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
// do stuff
}
});
For my needs, the input was a number (hence the commented out line) but if you want text use what's there.
Here is how I solved it:
final EditTextPreference namePref = (EditTextPreference) findPreference("name");
namePref.getEditText().setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if(actionId == EditorInfo.IME_ACTION_DONE) {
namePref.onClick(null, DialogInterface.BUTTON_POSITIVE);
namePref.getDialog().dismiss();
return true;
}
return false;
}
});
But you may want to consider subclassing EditTextPreference instead, since this onClick call is a hack, and its implementation may change in the future.