I have a couple of queries regarding the EditText function in Android.
First of all, is it possible to set a minimum number of characters in the EditText field? I'm aware that there is an
android:maxLength="*"
however for some reason you can't have
android:minLength="*"
Also, I was wondering if it is possible to launch a new activity after pressing the enter key on the keyboard that pops us when inputing data into the EditText field? And if so, could someone show me how?
Thanks for any help you could offer regarding either question :)
To respond to an enter key in your edit field and notify the user if they haven't entered enough text:
EditText myEdit = (EditText) findViewById(R.id.myedittext);
myEdit.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
if (myEdit.getText().length() < minLength) {
Toast.makeText(CurrentActivity.this, "Not enough characters", Toast.LENGTH_SHORT);
} else {
startActivity(new Intent(CurrentActivity.this, ActivityToLaunch.class);
}
return true;
}
return false;
}
});
There's no simple way to force a minimum length as the field is edited. You'd check the length on every character entered and then throw out keystrokes when the user attempt to delete past the minimum. It's pretty messy which is why there's no built-in way to do it.
Related
I'm making a shopping cart app that dynamically generates rows as items get added. For each item row, an EditText field is used for the item quantity so that quantities can be modified. Since the quantities need to be integers for calculations, I'm using a parseInt to convert the text grabbed from an altered EditText and trapping out any NFEs in case the input was bad.
When the input is good, everything works fine. When the input is bad, the EditText is set back to its prior value (as desired) but if there is another (dynamically-generated) row below it, the focus shifts to the EditText in that lower row. The desired behavior is for the focus to remain in the EditText that the user wants to change.
Regarding what happens to focus on a successful change -- the virtual keyboard closes on success and nothing keeps focus. In that try/catch block I try to hide the keyboard, but that doesn't help ... it stays open on shifting to the lower field.
Here's an image if it helps to visualize:
before and after hitting ENTER
I've read other posts about using requestFocus() and I've used it here but it doesn't seem to have any effect -- maybe due to all this being generated on the fly? I've also seen posts saying that dynamically generated views don't have any IDs you can grab for being a bit more specific in identifying what should get the focus, but perhaps I'm not understanding it in this context.
So, how do I keep the focus in the field the user wants to edit after handling the NFE and resetting the value of that field?
Here's the specific code that catches that NFE:
try {
quantity = Integer.parseInt(quantityCell.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Please enter a valid number",
Toast.LENGTH_LONG).show();
imm.hideSoftInputFromWindow(quantityView.getWindowToken(), 0);
quantityCell.setText("" + savedQuantity);
quantityCell.requestFocus();
return false;
}
... and here is all the code that goes into generating that EditText field on the fly:
// create quantity edittext and add to row
final EditText quantityView = new EditText(this);
quantityView.setLayoutParams(cellParams);
quantityView.setSingleLine();
quantityView.setPadding(5, 5, 5, 5);
quantityView.setText("" + theQuantity);
quantityView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// capture old value of quantity before changing it
EditText et = (EditText)v;
savedQuantity = Integer.parseInt(et.getText().toString());
return false;
}
});
quantityView.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN)
if (keyCode == KeyEvent.KEYCODE_ENTER) {
int quantity;
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
TableRow theRow = (TableRow) v.getParent();
TextView nameCell = (TextView) theRow.getChildAt(0);
String name = nameCell.getText().toString();
EditText quantityCell = (EditText) theRow.getChildAt(1);
try {
quantity = Integer.parseInt(quantityCell.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Please enter a valid number",
Toast.LENGTH_LONG).show();
imm.hideSoftInputFromWindow(quantityView.getWindowToken(), 0);
quantityCell.setText("" + savedQuantity);
quantityCell.requestFocus();
return false;
}
TextView unitCell = (TextView) theRow.getChildAt(2);
double unit = Double.parseDouble(unitCell.getText().toString().substring(1));
TextView totalCell = (TextView) theRow.getChildAt(3);
double total = Double.parseDouble(totalCell.getText().toString().substring(1));
totalPrice -= total;
totalQuantity -= quantity;
cartDB.changeQuantity(name, quantity, unit);
removeAllRows();
writeOrderTable();
imm.hideSoftInputFromWindow(quantityView.getWindowToken(), 0);
return true;
}
return false;
}
});
// set length of edittext line
productRow.addView(quantityView);
EDIT:
Looking at the code in that catch clause, I'm guessing that the line to hide the virtual keyboard wouldn't do much if the desired field retained any focus in the first place, so maybe I should remove it. The reason it's there is that I tried doing that (hiding the virtual keyboard) to just remove any focus at all and that approach did not work. The field below still grabbed focus and the keyboard remained open.
ANOTHER EDIT:
This does not happen with a physical keyboard -- at least when using by computer keyboard with a Genymotion virtual device (can't use a built-in AVD, I have an AMD cpu). When the same simulator is set to use a virtual keyboard, the problem appears.
FINAL EDIT:
I altered the try/catch block to this and it works as desired. Changes are in the catch clause:
try {
quantity = Integer.parseInt(quantityCell.getText().toString());
} catch (NumberFormatException nfe) {
Toast.makeText(getApplicationContext(), "Please enter a valid number",
Toast.LENGTH_LONG).show();
quantity = savedQuantity;
}
Some code later in the larger block above winds up handling resetting the field when the user inputs bad data. I'm guessing the cause of what was happening was me trying to restore the old value with that setText() method in the old code.
I saw a possible answer here: http://imax-live.blogspot.hk/2012/12/prevent-enter-key-on-edittext-as-multi.html
The idea is to override the keyborad input so that the user cannot use the normal function of the "enter" key
Btw, you can set android:inputType="number" in xml so that only numbers can be entered into the edit text field
class MyTextView extends EditText
{
...
#Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode==KeyEvent.KEYCODE_ENTER)
{
// Just ignore the [Enter] key
return true;
}
// Handle all other keys in the default way
return super.onKeyDown(keyCode, event);
}
}
A client is testing an Android app I made for them and they are using a tablet. They say that they can't enter numbers in an EditText, but it seems to work on my phone. What could be a reason or this?
Here is the code for a particular EditText:
pWord = (EditText)findViewById(R.id.passwordsignin);
y = false;
signIn = (Button) findViewById(R.id.signin);
pWord.setOnKeyListener(new OnKeyListener(){
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER){
y = true;
new RegisterDeviceAsynctask().execute();
}
return true;
}
});
and the XML:
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="textPassword"
android:ems="10"
android:id="#+id/passwordsignin"
android:layout_below="#+id/emailsignin"
android:layout_centerHorizontal="true"
android:hint="Password"
android:layout_marginTop="10dip"/>
Edit: The issue ended when I ended the setOnKeyListener code. Any idea why this could be?
tell your client to use two types of text, for example: android:inputType= "typeOne|typeTwo" ... change typeOne and Two and use Log to print real output.
Some suggestions:
1. Your android:inputType="textPassword" will not let anyone see what is being entered. Try changing the android:inputType="text" so you can see if the expected character is being entered. That will let you debug the issue. It is possible the user is mistyping.
2. Try logging the password or putting it into a Toast so the user can see what they typed.
The above suggestions are for the debug period only. For release you don't want to have those in place. Your users should probably change their password after the debug period (or before, to a temporary password, and then change it back to the real password).
Try this
android:inputType="TYPE_TEXT_VARIATION_PASSWORD|TYPE_NUMBER_VARIATION_PASSWORD"
This will ensure that an appropriate keyboard/input method is selected for it (this can be dependent on the actual hardware manufacturer).
If that doesn't work, ask that they separate the physical keyboard from the tablet, to make the software keyboard come up.
If that doesn't work, see if they don't have a third party custom keyboard installed. Not only we have different hardware manufacturers, but since people can install their own keyboards from Google Play, that's another possibility.
If that doesn't work, ask them to take a screenshot of the keyboard they're getting on it, anonymize the screenshot the best way you can, and then post it on here in your question.
Just change youe code a bit:
pWord = (EditText)findViewById(R.id.passwordsignin);
y = false;
signIn = (Button) findViewById(R.id.signin);
pWord.setOnKeyListener(new OnKeyListener(){
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(event.getAction() == KeyEvent.ACTION_DOWN && keyCode == KeyEvent.KEYCODE_ENTER){
y = true;
new RegisterDeviceAsynctask().execute();
return true;
}
return false;
}
});
just use this code as your SetOnKeyListener
if (keycode==keyevent.keyback)
{
...
}
else
{
return false;
}
I have a set of EditTexts in my app that the user needs to fill in. Pressing "Next" on the soft keyboard advances the focus to the next EditText and at the last one I capture the soft key Enter action to validate and submit the entered data. In case there is a validation error (e.g. an unfilled field) the relevant field (i.e. the unfilled field) requests focus whilst also showing a toast to display the error.
It works fine (focuses on the correct item) if I use a Send button which calls the same validation function, but if I hit the Enter button on the soft keyboard, the focus jumps to the EditText that caused the validation error and immediately moves to the one immediately after it.
This is the snippet that sets the listener on the last EditText.
lastEditText.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event) {
if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
if(validateFields()){ //Validation function
sendPressed(); //Submit function
}
return true;
}
return false;
}
});
Any help would be appreciated..
I am having some very strange problems with the EditText control in Mono for Android. My solution is targeting 2.3 and I am debugging on a T Mobile VivaCity. Here is my AXML for the EditText
<EditText
android:inputType="text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/ctl_searchText" />
When I show the View containing the EditText the keyboard automatically appears, this is not a problem. The problem is I can't enter any numbers by tapping the numbers on the keyboard, the only way I can get a number to show in the text field is if I hold the key down and chose the number from a context menu. Although once I've entered a number in using this method I'm then not able to delete it. I've tried all sorts of input methods and had a look for similar issues in SO to no avail. Does this sound like an issue with the device? Or is there something glaringly obvious I'm not doing in the code/AXML?
== EDIT ==
I think I've narrowed the problem down, it has something to do with the KeyPress event handler used on the EditText. As the EditText represents a search field I have added the attribute android:singleLine="true" to stop the return key from adding an extra line and instead say "Done". When I add a KeyPress event handler to the control this is when it stops me from entering numbers, but without the handler it begins to function normally again. Here is what I have:
<EditText
android:id="#+id/ctl_searchText"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="true" />
EditText ctl_searchText = FindViewById<EditText>(Resource.Id.ctl_searchText);
ctl_searchText.KeyPress += (object sender, View.KeyEventArgs e) =>
{
if (e.Event.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter)
{
Toast.MakeText (this, ctl_searchText.Text, ToastLength.Short).Show ();
e.Handled = true;
}
};
With this code I cannot enter numbers into the text field, but I can enter letters. When I remove the event handler it works again, allowing me to enter all characters. I'm going to carry on investigating, this is very strange.
Please cheack that you doesn't use OnKeyListener. If yes just check that onKey (View v, int keyCode, KeyEvent event) method return True if the listener has consumed the event, false otherwise. In your case it something like this:
ctl_searchText.setOnKeyListener(new OnKeyListener() {
public boolean onKey(View v, int keyCode, KeyEvent event){
if (keyCode == KeyEvent.KEYCODE_ENTER){
//do smth
return true;
}
return fasle;
}
});
Try adding an else stating that e.Handled = false;
Your code will then look like:
ctl_searchText.KeyPress += (object sender, View.KeyEventArgs e) =>
{
if (e.Event.Action == KeyEventActions.Down && e.KeyCode == Keycode.Enter)
{
Toast.MakeText (this, ctl_searchText.Text, ToastLength.Short).Show ();
e.Handled = true;
}
else
{
e.Handled = false;
}
};
To All.
Right now i am working on App which launches a dialog(containing EditText) on any alphanumeric key pressed from keyboard. Now i want that whatever user type should appear in EditText box, which is working properly the only issue that i have is, i want the char key which was 1st pressed to open dialog in EditText Box. I am missing the 1st char key which is obviously right. But I retrieve that char as string separately.
Now wanted to attach(show) that char key to inputted EditText from user as 1st letter.
I tried this,
{
final EditText search_d_text = (EditText) dialog
.findViewById(R.id.search_text1);
search_d_text.setText(s1);// si is the 1st char key launch dialog(containing edittext).
search_d_text.setInputType(InputType.TYPE_NULL);
search_d_text
.setOnEditorActionListener(new OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId,
KeyEvent event) {
if (event != null
&& event.getAction() == KeyEvent.ACTION_DOWN) {
// Handle enter key
return true;
}
if (actionId == EditorInfo.IME_ACTION_NEXT) {
// Handle IME NEXT key
return true;
}
if (actionId == EditorInfo.IME_ACTION_DONE) {
// Handle IME DONE key
return true;
}
return false;
}
});
search_string = search_d_text.getText().toString();
enterd_text = search_d_text.getText();
// collecting input text.
}
What i am getting is eg. when i type MASK, It shows ASKM.
The setText(s1) is always act as last letter.
I want to show the word or whatever user input starting from 1st key.
Thank You.
Found solution ,
Just moved edit text cursor position. By
search_d_text.setSelection(s1.length()); i.e to next position.