在ListView上实现搜索功能

huangapple go评论79阅读模式
英文:

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&lt;ParseUser&gt; 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&lt;ParseObject&gt; mRooms = new ArrayList&lt;&gt;();
private ParseObject room;
private String mSection;
public RoomCardRecyclerViewAdapter(){
super(DIFF_CALLBACK);
}
public static final DiffUtil.ItemCallback&lt;ParseObject&gt;  DIFF_CALLBACK = new 
DiffUtil.ItemCallback&lt;ParseObject&gt;() {
@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()) &amp;&amp; 
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(&quot;Click event: &quot;, &quot;My room has been clicked.&quot;);
int pos = getAdapterPosition();
Intent intent;
ParseObject room = getCurrentList().get(pos);
//create the ParseObject proxy
ParseProxyObject roomProxy = new ParseProxyObject(room);
Toast.makeText(context, room.getString(&quot;roomSuburb&quot;), Toast.LENGTH_LONG).show();
//fork to corresponding activity
if(mSection != null) {
Log.i(&quot;mSection text: &quot;, &quot;mSection text is: &quot; + mSection);
if (mSection.equals(&quot;My Rooms&quot;)) {
//start my rooms detail activity
Log.i(&quot;My room: &quot;, &quot;Room selected &quot; + roomProxy.getObjectId());
intent = new Intent(context, MyRoomDetailActivity.class);
//add the room to the intent
intent.putExtra(&quot;currentSelectedRoomObject&quot;, room);
Log.i(&quot;Selected room&quot;, &quot;Put Extra, &quot; + room);
intent.putExtra(&quot;roomObject&quot;, roomProxy);
context.startActivity(intent);
}
}else {
Log.i(&quot;My room:&quot;, &quot;RoomDetailActivity loaded for MyRoomDetail Activity instead&quot;);
intent = new Intent(context, RoomDetailActivity.class);
//add the proxy to the intent
intent.putExtra(&quot;roomObject&quot;, 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(&quot;roomSuburb&quot;));
holder.mRoomPrice.setText(Integer.toString(room.getInt(&quot;roomMonthlyRent&quot;)));
holder.mInclusiveOrNot.setText(room.getString(&quot;roomRentInclusiveOfBills&quot;));
holder.mPropertyType.setText(room.getString(&quot;roomPropertyType&quot;));
holder.mNumOfBeds.setText(Integer.toString(room.getInt(&quot;roomBedrooms&quot;)));
holder.mNumOfBaths.setText(Integer.toString(room.getInt(&quot;roomBathrooms&quot;)));
//get the image
//check if its roomImage or image1 set
ParseFile imageFile;
if (room.getParseFile(&quot;roomImage&quot;) != null){
//
imageFile = room.getParseFile(&quot;roomImage&quot;);
}else {
imageFile = room.getParseFile(&quot;roomImage1&quot;);
}
//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&lt;ParseObject&gt; newRooms){
mRooms.addAll(newRooms);
submitList((PagedList&lt;ParseObject&gt;) mRooms);
}
public void addAll(List&lt;ParseObject&gt; 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&lt;ParseObject&gt; filteredList = null;
if (charSequence == null || charSequence.length() == 0) {
results.count = mRooms.size();
results.values = mRooms;
//results = mRooms.size();
} else {
filteredList = new ArrayList&lt;&gt;();
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;
}

huangapple
  • 本文由 发表于 2020年9月15日 15:20:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63896946.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定