I am getting the users information from an edit text. I do have a listener that gets their entered information after clicking submit, but I want to also get the entered info after clicking back or clicking somewhere else:
For example, if the users clicks on the black space, I want to get the text they entered. If they type "hello", and click back rather than "enter", I still want to get the text hello. If, however, they don't type anything, I don't care about their input. How can I achieve this?
Thanks,
Ruchir
First add these as a class variables
private String inputText;
private EditText yourEditText;
Get the instance of your EditText View
yourEditText = (EditText)findViewById(R.id.your_editText);
When a button is clicked, you can get the content of the EditText field like this
Button mButton = (Button)findViewById(R.id.m_button);
mButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
inputText = yourEditText.getText().toString();
}
});
If a user press the Back button, you can get the input if any like this
#Override
public void onBackPressed() {
inputText = yourEditText.getText().toString();
super.onBackPressed();
}
Then check if there is any value assigned to your String variable
if(inputText.equals("") || inputText == null){
// there is no value
}else{
// there is value entered.
}
To extend my solution for clicking some where else
add a class variable
private boolean isEditTextHasFocus;
then create a focus listener which will check if the Edittext has focus
private View.OnFocusChangeListener focusListener = new View.OnFocusChangeListener() {
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus){
isEditTextHasFocus = true;
} else {
isEditTextHasFocus = false;
}
}
}
Add this line in onCreate(Bundle savedInstanceState) method
yourEditText.setOnFocusChangeListener(focusListener);
Then override to onTouchEvent(MotionEvent event) listener and access the Edittext input when the key up action is called
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
if(!isEditTextHasFocus){
inputText = yourEditText.getText().toString();
}
}
return true;
}
I hope this will give you a further idea to find your unique solution.
Overriding what happens when the back button is pressed is bad practice and is unnecessary for what you want to do.
You need to use a special listener called onFocusChangedListener. This function is called anytime an element gains or loses focus. In this case for your editText it will be called whenever someone clicks on it or away. Pressing the back button or leaving the editText in any way will call this function. In the following code I check if
if(!username.hasFocus())
which makes it so the value is only saved when focus from the editText is lost rather than everytime focus is changed.
You haven't added any of your own code so I am just going to use obvious placeholder variables in my code example.
Edittext username = (EditText findViewById(R.id.YOUR_EDITTEXTS_ID);
String previousValue = ""; // to keep track of value change
String usernameValue = "";
username.setOnFocusChangeListener(new View.OnFocusChangeListener(
{
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (username.hasFocus()){
//take note of value for comparison when clicking away
previousValue = username.getText().toString();
} else if (!username.hasFocus()){
// check if value has changed
if (!previousValue.equals(username.getText().toString()){
usernameValue = username.getText().toString();
}
}
}
});
Related
I added the following lines of Code into my OnCreate method.My goal is to assign a button to two functions and to call them up alternately. With the first click the text of the button should be changed and the EditText should be editable. At the second click, the fields should no longer be editable and the button text should change to the first alternative. I have implemented two OnClickListeners and the program structure seems logical to me. Nevertheless, I get an error message; "Cannot resolve symbol onClickListener". What can I do to get the setup described above up and running? Thanks for all responses!
private Button ProfilUpdate;
ProfilUpdate=findViewById(R.id.buttonProfilUpdate);
.
.
.
.
final ProfilUpdate.OnClickListener listener2 = new View.OnClickListener() {
#Override
public void onClick(View v) {
ProfilUpdate.setText("Profil bearbeiten");
profilVorname.setFocusable(false);
}
};
ProfilUpdate.OnClickListener listener1 = new View.OnClickListener() {
#Override
public void onClick(View v) {
ProfilUpdate.setText("Ă„nderungen speichern");
profilVorname.setFocusable(true);
v.setOnClickListener(listener2);
}
};
ProfilUpdate.setOnClickListener(listener1);
why don't you create a boolean isFirstClick = true , and then check it in the same listener
ProfilUpdate.OnClickListener listener = new View.OnClickListener() {
#Override
public void onClick(View v) {
if(isFirstClick){
//Do the job for the first click process
isFirstClick= false;
}else {
//Do the job for the second click process
isFirstClick= true;
}
}
};
ProfilUpdate.setOnClickListener(listener);
There can only be one click listener on one view at a time. Use ProfileUpdate.setOnClickListener(listener object). To get the alternate functionality, you can define a Boolean to keep track of the state, for the example, define a class variable at the top Boolean shouldChangeText = true, and in the onClick body in the listener, do something like:
If (shouldChangeText) { // change the text
}
else { // clear the text
}
shouldChangeText = !shouldChangeText
I am trying to set up a system to validate user input, in this case, just checking that there is anything entered by the user.
I have a Utility class that checks that the EditText has data.
I am using an OnFocusChangeListener which then calls the method from the Utility class.
This is the code from the activity:
editText = (EditText) view.findViewById(R.id.editText);
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
if (Utility.checkInput(editText) == false) {
Toast.makeText(getActivity(), "Enter value!",
Toast.LENGTH_SHORT).show();
// TODO....
// Retain focus - do not allow user to move on.
// This is where I am lost...
}
}
}
});
This is the code from the Utility class:
public class Utility {
public static boolean checkInput(EditText editText) {
if (editText.getText().length() != 0) {
return true;
}
return false;
}
//.../
Where I am stumped is how to retain focus if the check input returns false. I want to prevent the user from moving forward. I am sure there is a simple solution, but I have not found it.
I am also wondering if the xml ime.Options will affect this.
Thanks.
EDIT
This is my xml:
<EditText
android:imeOptions="actionDone"
android:inputType="textPersonName"
android:maxLength="24"/>
<spinner ../
<EditText
android:imeOptions="actionDone"
android:inputType="phone"
android:maxLength="12"/>
When I use:
if (!hasFocus) {
if (Utility.checkInput(name) == false) {
Toast.makeText(AddDriverUserActivity.this, "Enter value!",Toast.LENGTH_SHORT).show();
name.requestFocus();
}
}
The problem is, I am using action done (to hide the keyboard), as the user then selects from a spinner then proceeds to the next EditText. So the toast isn't showing until I touch the next edit text (phone) and the focus is then set on two edit texts:
When I reset:
android:imeOptions="actionDone"
to actionNext it shows the toast and then proceeds to the next edittext, as shown in the screen shot, both are focused.
Request focus doesn't prevent it from moving from the edittext.
Use View.requestFocus()
// Retain focus - do not allow user to move on.
editText.requestFocus();
This isn't a solution to retaining focus within the EditText to validate input, but it is an elegant way to check for user input.
I add all my EditTexts to an array and pass them to a method that loops through the array and checks each for input.
In my Utility class:
public static boolean checkAllInput(EditText[] editTexts) {
for (int i = 0; i < editTexts.length; i++) {
if (editTexts[i].getText().length() == 0) {
return false;
}
}
return true;
}
In the activity/fragment:
I add the EditTexts to an array:
final EditText[] editTexts = {arg1, arg2, arg3, arg4, .../};
Then use the function in my OnTouchListener for the button.
addBtn.setOnTouchListener(new View.OnTouchListener() {
#Override public boolean onTouch(View v, MotionEvent event) {
hideKeyboard();
disableButton(addBtn);
if (Utility.checkAllInput(editTexts) == false) {
Toast.makeText(getActivity(), "Enter all fields",
Toast.LENGTH_SHORT).show();
enableButton(addBtn);
} else {
// Do something ..
}
return false;
}
});
I thought this might be helpful for others working their way through android.
As a side note, I have been disabling my buttons, to prevent repeated touches:
Using countdown to set button enabled
I have been search SO for days and have finally compiled enough answers to accomplish what I wanted. First off, it seems to be an often asked question but not really answered (at least not the way I was looking for it). I thought I would share my findings but I also have one small issue left that I would like to ask for help with. Here goes:
I have a TextView which displays a score. It starts at 0 and at an onClick event the score increments and updates the TextView (score is tracked as a byte - valScore).
onLongClick: This was the challenge. I want the user to be able to do a LongClick to correct/change the score. I first found a solution that utilized another layout.xml file with just an EditText element and the OK and CANCEL buttons. This was very cumbersome to change the score as it involved the LongClick, then the dialog opens, then you had to click on the EditText element to open the keyboard, then you enter the value, click DONE and then click OK. I shortened it by figuring out how to open the software keyboard automatically when the dialog opened. However, you still had to click DONE and then OK. I didn't like this action so I continued searching.
Days later I came up with a bit of code and then more and with a lot of playing/hacking around I came up with the following solution:
// set the onLongClickListener for tvScoreHome
tvScoreHome.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
tvScoreHome.setInputType( InputType.TYPE_CLASS_NUMBER );
tvScoreHome.setFocusable(true);
tvScoreHome.setFocusableInTouchMode( true );
tvScoreHome.requestFocus();
InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
imm.showSoftInput(tvScoreHome, InputMethodManager.SHOW_FORCED);
tvScoreHome.setText("");
tvScoreHome.setOnEditorActionListener( new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
valScoreHome = Byte.valueOf( tvScoreHome.getText().toString() );
// This part will hide the keyboard after input
InputMethodManager imm = (InputMethodManager) context.getSystemService(Service.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
tvScoreHome.setFocusable( false );
tvScoreHome.setFocusableInTouchMode( false );
tvScoreHome.setText( Byte.toString(valScoreHome) );
return true;
}
return false;
}
});
return true;
}
});
This works EXACTLY how I want. User performs LongClick the keyboard opens, the user enters the new value and clicks DONE. The TextView is updated and it works great!
The problem arises if the user changes their mind and hits the BACK button on the device. The keyboard closes (GOOD), but then the focus remains on the TextView instead of removing the focus like I do if the DONE button is pressed. So if you cancel out of a change every click after that results in the keyboard opening again instead of just incrementing the score -- until you actually type a value into the keyboard and click DONE (then the regular behavior takes over again. I need to setFocusableInTouchMode to FALSE if the BACK button is pressed.
The other issue is that the setText() method is executed even if the BACK button is pressed if a different value has been typed in. Even though valScoreHome isn't updated the TextView changes. On the next increment it goes to the correct number again, but the setText() should not execute if the BACK button is pressed.
Can someone help me figure this out please?
Both issues can be handled by subclassing TextView.
The back button press that closes the keyboard is handled by overriding onKeyPreIme.
To avoid updating the text when the user closes the keyboard, the score value is saved in the variable mScore, but only if the TextView is currently not focusable. That means, the TextView "remembers" the current value of the score, that was not entered by the user. When the user closes the the keyboard, the text is set back to the saved value.
public class ScoreTextView extends TextView {
private CharSequence mScore;
public ScoreTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public void setText(CharSequence text, BufferType type) {
if (!isFocusable()) {
mScore = text;
}
super.setText(text, type);
}
#Override
public boolean onKeyPreIme(int keyCode, KeyEvent event) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
setFocusable(false);
setFocusableInTouchMode(false);
setText(mScore);
}
return super.onKeyPreIme(keyCode, event);
}
}
I'm new to android and I have not done any Java programming for probably near on 2 years.
I'm following the tutorials at the android developer resources.
More specifically http://developer.android.com/resources/tutorials/views/hello-formstuff.html
Using the EditText widget.
Now the code in the example runs fine (creating the listener in the onCreate method)
However, when playing around I like to define the listener elsewhere, simply because it separates the code out to make it easier to read and manage,
So here is my class with all other stuff taken out
public class HelloFormStuf extends Activity {
private EditText edittext;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button button = (Button) findViewById(R.id.button);
button.setOnClickListener(btnOnClickListener);
edittext = (EditText)findViewById(R.id.edittext);
edittext.setOnKeyListener(etOnKeyListener);
}
private OnClickListener btnOnClickListener = new OnClickListener() {
public void onClick(View v) {
Toast.makeText(HelloFormStuf.this, "Beep Bop", Toast.LENGTH_SHORT).show();
}
};
private OnKeyListener etOnKeyListener = new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// if the event is a key-down event on the enter button
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER))
{
Toast.makeText(HelloFormStuf.this, edittext.getText() ,Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
}; }
Now the original tutorial the edittext is final.
final EditText edittext = (EditText) findViewById(R.id.edittext);
edittext.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// If the event is a key-down event on the "enter" button
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER)) {
// Perform action on key press
Toast.makeText(HelloFormStuff.this, edittext.getText(), Toast.LENGTH_SHORT).show();
return true;
}
return false;
}});
My question is, is this safe to do it this way compared to the tutorial? Because the big difference is now really is that the EditText object is now no longer final and is declared outside the class, but initialized inside the onCreate
Is this safe? such as there will be no little quirks laying around the corner to cause bugs. Does making the EditText object not final really matter?
My button is final, its listener is declared elsewhere and android is happy, I guess because I'm not altering the button or getting any properties of the button. Where as if I keep EditText final, my listener code cannot resolve edittext (The EditText object).
Can I carry on doing this or is there another way (other then declaring it all in the onCreate method).
They make the EditText final so that the reference could not change since you couldn't reassign it to other value. By putting it as an instance variable, a reference to the EditText might change during onKey in
Toast.makeText(HelloFormStuf.this, edittext.getText() ,Toast.LENGTH_SHORT).show();
return true;
Below is the code showing reference reassignment:
// get the EditText from the XML
this.editText = (EditText)this.findViewById(R.id.edittext);
this.editText.setOnKeyListener(etOnKeyListener);
// Create a new EditText
EditText modifiedText = new EditText(this);
modifiedText.setText("Foo Bar");
// reassign the reference to modified text
this.editText = modifiedText;
Now when you press the key, you will see "Foo Bar" in your toast instead of what is in the EditText
in the layout
Optionally, you could get the right reference of the View that you are setting the listener to from the View v argument in onKey below
public abstract boolean onKey (View v, int keyCode, KeyEvent event)
Below is the modification of the listener code to get the text from the EditText where the OnKeyListener is listening to
private OnKeyListener etOnKeyListener = new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
// if the event is a key-down event on the enter button
if ((event.getAction() == KeyEvent.ACTION_DOWN) &&
(keyCode == KeyEvent.KEYCODE_ENTER))
{
// get the EditText that this listener is set on
EditText editTextWithListener = (EditText)v;
// now you will get the text from the EditText where you are listening to even if you
// change the reference as above
Toast.makeText(WebViewMain.this, editTextWithListener.getText() ,Toast.LENGTH_SHORT).show();
return true;
}
return false;
}
};
Note that despite the little risk of having the reference changes, putting your View as instance variable is not an uncommon practice. Many code that I've seen only assign the View once via onCreate like you did thereby reducing the risk of reference reassignment.
For example, send a backspace key to the edit text control to remove a character or send a char code like 112 to append a character in the edittext control programmatically.
Actually, I need a method like
void onKeyReceived(int keyCode)
{
// here I would like to append the keyCode to EditText, I know how to add a visible character, but what about some special keys, like arrow key, backspace key.
}
To send a simulated backspace key press to an EditText you have to send both key press and release events. Like this:
mEditText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_DOWN,
KeyEvent.KEYCODE_DEL, 0));
mEditText.dispatchKeyEvent(new KeyEvent(0, 0, KeyEvent.ACTION_UP,
KeyEvent.KEYCODE_DEL, 0));
This can be used to send any other key code, not just delete.
Your question is not all that clear, but I think you want to modify/append text to a TextView when certain buttons are pressed. If so, you want a combination of some of the existing answers.
#Override
public void onCreate(Bundle savedInstanceState) {
...
(TextView) textView = (TextView) findViewById(R.id.myTextView);
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
switch(keyCode) {
case KeyEvent.KEYCODE_BACK:
// user pressed the "BACK" key. Append "_back" to the text
textView.append("_back");
return true;
case KeyEvent.KEYCODE_DEL:
// user pressed the "BACKSPACE" key. Append "_del" to the text
textView.append("_del");
return true;
default:
return super.onKeyDown(keyCode, event);
}
}
Whether to return true for each case you have handled (as above) or to always return super.onKeyDown(keyCode, event); after your switch statement will depend on your exact requirements. Check the documentation for the behaviour of onKeyDown
If, instead of appending text in each case you want to delete a character, or move the cursor, you could do that in each case statement. Have a look at the TextView documentation for the different methods you can call. Also look at the KeyEvent documentation for a list of the keys you can check for.
I think you need use addTextChangedListener to EditText.
Refer the answer of EditText input with pattern android and Live editing of users input
virsir , I suppose you are looking for dispatching hard keys programmatically.
For that you may try dispatch (KeyEvent.Callback receiver, KeyEvent.DispatcherState state, Object target) with an example at Back and other hard keys: three stories
Hope that helps.
Check for key events in your activity. for example, this code listens for back keypress:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if ((keyCode == KeyEvent.KEYCODE_BACK))
{
finish();
}
return super.onKeyDown(keyCode, event);
}
just use the setText method to do this. If you are wanting to simulate a backspace you could do something like this.
String curText = mEditText.getText();
if(!curText.equals("")){
mEditText.setText(curText.subString(0, curText.length - 1));
}
to simulate backspace key, just ad code
editText.setText(editText.getText().substring(0,editText.getText().length()-1))
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
to simulate adding a character, put the code
editText.setText(editText.getText() + (char) charCode)
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
Take a look at this article: creating-input-method.html. Basically, you can either manually send KeyEvents or you can manually edit and commit text around the cursor in the application's Input View.These are all done via your IME's InputConnection.
Hope this helps,
if you want a click listener, the best way to do it is this:
View textfield = findViewById(R.id.textfield);
textfield .setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
/*your code for the click event here*/ }});
if you want a backspace button, do this:
public void backSpace() {
EditText textfield = (EditText)findViewById(R.id.textfield);
try {
textfield.getText().delete(textfield.getSelectionEnd() - 1, textfield.getSelectionStart());
} catch (Exception e) {
try {
textfield.getText().delete(textfield.length() - 1, textfield.length());
} catch (Exception myException) {
//textfield.getText().delete(textfield.length(), textfield.length() - 1);
}
}
}
if you want to append a character in the EditText, do this:
EditText textfield = (EditText)findViewById(R.id.textfield);
textfield.setText(textfield.getText().concat("112"));
try implementing TextWatcher interface.
it has 3 methods which you need to override.
public void afterTextChanged(Editable s) {
Log.v("afterTextChanged","here");
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
Log.v("beforeTextChanged","here");
}
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
I think this will work.