英文:
Implementing search functionality on ListView
问题
我正在使用 Parse 服务器作为我的数据库。我希望在用户使用搜索功能时获取项目。我在谷歌上搜索了这个问题,但没有找到合适的内容。
MainActivity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
final ParseQuery<ParseUser> query = ParseUser.getQuery();
// 获取搜索视图并设置可搜索的配置
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
// 假定当前活动是可搜索的活动
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(true);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
return true;
}
@Override
public boolean onSearchRequested() {
return super.onSearchRequested();
}
RoomCardRecyclerViewAdapter
我希望通过搜索功能从此适配器中获取项目并为用户进行过滤。
private List<ParseObject> mRooms = new ArrayList<>();
private ParseObject room;
private String mSection;
public RoomCardRecyclerViewAdapter() {
super(DIFF_CALLBACK);
}
public static final DiffUtil.ItemCallback<ParseObject> DIFF_CALLBACK =
new DiffUtil.ItemCallback<ParseObject>() {
@Override
public boolean areItemsTheSame(@NonNull ParseObject oldItem, @NonNull ParseObject newItem) {
return oldItem.getObjectId().equals(newItem.getObjectId());
}
@Override
public boolean areContentsTheSame(@NonNull ParseObject oldItem, @NonNull ParseObject newItem) {
return oldItem.getUpdatedAt().equals(newItem.getUpdatedAt()) &&
oldItem.getCreatedAt().equals(newItem.getCreatedAt());
}
};
public RoomCardRecyclerViewAdapter(String section) {
this();
this.mSection = section;
}
public class RoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
protected ImageView mRoomImage;
protected TextView mRoomPrice;
protected TextView mInclusiveOrNot;
protected TextView mPropertyType;
protected TextView mNumOfBeds;
protected TextView mNumOfBaths;
protected TextView mRoomLocation;
// ... (其他代码)
@Override
public void onBindViewHolder(@NonNull RoomViewHolder holder, int position) {
room = getItem(position);
holder.mRoomLocation.setText(room.getString("roomSuburb"));
holder.mRoomPrice.setText(Integer.toString(room.getInt("roomMonthlyRent")));
holder.mInclusiveOrNot.setText(room.getString("roomRentInclusiveOfBills"));
holder.mPropertyType.setText(room.getString("roomPropertyType"));
holder.mNumOfBeds.setText(Integer.toString(room.getInt("roomBedrooms")));
holder.mNumOfBaths.setText(Integer.toString(room.getInt("roomBathrooms")));
// 获取图片(略)
// ...
}
// ...
}
public void addMoreRooms(List<ParseObject> newRooms) {
mRooms.addAll(newRooms);
submitList((PagedList<ParseObject>) mRooms);
}
public void addAll(List<ParseObject> latestRooms) {
mRooms.addAll(0, latestRooms);
notifyDataSetChanged();
}
@Override
public Filter getFilter() {
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults results = new FilterResults();
List<ParseObject> filteredList = null;
if (charSequence == null || charSequence.length() == 0) {
results.count = mRooms.size();
results.values = mRooms;
} else {
filteredList = new ArrayList<>();
String filterText = charSequence.toString().toLowerCase();
for (ParseObject item : mRooms) {
String objectId = item.getObjectId().toLowerCase();
if (objectId.contains(filterText)) {
filteredList.add(item);
}
}
}
results.count = filteredList.size();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults results) {
mRooms.clear();
if (results.values != null) {
mRooms.addAll((List<ParseObject>) results.values);
}
notifyDataSetChanged();
}
};
}
以上是你提供的代码的翻译。
英文:
I am using parse server for my database. I wanted to get the item while user search on the search function. I search on the google for this but did not found anything suitable.
#MainActivity
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
final ParseQuery<ParseUser> query = ParseUser.getQuery();
//get the search view and set the searchable configuration
SearchManager searchManager = (SearchManager) getSystemService(Context.SEARCH_SERVICE);
SearchView searchView = (SearchView) menu.findItem(R.id.search).getActionView();
//searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
//assumes the current activity is the searchable activity
searchView.setSearchableInfo(searchManager.getSearchableInfo(getComponentName()));
searchView.setSubmitButtonEnabled(true);
searchView.setSubmitButtonEnabled(true);
// searchView.setOnQueryTextListener((SearchView.OnQueryTextListener) this);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
return true;
}
});
return true;
}
@Override
public boolean onSearchRequested() {
//pauseSomeStuff();
return super.onSearchRequested();
}
RoomCardRecyclerViewAdapter
I wanted to get item from this adapter by using search functionality and filter it for the user
private List<ParseObject> mRooms = new ArrayList<>();
private ParseObject room;
private String mSection;
public RoomCardRecyclerViewAdapter(){
super(DIFF_CALLBACK);
}
public static final DiffUtil.ItemCallback<ParseObject> DIFF_CALLBACK = new
DiffUtil.ItemCallback<ParseObject>() {
@Override
public boolean areItemsTheSame(@NonNull ParseObject oldItem, @NonNull ParseObject newItem) {
return oldItem.getObjectId() == newItem.getObjectId();
}
@Override
public boolean areContentsTheSame(@NonNull ParseObject oldItem, @NonNull ParseObject newItem) {
return (oldItem.getUpdatedAt().equals(newItem.getUpdatedAt()) &&
oldItem.getCreatedAt().equals(newItem.getCreatedAt()));
}
};
public RoomCardRecyclerViewAdapter(String section) {
this();
this.mSection = section;
}
public class RoomViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
protected ImageView mRoomImage;
protected TextView mRoomPrice;
protected TextView mInclusiveOrNot;
protected TextView mPropertyType;
protected TextView mNumOfBeds;
protected TextView mNumOfBaths;
protected TextView mRoomLocation;
private Context context;
public RoomViewHolder(Context context, View itemView) {
super(itemView);
mRoomImage = itemView.findViewById(R.id.room_image);
mRoomPrice = itemView.findViewById(R.id.price_label);
mInclusiveOrNot = itemView.findViewById(R.id.incl_excl_label);
mPropertyType = itemView.findViewById(R.id.propertyType_label);
mNumOfBeds = itemView.findViewById(R.id.num_beds_label);
mNumOfBaths = itemView.findViewById(R.id.details_num_baths_label);
mRoomLocation = itemView.findViewById(R.id.location_label);
this.context = context;
//set onclick listener
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Log.i("Click event: ", "My room has been clicked.");
int pos = getAdapterPosition();
Intent intent;
ParseObject room = getCurrentList().get(pos);
//create the ParseObject proxy
ParseProxyObject roomProxy = new ParseProxyObject(room);
Toast.makeText(context, room.getString("roomSuburb"), Toast.LENGTH_LONG).show();
//fork to corresponding activity
if(mSection != null) {
Log.i("mSection text: ", "mSection text is: " + mSection);
if (mSection.equals("My Rooms")) {
//start my rooms detail activity
Log.i("My room: ", "Room selected " + roomProxy.getObjectId());
intent = new Intent(context, MyRoomDetailActivity.class);
//add the room to the intent
intent.putExtra("currentSelectedRoomObject", room);
Log.i("Selected room", "Put Extra, " + room);
intent.putExtra("roomObject", roomProxy);
context.startActivity(intent);
}
}else {
Log.i("My room:", "RoomDetailActivity loaded for MyRoomDetail Activity instead");
intent = new Intent(context, RoomDetailActivity.class);
//add the proxy to the intent
intent.putExtra("roomObject", roomProxy);
context.startActivity(intent);
}
}
}
@Override
public RoomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
//inflating the viewholder with the appropriate views
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.room_cardview, parent, false);
return new RoomViewHolder(parent.getContext(), view);
}
@Override
public void onBindViewHolder(@NonNull RoomViewHolder holder, int position) {
room = getItem(position);
holder.mRoomLocation.setText(room.getString("roomSuburb"));
holder.mRoomPrice.setText(Integer.toString(room.getInt("roomMonthlyRent")));
holder.mInclusiveOrNot.setText(room.getString("roomRentInclusiveOfBills"));
holder.mPropertyType.setText(room.getString("roomPropertyType"));
holder.mNumOfBeds.setText(Integer.toString(room.getInt("roomBedrooms")));
holder.mNumOfBaths.setText(Integer.toString(room.getInt("roomBathrooms")));
//get the image
//check if its roomImage or image1 set
ParseFile imageFile;
if (room.getParseFile("roomImage") != null){
//
imageFile = room.getParseFile("roomImage");
}else {
imageFile = room.getParseFile("roomImage1");
}
//if there is no image saved in Parse
if(imageFile == null){
//continue to load predefined default image
int r = R.mipmap.ic_launcher;
Glide.with(holder.mRoomImage.getContext()).load(r)
.into(holder.mRoomImage);
}else {
Uri fileUri = Uri.parse(imageFile.getUrl());
//image loader recommended by Google
Glide.with(holder.mRoomImage.getContext()).load(fileUri.toString())
.thumbnail(0.6f)
.centerCrop()
.crossFade()
.into(holder.mRoomImage);
}
}
public void addMoreRooms(List<ParseObject> newRooms){
mRooms.addAll(newRooms);
submitList((PagedList<ParseObject>) mRooms);
}
public void addAll(List<ParseObject> latestRooms) {
mRooms.addAll(0, latestRooms);
//mRooms.add(i, latestRooms);
notifyDataSetChanged();
}
@Override
public Filter getFilter(){
return new Filter() {
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults results = new FilterResults();
List<ParseObject> filteredList = null;
if (charSequence == null || charSequence.length() == 0) {
results.count = mRooms.size();
results.values = mRooms;
//results = mRooms.size();
} else {
filteredList = new ArrayList<>();
charSequence = charSequence.toString().toLowerCase();
for (ParseObject item : mRooms) {
String mSection = item.getObjectId().toLowerCase();
filteredList.add(item);
}
}
results.count = filteredList.size();
results.values = filteredList;
return results;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults results) {
room = (ParseObject) results.values;
notifyDataSetChanged();
}
};
}
答案1
得分: 2
请将您的适配器实现Filterable
接口,并查看此链接中的主题,尤其是非常详细的答案。该主题讨论了BaseAdapter
,但是负责过滤的部分对于所有适配器都是通用的。关键是在适配器中具有自定义的重写getFilter()
方法。
@Override
public Filter getFilter() {
return new Filter() {
// 实现您的过滤器
...
并通过以下方式将SearchView
中的query
传递给它:
@Override
public boolean onSearchRequested() {
String query = searchView.getText().toString();
adapter.getFilter().filter(query);
return true;
}
英文:
make your adapter implements Filterable
and take a look for THIS topic on SO, especially very detailed answer. it's about BaseAdapter
, but part resposible for filtering is common for all adapters. the clue is to have custom overriden getFilter()
method in your adapter
@Override
public Filter getFilter() {
return new Filter() {
// implementation of your Filter
...
and pass query
from SearchView
to it by
@Override
public boolean onSearchRequested() {
String query - searchView.getText().toString();
adapter.getFilter().filter(query);
return true;
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论