在listview过滤不能正常工作

时间:2013-05-14 12:58:24

标签: java android listview android-edittext textwatcher

我在列表过滤时面临问题。我正在使用onTextChange()方法。它工作正常但问题是,当我在编辑文本中键入单个字符时,软键盘消失,我必须点击编辑文本再次键入完整的字符串。我也完成了代码,以便软键盘在文本更改后不会消失,但键入仍然我必须点击编辑文本。这是我的代码:

 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);
        }
    });

这是我编辑文本的xml代码:

<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" />

我还在列表视图上设置了android:focusable =“false”属性,这样它就不会与软键盘重叠。但编辑文本的问题仍然相同。这是截图

enter image description here

当我插入单个字符列表时,获取过滤器并且光标从编辑文本框中消失。

enter image description here

3 个答案:

答案 0 :(得分:1)

我查看了ArrayAdapter的实际源代码,看起来它实际上是按照这种方式编写的。

ArrayAdapter有两个列表:mObjects和mOriginalValues。 mObjects是适配器将使用的主要数据集。使用add()函数,例如:

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

}

mOriginalValues最初为null,因此所有操作(add,insert,remove,clear)默认都是针对mObjects的。在您决定在列表上启用过滤并实际执行过滤之前,这一切都很好。第一次过滤使用mObjects具有的mOriginalValues初始化:

 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现在拥有原始值/项的副本,因此适配器可以完成其工作并通过mObjects显示已过滤的列表,而不会丢失预过滤的数据。

现在原谅我(并且请告诉和解释)如果我的想法不正确但我觉得这很奇怪,因为现在mOriginalValues不再为null,所有后续调用任何适配器操作都只会修改mOriginalValues。但是,由于适配器设置为将mObjects视为其主要数据集,因此屏幕上将显示没有任何事情发生。直到你执行另一轮过滤。删除过滤器会触发:

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

mOriginalValues,我们自第一个过滤器以来一直在修改(虽然我们看不到它在屏幕上发生)存储在另一个列表中并复制到mObjects,最后显示所做的更改。不过从这一点开始它将是这样的:所有操作都将在mOriginalValues上完成,并且只有在过滤后才会出现更改。

至于解决方案,我现在提出的是(1)放置一个布尔标志,告诉适配器操作是否有正在进行的过滤 - 如果过滤完成,则复制将mOriginalValues的内容转换为mObjects,或者(2)简单地调用适配器的Filter对象并传递一个空字符串* .getFilter()。filter(“”)以在每次操作后强制过滤器[同样由Santhosh建议]。

如果有人能够对这个问题有所了解或确认我刚刚做了什么,我们将不胜感激。谢谢!

答案 1 :(得分:0)

//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) {


}
});

答案 2 :(得分:0)

我猜你已经通过addView()方法在列表视图中添加了编辑文本。确实发生了这种情况,因为所有视图都被重新绘制,因此表示用于聚焦的任何行的编辑文本现在是完全不同的对象。在适配器中设置变量:int currentFocusedRow;

在适配器的getView中

: 添加onFocusChanged侦听器以编辑文本 当编辑文本获得焦点时,设置 currentFocusedRow(int variable)=聚焦(包含)编辑文本的行恰好在。还设置了当前聚焦路径中任何已编辑的文本。

如果您在此看到一些问题,请回复我。