Android Studio实现JSON营养数据库列表搜索功能咨询
安卓端本地营养数据搜索最简实现方案

你现有代码已经把接口拉取的全量营养数据存在内存列表里了,不用重构网络层、不用引入额外数据库,直接基于现有SimpleAdapter加筛选逻辑就行,改造成本极低,适合新手快速实现。
前置准备:调整全局变量声明
首先把原来写在onPostExecute里的SimpleAdapter提为全局变量,同时新增一个列表存原始全量数据,避免筛选过程中源数据丢失:
public class NutritionDatabase extends AppCompatActivity { EditText et_dataInput; private String TAG = MainActivity.class.getSimpleName(); private ListView lv; ArrayList<HashMap<String, String>> resultList; // 新增以下两个全局变量 private SimpleAdapter adapter; private ArrayList<HashMap<String, String>> originalDataList; // ... 剩下的原有代码不变
核心修改1:重写Adapter的筛选规则
默认的SimpleAdapter会匹配所有Map字段的内容,你需要的是仅匹配产品名称,所以在初始化Adapter的时候重写Filter逻辑,只对name字段做关键词匹配:
找到你原来onPostExecute方法里初始化Adapter的代码,替换成下面的版本:
@Override protected void onPostExecute(Void result) { super.onPostExecute(result); // 先备份原始全量数据 originalDataList = new ArrayList<>(resultList); // 初始化自定义筛选规则的Adapter adapter = new SimpleAdapter(NutritionDatabase.this, resultList, R.layout.list_item_nutrition, new String[]{ "name","fat","energy","protein","carbohydrates","carbohydrates_sugar","fat_saturated","fibres","sodium"}, new int[]{R.id.name, R.id.fat,R.id.protein,R.id.energy,R.id.carbohydrates,R.id.carbohidrates_sugar,R.id.fat_saturated,R.id.fibres,R.id.sodium}) { @Override public Filter getFilter() { return new Filter() { @Override protected FilterResults performFiltering(CharSequence input) { FilterResults filterResults = new FilterResults(); ArrayList<HashMap<String, String>> tempList = new ArrayList<>(); // 输入为空时直接返回全量数据 if (input == null || input.length() == 0) { filterResults.count = originalDataList.size(); filterResults.values = originalDataList; return filterResults; } // 关键词转小写,实现不区分大小写匹配 String keyword = input.toString().toLowerCase().trim(); for (HashMap<String, String> item : originalDataList) { // 仅匹配产品名称字段 if (item.get("name").toLowerCase().contains(keyword)) { tempList.add(item); } } filterResults.count = tempList.size(); filterResults.values = tempList; return filterResults; } @Override protected void publishResults(CharSequence constraint, FilterResults results) { // 更新列表数据并刷新UI resultList.clear(); resultList.addAll((ArrayList<HashMap<String, String>>) results.values); notifyDataSetChanged(); } }; } }; lv.setAdapter(adapter); }
核心修改2:给搜索框加实时输入监听
在onCreate方法里,你绑定完et_dataInput控件之后,加文字变化监听,用户输入时自动触发搜索:
et_dataInput = findViewById(R.id.et_dataInput); // 新增以下监听代码 et_dataInput.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {} @Override public void onTextChanged(CharSequence s, int start, int before, int count) { // 输入内容变化时直接触发筛选 adapter.getFilter().filter(s); } @Override public void afterTextChanged(Editable s) {} });
注意:需要手动补三个导包,不然会报红:
import android.text.Editable; import android.text.TextWatcher; import android.widget.Filter;
建议顺手修复的布局问题
你现有布局里的硬编码边距、负边距很容易导致不同分辨率下控件重叠,建议调整下约束关系:
- 把搜索框
EditText的android:layout_marginTop="-58dp"删掉,新增约束app:layout_constraintTop_toBottomOf="@id/relativeLayout",同时加16dp左右的上下边距,让搜索框固定在Toolbar下方 - 把
ListView的android:layout_marginTop="123dp"改成app:layout_constraintTop_toBottomOf="@id/et_dataInput",让列表自动跟在搜索框下面,不会出现错位 - 去掉Toolbar写死的
android:layout_width="411dp",改成match_parent适配所有屏幕宽度
内容的提问来源于stack exchange,提问作者Emil Mester
相关产品推荐
相关产品推荐

