Gilbou
Gilbou

Reputation: 5254

Edittext keeps focus when keyboard up AND scrolling the listview

I use a listview. Each item in the list contains one edittext. When I click on an edittext, the soft keyboard pops up, the edittext I clicked on gains the focus for a short time and then lose it. I have to click a second time to really get the focus (why?)

(focus on an editext and keyboard up) I scroll the listview...

Because the listview elements are recycled, the focus reappears on edittext at other positions in the list and I guess this is normal BUT why does Android not remove this damned focus!? How could I say to Android ok I do not want the focus anymore on an edittext if my user begins to scroll ?

Here is the code of the activity:

public class SimpleList extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.user_picker);

    ListView listview = (ListView)this.findViewById(R.id.user_picker_list);
    new UserPickerAdapter(this, listview); 

}

And the code of the adapter:

public class UserPickerAdapter extends BaseAdapter {

private final LayoutInflater mInflater;

private String[] mUsers = {"Guib", "Jonas", "Fred", "Denis", "Arnold", "Francois", "David", "Alex", "Saskia", "Verner", "Anatole"};

public UserPickerAdapter(Context context, ListView listview) {

    mInflater = LayoutInflater.from(context);   
    listview.setAdapter(this);  

}

@Override
public int getCount() {
    return mUsers.length;
}

@Override
public Object getItem(int position) {
    return mUsers[position];
}

@Override
public long getItemId(int position) {
    return position;
}

static private class Holder {
    TextView username; 
}

@Override
public View getView(int position, View convertView, ViewGroup arg2) {

    Holder holder;  

    if (convertView != null) {  

        holder = (Holder) convertView.getTag(); 

    } else {    

        holder = new Holder();  
        convertView = mInflater.inflate(R.layout.user_picker_list_item,null);
        holder.username = (TextView) convertView.findViewById(R.id.user_picker_list_item_name);
        convertView.setTag(holder);

    }

    String str = (String)getItem(position);
    holder.username.setText(str);
    return convertView;

}

Just in case, here is the code in 'user_picker.xml'

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_height="fill_parent" android:layout_width="fill_parent" android:orientation="vertical" android:padding="0dp"><ListView android:background="@color/color_grey1" android:cacheColorHint="@color/color_grey1" android:id="@+id/user_picker_list" android:divider="@color/color_blueGrey1" android:layout_height="match_parent" android:layout_width="match_parent"/>

And the one in 'user_picker_list_item.xml'

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:orientation="vertical" android:layout_height="fill_parent"><EditText android:layout_height="wrap_content"android:id="@+id/user_picker_list_item_name" android:layout_width="wrap_content" android:minWidth="200dp" android:layout_gravity="center"></EditText></LinearLayout> 

Upvotes: 4

Views: 7890

Answers (4)

Ruzin
Ruzin

Reputation: 1674

Maybe I'm late but I hope this will help someone. Sangeeth Kumar's answer is on the right track but it needs another line of code added to the manifest.

The problem here is when a soft keyboard pops out the contents on the screen are forced to scroll and resize. When a ListView (or an ExpandableListView) is scrolled all the views are getting rendered again, so the EditText field object in the item row that used to be focused is now a completely different object.

So to solve this problem you need to add two lines of code:

  1. Add the following line to the ListView item XML:

    android:descendantFocusability="beforeDescendants"

  2. Add the following line to the activity tag containing your ListView (or ExpandableListView) in the application's manifest

    android:windowSoftInputMode="adjustPan"

Hope this helps :)

Upvotes: 1

Sangeeth Kumar
Sangeeth Kumar

Reputation: 21

You Need to Add

In XML

android:descendantFocusability="afterDescendants"

In Java

listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);

i think it works .

Upvotes: 0

Hansenclever Bassani
Hansenclever Bassani

Reputation: 11

I tried Gilbou solution but it didn't work for me because I had EditTexts in all rows. But with some changes I could make it work:

EditText currentEdit;

public View getView(int q, View convertView, ViewGroup parent) {

    ViewHolder holder;

    if (convertView==null) {

        convertView = (LinearLayout)inflater.inflate(R.layout.grade_row, null);

        holder = new ViewHolder();
        //Inflate holder
        convertView.setTag(holder);     
    } else {
        holder = (ViewHolder)convertView.getTag();
    }

    if (listView.getSelectedItemPosition() == ListView.INVALID_POSITION) {
        if (currentEdit!=null)
            currentEdit.requestFocus();
    }

    //update row items

    return convertView;
}

Also, add a focus change listener for every EditText inside the listview:

myEditText.setOnFocusChangeListener(new OnFocusChangeListener() {  

    public void onFocusChange(View v, boolean hasFocus) {
        if(!hasFocus) 
            currentEdit = myEditText;
    }
}

Upvotes: 1

Gilbou
Gilbou

Reputation: 5254

I think found the solution...

I replaced a part of the code in the getView() method of my adapter by the following:

if (convertView != null) {
   holder = (Holder) convertView.getTag();
   if (((ListView)arg2).getSelectedItemPosition() == ListView.INVALID_POSITION) {
      arg2.requestFocus();
   }
}

Upvotes: 0

Related Questions