EditText in ListView hidden by keyboard when focused - android

I have a ListView containing rows with EditText's.
When I click on an EditText and it's not already focused it receives focus, the keyboard appears and the EditText is moved above the CandidateView (desired behaviour).
However when I make a key press, the EditText maintains focus and receives the input but moves down and is obscured by the keyboard (the previous movement is reversed).
When I click on the EditText when it is already selected without the keyboard shown, the keyboard pops up but the EditText is not moved to the right position (above the CandidateView). It still receives the input.
I add a header view containing EditText's and there everything works correctly.
This is the code of my ArrayAdapter where the row view is created:
View view = inflater.inflate(R.layout.row_profile_entry_text, null);
final String question = getItem(position);
TextView textViewQuestion = (TextView) view.findViewById(R.id.rpeq_TextViewQuestion);
textViewQuestion.setText(question);
final EditText editTextAnswer = (EditText) view.findViewById(R.id.rpeq_EditTextAnswer);
editTextAnswer.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
mAnswers.put(question, s.toString());
}
});
if (mAnswers.containsKey(question)) {
editTextAnswer.setText(mAnswers.get(question));
}
return view;
I would also like to emphasize that I already added
android:windowSoftInputMode="adjustPan" to the Manifest and android:descendantFocusability="beforeDescendants" to the ListView as most of the answers to other questions suggest.
Without adjustPan the EditText is not able to receive focus at all but it does not solve the issue entirely.
Does someone have an idea what I am doing wrong?

Try this:
<activity name="YourActivity"
android:windowSoftInputMode="stateVisible|adjustResize|adjustPan">
</activity>
in the manifest file.
Most probably, adjustResize must work, if you are using a ScrollView.

after many hours spent on this problem this is my solution (for Android < 4.2):
1) Manifest => android:windowSoftInputMode="adjustPan"
2) Activity=> create OnTouchListner and pass to Adapter
private OnTouchListener exampleOnTouchListener = new OnTouchListener() {
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_UP == event.getAction()) {
int position = (Integer) v.getTag();
myListView.setSelection(position);
}
return false;
}
};
3) Adapter
if (exampleOnTouchListener!= null) {
myEditText.setTag(position);
myEditText.setOnTouchListener(exampleOnTouchListener);
// if last element set padding bottom for spacing
if (position == items.size() - 1) {
LinearLayout myLinearLayout = (LinearLayout) convertView
.findViewById(R.id.ticketcontolProposedRealvalueLinearLayout);
myLinearLayout.setPadding(0, 0, 0,SET_PADDING_BOTTOM);
}
}

Related

Edit text loosing focus after typing something

I am inflating edit text in adapter class within of a list view. View is looking cool multiple edit text are appearing properly but when I do focus on the edit text or if I try to type something it loosing focus I tried to adding listeners, changing manifest file but nothing works for me.
following code is not working for me
#Override
public View getChildView(int position, int i1, boolean b, View view,
ViewGroup viewGroup) {
EditText comment = view.findViewById(R.id.txtRecordComment);
comment.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (lastFocussedPosition == -1 || lastFocussedPosition == position) {
lastFocussedPosition = position;
edittext.requestFocus();
}
}
}, 200);
} else {
lastFocussedPosition = -1;
}
}
});
return view;
}
please help me to resolve this issue
Since you are using a ListView, it is bound to happen with your current code implementation.
You must remember that if your EditText is in a ListView, every key down will result in the edit text losing and getting focus because all the views are redrawn, so the edit text representing whatever row used to be focused is now a completely different object.
To get the expected behaviour, declare a variable in your adapter: int focusedRow. In getView method of your adapter, add an onFocusChanged listener to the EditText and when that edit text gains focus, set focusedRow = whatever row the focused EditText happens to be in.
Also set any edit text that is in the currentlyFocusedRow to be focused.
Update:
If you have multiple EditTexts, add an onFocusChanged listener to each edit text.
Add below code in Android Manifest file
<activity android:name=".ActivityName"
android:label="#string/app_name"
android:windowSoftInputMode="adjustPan">
Hope this will work

Android InputType not honored

I have a listview with an EditText in each row. The EditText is supposed to collect numeric values so I tried to keep the alpha keyboard off and allow the user to only see the numeric keypad.
What happens, though, is that when the listview is populated and I click on any EditText in the list, the numeric keyboard appears - but is then quickly replaced by the full qwerty keyboard - and the user must switch back to numeric to input numbers.
I've tried various combinations programmatically, like so:
mPercent.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL);
As well as multiple comnbinations of XML such as
android:inputType="phone"
or
android:digits="0123456789"
But, no matter the combination, they keyboard always rapidly switches back to qwerty and off the numeric keys.
I'm thinking it might be something with the TextWatcher. I use a textwatcher to indicate what has been typed. I remove it, add whatever text might be in that row's edittext and then add the textwatcher.
This is the guts of my custom adapter :
public View getView(final int position, View inView, ViewGroup parent) {
ViewHolder holder = null;
if (inView == null) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inView = inflater.inflate(mLayoutResource, null);
holder = new ViewHolder();
holder.mPercent = (EditText) inView.findViewById(R.id.percent);
holder.mMaterial = (TextView) inView.findViewById(R.id.name);
inView.setTag(holder);
} else {
holder = (ViewHolder) inView.getTag();
}
mMaterial.moveToPosition(position);
holder.mPercent.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_VARIATION_NORMAL);
// remove textwatcher on percentage
holder.mPercent.removeTextChangedListener(percentWatcher);
// insert the percentage for this row
final String material = mMaterial.getString(mMaterial.getColumnIndex(OptionsProvider.OPTIONS_DATA));
final EditText percent = holder.mPercent;
percent.setTag(material); // use material and position as keys into which of the many edittexts the textwatcher is watching
percent.setId(position);
holder.mMaterial.setText(material);
// persist any text the user may have typed in the comment box
if (percentages.containsKey(material)) {
percent.setText(percentages.get(material));
}
else {
percent.setText("");
}
// turn on textwatcher
percentWatcher = new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
// save this text and the position in which is resides.
// if the user scrolls before pressing send, only this position should
// contain the text
String text = percent.getText().toString().trim();
if (text.length() > 0) {
if ((position == percent.getId() &&
(material.equals( percent.getTag().toString())))) {
percentages.put(material, text);
Log.d(TAG, "Percentage inserted "+material+"="+text);
}
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
// force the EditText to stay with 3 digits (max of 100%)
#Override
public void afterTextChanged(Editable s) {
if (s.length() > 0) {
int pct = Integer.parseInt(s.toString());
Log.d(TAG, " Material "+(String) percent.getTag()+ " = "+pct);
}
}
};
// add the textwatcher back to the edittext
holder.mPercent.addTextChangedListener(percentWatcher);
Anyone know if removing/adding a textwatcher corrupts the InputType? Is this a path I should explore to figure out why the keyboard always goes back to qwerty?
Might be that the ListView steals the focus. Try to add this your ListView
XML
android:descendantFocusability="afterDescendants"
Or in Java
listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

Text watcher in edit text is making the edittext slow

In my tablet app I have used fragments and one fragment has multiple Edittexts, and I have a linear layout which will add a sublayout as many times the user wishes to add, in that fragment
This sublayout has two edittext, both this edittext is having
addtextchangelistener(Textwatcher) and
onfocuschangelistner
every time the text is changed 3 conditions are checked in both the edittext
every time the focus is changed 2 conditions are checked in both the edittext
After doing all this condition check, the problem I'm facing is, the edittext typing is too slow, its like i type an email and the whole email gets completely typed after 5 secs or more,
This is the code for 1 edit text in the sublayout:
receiverName.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View paramView, boolean hasFocus) {
receivernameFocus = hasFocus;
if(hasFocus)
{
if(receiverName.getText().toString().length()>0)
ReceiverName_btn_cancel.setVisibility(View.VISIBLE);
else
ReceiverName_btn_cancel.setVisibility(View.INVISIBLE);
}
else
ReceiverName_btn_cancel.setVisibility(View.INVISIBLE);
}
});
receiverName.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence paramCharSequence, int paramInt1,int paramInt2, int paramInt3) {
if(receivernameFocus)
{
if(receiverName.getText().toString().length()>0)
{
receiverNamePresent = true;
ReceiverName_btn_cancel.setVisibility(View.VISIBLE);
}
else
{
receiverNamePresent = false;
ReceiverName_btn_cancel.setVisibility(View.INVISIBLE);
}
}
else
ReceiverName_btn_cancel.setVisibility(View.INVISIBLE);
if(receiverEmailPresent && receiverNamePresent)
addReceiver.setBackgroundResource(R.drawable.plus_receiver);
else
addReceiver.setBackgroundResource(R.drawable.plus_deselect_receiver);
}
#Override
public void beforeTextChanged(CharSequence paramCharSequence,
int paramInt1, int paramInt2, int paramInt3) {
}
#Override
public void afterTextChanged(Editable paramEditable) {
}
});
same conditions are present for the other edittext, and everytime the user inflate another view, same set of edittext will be created for the new view too.
I can't remove the conditions, all of them are necessary, and you can see its just some button visibility or setting background resource
How to optimize this code, or how to speed up the edittext typing speed for android tablet?
EDIT: If I'm typing 10 letters persecond its showing only 1 letter per second in the edittext(so all the 10 letters will be visible in the edittext after 10 seconds), which I believe is happening because of multiple condition checking within onTextChanged method, the delay in showing the text is too much for user experience.
How to make the edittext show the text as fast as I'm typing it
Thanks
Here public void onTextChanged(CharSequence paramCharSequence, int paramInt1,int paramInt2, int paramInt3) it's generally in this format:
public void onTextChanged(CharSequence s, int start, int before, int count)
So here you will need to do some operation using paramInt3 . If you would like to show suggest text will come after you enter 3 letter then perform an operation here in this manner:
public void onTextChanged(CharSequence s, int start, int before, int count)
{
if (count%3 == 1)
{
adapter.clear();
GetPlaces task = new GetPlaces();
task.execute(dep_place.getText().toString());
}
}
here I haved updated text from server side in background. You just need to modify this portion from where your text will come use this code here.
Thanks.

Adding EditText fields on view when typing on a EditText

I want to create EditTextFields dynamically on depending the condition. Condition is that if I start typing on first EditTextField it will create one more EditTextField in the bottom and will create the third EditTextField when i start typing on second one. Similarly i want to delete the bottom text if there is no text in the upper EditTextField. Thanks.
Use a parent view, like a ScrollView that you know you can add a flexible about of content to. Then use a TextWatcher a/k/a a text change listener. You could then create a new text view which you would add to the ScrollView if text was typed into the EditText field.
For neatness I'd probably create a custom TextView class that housed this text change listener and replication check. Here's example of how you could add a TextView
//instance variable
private LinearLayout containerLayout;
private newTextViewCreated = false;
//initialize your conatinerLayout before you use it
//and create your first edit text field
public void onCreate(Bundle savedInstaceState){
containerLayout = (LinearLayout)findViewById(R.id.conatinerLinearLayout);
createEditText();
}
private void createEditText(){
EditText editText = new editText(this);
editText.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
if(count > 0 && !newTextViewCreated){
createEditText();
newTextViewCreated = true;
}
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
// TODO Auto-generated method stub
}
#Override
public void afterTextChanged(Editable s) {
//TODO Auto-generated method stub
}
});
containerLayout.addView(editText);
}
I didn't test this out, I'm writing it now but here's what I'm thinking. Read the description of how a TextWatcher works so you understand the inner methods. You're going to have to play with the conditionals but what you're doing is listening for a change in the number of characters entered and then making a recursive call to create an additional view when chars are added to each text view. I use a boolean flag to show when a view has been created so we don't add one each time the char is changed. I moved outside the createEditText method based on your comment. If you made your own EditText class you could just add a method that would set/get the status of whether this TextView had spanwed another. To remove you would just add a delete condition that would remove the view from the linear layout.
User TextWatcher
Implement your Activity with TextWatcher and override method
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {}
Show / Hide them in your layout if you know the total amount of editText fields needed or add them programatically like so:
EditText myET = new EditText(MyActivity.this);
myET.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
LayoutContentView.addView(myET);
Then check:
if (myET.getText().toString().trim().equals(""))
{
//Don't Show
}else{
//SHOW
}
SO question could help:https://stackoverflow.com/a/6792359/350421
EditText toAdd = new EditText(this);
list.add(toAdd);

How do you gray out a "Submit" button when specific EditText boxes are empty?

Regarding an Android app I am creating:
I have three EditText boxes that need to be filled with numbers/strings. I have a submit button that will start a series of calculations.
IF any box is empty and submit is pressed, the app crashes. I have tried to do this with try-catch statement, but it is not working out. I simply want to disable the button until three boxes have numbers. I know there is a way to setEnabled(false) I think? Or is there a better way? Will this grey out the button? Or is that an unrelated function to setEnabled?
Try this solution.
EditText edit1;
EditText edit2;
EditText edit3;
View button;
#Override
protected void onCreate(Bundle savedInstanceState) {
// Your initialization code...
TextWatcher watcher = new LocalTextWatcher();
edit1.addTextChangedListener(watcher);
edit2.addTextChangedListener(watcher);
edit3.addTextChangedListener(watcher);
updateButtonState();
}
void updateButtonState() {
boolean enabled = checkEditText(edit1)
&& checkEditText(edit2)
&& checkEditText(edit3);
button.setEnabled(enabled);
}
private boolean checkEditText(EditText edit) {
return Integer.getInteger(edit.getText().toString()) != null;
}
private class LocalTextWatcher implements TextWatcher {
public void afterTextChanged(Editable s) {
updateButtonState();
}
void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
void onTextChanged(CharSequence s, int start, int before, int count) {
}
}
You should disable the button by default in the XML so that the user cannot hit the button by accident. After this you need to look at your fields and insure all of them have data before the submission.
You could do this, or you could just have submit run a quick check on all the fields and insure none of them are equal to "".
Basically look like this (If you want to ignore hiding the button and just handle processing after the check)
if (!((t1.getText().toString.compareTo("") == 0) && (t2.getText().toString.compareTo("")==0) ...))
{
Do stuff
}
else
{
Toast message here
}
Otherwise you can just have a "watcher" like the above poster mentioned.
You can also use this check
boolean checkEditText(EditText editText) {
return editText.getText().toString().trim().equals("");
}
Hi i have tried above code and changed the function to given below for it to work.
private boolean checkEditText(EditText edit) {
return ((edit.getText().toString()).length() >0 );
}

Categories

Resources