Domanda

I am facing problem while filtration of list .I am using onTextChange() method for it .It is working properly but problem is that as i type single character in edit Text the soft keyboard gets disappear and I have to tap edit text again to type complete string .I have also done code so that soft keyboard does not disappear after text change but to type still I have to tap on edit text.Here is my code :

 search.addTextChangedListener(new TextWatcher() {
        @ Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
            // TODO Auto-generated method stub
            String startwith = s.toString();
            ArrayList < Myshares > filterList = new ArrayList < Myshares > ();
            for (int i = 0; i < fileList.size(); i++) {
                if (fileList.get(i).getName().toLowerCase().startsWith(startwith) || fileList.get(i).getName().toUpperCase().startsWith(startwith)) {
                    filterList.add(fileList.get(i));
                }
            }
            adapter = new MListAdapter(PlayListActivity.this, filterList);

            playListView.setAdapter(adapter);
            adapter.notifyDataSetChanged();

        }
        @
        Override
        public void beforeTextChanged(CharSequence s, int start, int count,
            int after) {    
        }
        @
        Override
        public void afterTextChanged(Editable s) {
            search.setSelection(search.getText().length());
            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.showSoftInput(search, InputMethodManager.SHOW_IMPLICIT);
        }
    });

here is my xml code for edit text:

<EditText
         android:ems="10"
        android:id="@+id/search_bar"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        android:layout_weight="2"
        android:background="@drawable/searchbox"
        android:editable="true"
        android:focusable="true"
        android:inputType="textFilter"
        android:hint="Search"
        android:keepScreenOn="true"
        android:paddingLeft="10dp"
        android:textSize="15dp" />

i have also set android:focusable="false " property on list view so that it doesn't overlap soft keyboard. But the problem with edit text is still same .Here are screenshots

enter image description here

As I insert A Single character list gets filter and cursor is gone from edit text box.

enter image description here

È stato utile?

Soluzione

I went through ArrayAdapter's actual source code and it looks like it was actually written to behave that way.

ArrayAdapter has two Lists to begin with: mObjects and mOriginalValues. mObjects is the primary data set that the adapter will work with. Taking the add() function, for example:

public void add(T object) {
    if (mOriginalValues != null) {
    synchronized (mLock) {
        mOriginalValues.add(object);
        if (mNotifyOnChange) notifyDataSetChanged();
    }
 } else {
    mObjects.add(object);
    if (mNotifyOnChange) notifyDataSetChanged();
 }

}

mOriginalValues is initially null so all operations (add, insert, remove, clear) are by default targeted to mObjects. This is all fine until the moment you decide to enable filtering on the list and actually perform one. Filtering for the first time initializes mOriginalValues with whatever mObjects has:

 private class ArrayFilter extends Filter {
     @Override
     protected FilterResults performFiltering(CharSequence prefix) {
    FilterResults results = new FilterResults();
    if (mOriginalValues == null) {
        synchronized (mLock) {
            mOriginalValues = new ArrayList<T>(mObjects);
            //mOriginalValues is no longer null
        }
    }
    if (prefix == null || prefix.length() == 0) {
        synchronized (mLock) {
            ArrayList<T> list = new ArrayList<T>(mOriginalValues);
            results.values = list;
            results.count = list.size();
        }
     } else {
        //filtering work happens here and a new filtered set is stored in newValues
        results.values = newValues;
        results.count = newValues.size();
     }
     return results;
  }
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
    //noinspection unchecked
    mObjects = (List<T>) results.values;
    if (results.count > 0) {
        notifyDataSetChanged();
     } else {
        notifyDataSetInvalidated();
     }
  }
 }

mOriginalValues now has a copy of, well, the original values/items, so the adapter could do its work and display a filtered list thru mObjects without losing the pre-filtered data.

Now forgive me (and please do tell and explain) if my thinking is incorrect but I find this weird because now that mOriginalValues is no longer null, all subsequent calls to any of the adapter operations will only modify mOriginalValues. However since the adapter was set up to look at mObjects as its primary data set, it would appear on screen that nothing is happening. That is until you perform another round of filtering. Removing the filter triggers this:

    if (prefix == null || prefix.length() == 0) {
        synchronized (mLock) {
            ArrayList<T> list = new ArrayList<T>(mOriginalValues);
            results.values = list;
            results.count = list.size();
        }
    }

mOriginalValues, which we've been modifying since our first filter (although we couldn't see it happening on screen) is stored in another list and copied over to mObjects, finally displaying the changes made. Nevertheless it will be like this from this point onwards: all operations will be done on mOriginalValues, and changes will only appear after filtering.

As for the solution, what I've come up with at the moment is either (1) to put a boolean flag which tells the adapter operations if there is an ongoing filtering or not--if filtering is complete, then copy over the contents of mOriginalValues to mObjects, or (2) to simply call the adapter's Filter object and pass an empty string *.getFilter().filter("") to force a filter after every operation [as also suggested by Santhosh].

It would be highly appreciated if anybody can shed some more light on this issue or confirm what I just did. Thank you!

Altri suggerimenti

//ArrayAdapter Definition. Make it activity class field.
ArrayAdapter<String> adapter;

//initialize the adapter by loading complete data and set Adapter to ListView.
//**Note: I have used ArrayList<String> below.**
ArrayList <String> filterList = new ArrayList <Myshares> ();

for (int i = 0; i < fileList.size(); i++) {
            if (fileList.get(i).getName().toLowerCase() || fileList.get(i).getName().toUpperCase()) {
                filterList.add(fileList.get(i));
            }
        }

adapter = new ArrayAdapter<String>(this, R.layout.searchresult_item, R.id.search_item_name,filterList);

//Here, searchresult_item is the layout file name. and search_item_name is the Textview inside it.

search.addTextChangedListener(new TextWatcher() {

@Override
public void onTextChanged(CharSequence cs, int start, int before, int count) {

        YourActivity.this.Youradapter.getFilter().filter(cs);

}

@Override
public void beforeTextChanged(CharSequence s, int start, int count,int after) {


}

@Override
public void afterTextChanged(Editable s) {


}
});

I guess you have added the edit text in list view by addView() Method. It is indeed happening because all the views are redrawn, so the edit text representing whatever row used to be focused is now a completely different object. Set a variable in your adapter: int currentlyFocusedRow;

in getView for your adapter: Add an onFocusChanged listener to edit text and when that edit text gains focus, set currentlyFocusedRow (int variable) = row that focused(contained) edit text happens to be in. Also set any edited text that is in the currentlyFocusedRow to be focused.

Reply me if you see some problems in this.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top