AutoCompleteTextView和ArrayFilter
初入安卓,大神勿喷.
今天心血来潮想在简书上写篇文章,就把最近学的AutoCompleteTextView拿出来讲讲,别看这东西简单,还是有些坑要填.
首先你需要熟悉SharedPreferences,因为这篇文章是用SharedPreferences保存用户输入历史的.
布局方面
AutoCompleteTextView
<pre><code>
<AutoCompleteTextView
android:id="@+id/tv_searchkey"
android:layout_width="0dp"
android:layout_height="30dp"
android:layout_weight="8"
android:textSize="12sp"
android:padding="3dp"
android:background="@drawable/shape"
android:drawableLeft="@drawable/search"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:hint="@string/et_hint">
</AutoCompleteTextView>
</code></pre>
这个布局就是简单的一个提示文本view,在这里我提示一下,如果你想要做的效果是每次输一个字母就会自动进行搜索功能的话,这时候需要进行对键盘弹出或者隐藏的监听.因为只有当键盘弹出再隐藏,我们才能判断说用户已经输入完成.这时候保存用户历史记录到SharedPreferences里面.我这里是对界面的根布局进行一个监听
当父布局的高度减去当前可见view的高度(不包括键盘)小于100时候,认为键盘隐藏了)
mParentLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = mParentLayout.getRootView().getHeight()- mParentLayout.getHeight(); //不显示软键盘
if(heightDiff < 100){
if (!TextUtils.isEmpty(auto_searchkey.getText().toString().trim()) &&
!mOriginalValues.contains(auto_searchkey.getText().toString().trim())) {
Log.e("mOriginalValues", auto_searchkey.getText().toString().trim());
mOriginalValues.add(auto_searchkey.getText().toString().trim());
saveSearchHistory();
autoAdapter.refresh(mOriginalValues);
}
}
}
接下来进入正题
MainActivity中进行读取Sharedprefences,以及删除prefences的记录.
主要部分是在监听键盘隐藏的时候将输入的字符保存在了mOriginalValues,通过刷新自定义的adapter来提示
public static final String SEARCH_HISTORY = "search_history";
private List<String> mOriginalValues;
private AutoAdapter autoAdapter;
/**
* 初始化autoTextView
* @param history
* @param auto
*/
private void initAutoComplete(String history, final AutoCompleteTextView auto) {
initSearchHistory();
autoAdapter = new AutoAdapter(this, mOriginalValues);
auto.setAdapter(autoAdapter);
auto.setDropDownHeight(350);
auto.setBackgroundColor(getResources().getColor(R.color.colorGray));
auto.setThreshold(1);
auto.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
AutoCompleteTextView view = (AutoCompleteTextView) v;
if (hasFocus) {
view.showDropDown();
}
}
});
mParentLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
int heightDiff = mParentLayout.getRootView().getHeight()- mParentLayout.getHeight();
//不显示软键盘
if(heightDiff < 100){
if (!TextUtils.isEmpty(auto_searchkey.getText().toString().trim()) && !mOriginalValues.contains(auto_searchkey.getText().toString().trim())) {
Log.e("mOriginalValues", auto_searchkey.getText().toString().trim());
mOriginalValues.add(auto_searchkey.getText().toString().trim());
saveSearchHistory();
autoAdapter.refresh(mOriginalValues);
}
}
}
});
}
/**
* 读取历史搜索记录
*/
public void initSearchHistory() {
SharedPreferences sp = getSharedPreferences(
MainActivity.SEARCH_HISTORY, 0);
String longhistory = sp.getString(MainActivity.SEARCH_HISTORY, "");
String[] hisArrays = longhistory.split(",");
mOriginalValues = new ArrayList<String>();
if (hisArrays.length == 1) {
return;
}
for (int i = 0; i < hisArrays.length; i++) {
Log.e("initSearchHistory", hisArrays[i]);
mOriginalValues.add(hisArrays[i]);
}
}
/**
* 保存历史记录
*/
private void saveSearchHistory() {
String text = auto_searchkey.getText().toString().trim();
if (text.length() < 1) {
return;
}
SharedPreferences sp = getSharedPreferences(MainActivity.SEARCH_HISTORY, 0);
String longhistory = sp.getString(MainActivity.SEARCH_HISTORY, "");
String[] tmpHistory = longhistory.split(",");
ArrayList<String> history = new ArrayList<String>(
Arrays.asList(tmpHistory));
if (history.size() > 0) {
int i;
for (i = 0; i < history.size(); i++) {
if (text.equals(history.get(i))) {
history.remove(i);
break;
}
}
history.add(0, text);
}
if (history.size() > 0) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < history.size(); i++) {
sb.append(history.get(i) + ",");
Log.e("saveSearchHistory", history.get(i));
}
sp.edit().putString(MainActivity.SEARCH_HISTORY, sb.toString()).commit();
} else {
sp.edit().putString(MainActivity.SEARCH_HISTORY, text + ",").commit();
}
}
/**
* 删除历史记录
* @param value
*/
private void deleteSearchHistory(String value) {
SharedPreferences sp = getSharedPreferences(MainActivity.SEARCH_HISTORY, 0);
String longhistory = sp.getString(MainActivity.SEARCH_HISTORY, "");
String[] tmpHistory = longhistory.split(",");
ArrayList<String> history = new ArrayList<String>(
Arrays.asList(tmpHistory));
sp.edit().clear().commit();
if (history.size() > 0) {
int i;
StringBuilder sb = new StringBuilder();
for (i = 0; i < history.size(); i++) {
if (value.equals(history.get(i))) {
Log.e("deleteSearchHistory", history.get(i));
history.remove(i);
} else {
sb.append(history.get(i) + ",");
}
}
sp.edit().putString(MainActivity.SEARCH_HISTORY, sb.toString()).commit();
}
}
坑点
第一个坑 自定义adapter时候一定要实现Filterable接口,不然会报错
<pre><code>
public class AutoAdapter extends BaseAdapter implements Filterable
</code></pre>
第二个坑
当你在MainActivity刷新数据的时候,必须得更新你的ArrayFilter中的数据,不然过滤器中的原始数据时不会更改的.就比如说我原本有1,2,3,11三个数.第一次我设置适配器的时候,传入这三个数.之后我修改了,在MainActivity中更新了数据变成1,2,3,14,11.这时候照理说调用 notifyDataSetChanged()就可以了,结果就是根本没有用.你输入1,只会提示1和11,并不会提示14这个新增的数据.所以切记要更改mUnfilteredData,过滤的基础数字.
private ArrayFilter mFilter;
private ArrayList<String> mUnfilteredData = new ArrayList<>();
@Override
public Filter getFilter() {
mFilter = new ArrayFilter();
return mFilter;
}
private class ArrayFilter extends Filter {
@Override
protected FilterResults performFiltering(CharSequence prefix) {
FilterResults results = new FilterResults();
//
// if (mLists != null) {
// mUnfilteredData.clear();
// mUnfilteredData.addAll(mLists);
// }
if (prefix == null || prefix.length() == 0) {
ArrayList<String> list = mUnfilteredData;
results.values = list;
results.count = list.size();
} else {
String prefixString = prefix.toString().toLowerCase();
ArrayList<String> unfilteredValues = mUnfilteredData;
int count = unfilteredValues.size();
ArrayList<String> newValues = new ArrayList<String>(count);
for (int i = 0; i < count; i++) {
String pc = unfilteredValues.get(i);
if (pc != null) {
if(pc!=null && pc.startsWith(prefixString)){
newValues.add(pc);
}
}
}
results.values = newValues;
results.count = newValues.size();
}
return results;
}
@Override
protected void publishResults(CharSequence constraint,
FilterResults results) {
//noinspection unchecked
mLists = (List<String>) results.values;
if (results.count > 0) {
notifyDataSetChanged();
} else {
notifyDataSetInvalidated();
}
}
}
这是我刷新的方法
/**
* 刷新数据
* @param reLists
*/
public void refresh(List<String> reLists) {
if (mLists != null) {
mLists.clear();
}
if (mUnfilteredData != null) {
mUnfilteredData.clear();
}
mLists.addAll(reLists);
mUnfilteredData.addAll(reLists);
}
到此结束,这篇文章只能参考下,因为是项目中一个小地方,不方便把项目搞上来,因为还没完成.不懂的地方欢迎询问.