搜索后单击 RecyclerView 不会产生正确的数据
Clicking on a RecyclerView after search doesn't yield correct data
我有一个在 RecyclerView 上显示酒店列表的片段。仅显示酒店名称。如果单击其中一个名称,将启动 activity,显示酒店详细信息(名称、地址、位置、房间数)。为了让生活更轻松,我还有一个 SearchView,因此用户可以简单地搜索酒店名称而不是滚动。
HotelFragment.java
public class HotelFragment extends Fragment {
ArrayList<Kost> hotelList = new ArrayList<>();
HotelAdapter mAdapter;
SearchView searchView;
public HotelFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.hotel_fragment, container, false);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
hotelAdapter = new KostAdapter(mList);
// if a hotel is clicked, launch an activity which displays its full information
mAdapter.setOnItemClickListener(new ClickListener() {
@Override
public void onItemClick(int position, View v) {
Hotel hotel = hotelList.get(position);
Bundle bnd = new Bundle();
bnd.putString("hotel_name", hotel.getName());
bnd.putString("hotel_description", hotel.getDescription());
bnd.putString("hotel_address", hotel.getAddress());
bnd.putString("hotel_room", hotel.getRoom());
bnd.putString("hotel_latitude", hotel.getLatitude());
bnd.putString("hotel_longitude", hotel.getLongitude());
Intent iii = new Intent(getActivity(), HotelDetailActivity.class);
iii.putExtra("hotel_detail", bnd);
startActivity(iii);
}
@Override
public void onItemLongClick(int position, View v) {
}
});
searchView = (SearchView) view.findViewById(R.id.searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
hotelAdapter.getFilter().filter(query);
return false;
}
@Override
public boolean onQueryTextChange(String query) {
hotelAdapter.getFilter().filter(query);
return false;
}
});
hotelAdapter.notifyDataSetChanged();
recyclerView.setAdapter(hotelAdapter);
getHotelListFromFirebase();
return view;
}
}
HotelAdapter.java
public class HotelAdapter extends RecyclerView.Adapter<HotelAdapter.ViewHolder> implements Filterable {
static ClickListener clickListener;
ArrayList<Hotel> hotelList;
ArrayList<Hotel> hotelList_filtered;
public KostAdapter(ArrayList<Hotel> hotelList)
{
this.hotelList = hotelList;
this.hotelList_filtered = hotelList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list,parent,false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Hotel hotel = hotelList_filtered.get(position);
holder.tvName.setText(hotel.getName());
holder.tvDescription.setText(hotel.getDescription());
holder.tvAddress.setText(hotel.getAddress());
}
@Override
public int getItemCount() {
if (hotelList_filtered != null) return hotelList_filtered.size();
return 0;
}
public void setOnItemClickListener(ClickListener clickListener) {
HotelAdapter.clickListener = clickListener;
}
@Override
public Filter getFilter() {
return new Filter(){
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String sequence = charSequence.toString().toLowerCase();
if (sequence.isEmpty()) kostList_filtered = kostList;
else {
ArrayList<Hotel> filteredList = new ArrayList<>();
for (Hotel h : hotelList){
if (h.getName().toLowerCase().contains(sequence)){
filteredList.add(h);
}
}
hotelList_filtered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = kostList_filtered;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
hotelList_filtered = (ArrayList<Hotel>) filterResults.values;
notifyDataSetChanged();
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView tvName;
TextView tvDescription;
TextView tvAddressl
public ViewHolder(View itemView)
{
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvDescription = (TextView) itemView.findViewById(R.id.tvDescription);
tvAddress = (TextView) itemView.findViewById(R.id.tvAddress);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
@Override
public void onClick(View view) {
clickListener.onItemClick(getAdapterPosition(), view);
}
@Override
public boolean onLongClick(View view) {
clickListener.onItemLongClick(getAdapterPosition(), view);
return false;
}
}
}
ClickListener.java
public interface ClickListener {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
显示初始列表和搜索没问题。到目前为止没问题。问题是搜索后点击酒店。
假设初始酒店列表是:
{"Hotel Foobar", "Hotel California", "Hotel 2112", "Hotel Crimson"}
如果我搜索“2112”,RecyclerView 只会显示 "Hotel 2112"(这是正确的),但单击它会显示 "Hotel Foobar" 的详细信息。我认为这是因为
Hotel hotel = hotelList.get(position);
和位置为0.
如何解决这个问题?
Relpace 这个,我也在我的项目中使用了同样的东西,如下所示,它给出了正确的结果
@Override
public int getItemCount() {
if (hotelList_filtered != null) return hotelList_filtered.size();
return 0;
}
有,
@Override
public int getItemCount() {
if (hotelList_filtered != null)
return hotelList_filtered.size();
}
您正在从过滤器列表中获取数据,所以这没有问题
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Hotel hotel = hotelList_filtered.get(position);
holder.tvName.setText(hotel.getName());
holder.tvDescription.setText(hotel.getDescription());
holder.tvAddress.setText(hotel.getAddress());
}
从您的筛选列表中获取位置:
@Override
public void onClick(View view) {
clickListener.onItemClick(hotelList_filtered.get(getPosition()), view);
}
@Override
public boolean onLongClick(View view) {
clickListener.onItemLongClick(hotelList_filtered.get(getPosition()), view);
return false;
}
不要使用包含所有酒店的列表,而是尝试使用当前正在使用的列表。
hotelAdapter.hotelList_filtered.get(position);
我有一个在 RecyclerView 上显示酒店列表的片段。仅显示酒店名称。如果单击其中一个名称,将启动 activity,显示酒店详细信息(名称、地址、位置、房间数)。为了让生活更轻松,我还有一个 SearchView,因此用户可以简单地搜索酒店名称而不是滚动。
HotelFragment.java
public class HotelFragment extends Fragment {
ArrayList<Kost> hotelList = new ArrayList<>();
HotelAdapter mAdapter;
SearchView searchView;
public HotelFragment() {
// Required empty public constructor
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.hotel_fragment, container, false);
RecyclerView recyclerView = (RecyclerView) view.findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(layoutManager);
hotelAdapter = new KostAdapter(mList);
// if a hotel is clicked, launch an activity which displays its full information
mAdapter.setOnItemClickListener(new ClickListener() {
@Override
public void onItemClick(int position, View v) {
Hotel hotel = hotelList.get(position);
Bundle bnd = new Bundle();
bnd.putString("hotel_name", hotel.getName());
bnd.putString("hotel_description", hotel.getDescription());
bnd.putString("hotel_address", hotel.getAddress());
bnd.putString("hotel_room", hotel.getRoom());
bnd.putString("hotel_latitude", hotel.getLatitude());
bnd.putString("hotel_longitude", hotel.getLongitude());
Intent iii = new Intent(getActivity(), HotelDetailActivity.class);
iii.putExtra("hotel_detail", bnd);
startActivity(iii);
}
@Override
public void onItemLongClick(int position, View v) {
}
});
searchView = (SearchView) view.findViewById(R.id.searchView);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
hotelAdapter.getFilter().filter(query);
return false;
}
@Override
public boolean onQueryTextChange(String query) {
hotelAdapter.getFilter().filter(query);
return false;
}
});
hotelAdapter.notifyDataSetChanged();
recyclerView.setAdapter(hotelAdapter);
getHotelListFromFirebase();
return view;
}
}
HotelAdapter.java
public class HotelAdapter extends RecyclerView.Adapter<HotelAdapter.ViewHolder> implements Filterable {
static ClickListener clickListener;
ArrayList<Hotel> hotelList;
ArrayList<Hotel> hotelList_filtered;
public KostAdapter(ArrayList<Hotel> hotelList)
{
this.hotelList = hotelList;
this.hotelList_filtered = hotelList;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list,parent,false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Hotel hotel = hotelList_filtered.get(position);
holder.tvName.setText(hotel.getName());
holder.tvDescription.setText(hotel.getDescription());
holder.tvAddress.setText(hotel.getAddress());
}
@Override
public int getItemCount() {
if (hotelList_filtered != null) return hotelList_filtered.size();
return 0;
}
public void setOnItemClickListener(ClickListener clickListener) {
HotelAdapter.clickListener = clickListener;
}
@Override
public Filter getFilter() {
return new Filter(){
@Override
protected FilterResults performFiltering(CharSequence charSequence) {
String sequence = charSequence.toString().toLowerCase();
if (sequence.isEmpty()) kostList_filtered = kostList;
else {
ArrayList<Hotel> filteredList = new ArrayList<>();
for (Hotel h : hotelList){
if (h.getName().toLowerCase().contains(sequence)){
filteredList.add(h);
}
}
hotelList_filtered = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = kostList_filtered;
return filterResults;
}
@Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
hotelList_filtered = (ArrayList<Hotel>) filterResults.values;
notifyDataSetChanged();
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
TextView tvName;
TextView tvDescription;
TextView tvAddressl
public ViewHolder(View itemView)
{
super(itemView);
tvName = (TextView) itemView.findViewById(R.id.tvName);
tvDescription = (TextView) itemView.findViewById(R.id.tvDescription);
tvAddress = (TextView) itemView.findViewById(R.id.tvAddress);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
}
@Override
public void onClick(View view) {
clickListener.onItemClick(getAdapterPosition(), view);
}
@Override
public boolean onLongClick(View view) {
clickListener.onItemLongClick(getAdapterPosition(), view);
return false;
}
}
}
ClickListener.java
public interface ClickListener {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
显示初始列表和搜索没问题。到目前为止没问题。问题是搜索后点击酒店。
假设初始酒店列表是:
{"Hotel Foobar", "Hotel California", "Hotel 2112", "Hotel Crimson"}
如果我搜索“2112”,RecyclerView 只会显示 "Hotel 2112"(这是正确的),但单击它会显示 "Hotel Foobar" 的详细信息。我认为这是因为
Hotel hotel = hotelList.get(position);
和位置为0.
如何解决这个问题?
Relpace 这个,我也在我的项目中使用了同样的东西,如下所示,它给出了正确的结果
@Override
public int getItemCount() {
if (hotelList_filtered != null) return hotelList_filtered.size();
return 0;
}
有,
@Override
public int getItemCount() {
if (hotelList_filtered != null)
return hotelList_filtered.size();
}
您正在从过滤器列表中获取数据,所以这没有问题
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
Hotel hotel = hotelList_filtered.get(position);
holder.tvName.setText(hotel.getName());
holder.tvDescription.setText(hotel.getDescription());
holder.tvAddress.setText(hotel.getAddress());
}
从您的筛选列表中获取位置:
@Override
public void onClick(View view) {
clickListener.onItemClick(hotelList_filtered.get(getPosition()), view);
}
@Override
public boolean onLongClick(View view) {
clickListener.onItemLongClick(hotelList_filtered.get(getPosition()), view);
return false;
}
不要使用包含所有酒店的列表,而是尝试使用当前正在使用的列表。
hotelAdapter.hotelList_filtered.get(position);