I ran into a problem and still don't know how to get out. I made a listview with a custom adapter for it. I also implemented a searchview which will update the listview everytime I type in a character. But the problem is that the listview is not showing the correct results. I put some checkpoints in getView
method of the custom adapter to check if the values which will be displayed are right or not and they're all right.
I have two items, let's call them HD03 and HD02 as you can see their name on the top left corner of each item.
when I type in the search bar 02
, the result must be item HD02
but I got item HD03
instead. Although, the value I checked in the getView
method using debugger was HD02
I think I made a silly mistake somewhere but I can't find it. Thank you for your time ! Here're my fragment and my adapter code.
Fragment
public class DashboardFragment extends Fragment {
private DashboardViewModel dashboardViewModel;
private ListView listViewContract;
private SearchView contractSearchView;
private ContractAdapter productListAdapter;
public View onCreateView(@NonNull LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
dashboardViewModel =
new ViewModelProvider(this).get(DashboardViewModel.class);
View root = inflater.inflate(R.layout.fragment_dashboard, container, false);
initView(root);
return root;
}
private void initView(View view) {
listViewContract = view.findViewById(R.id.contract_list);
listViewContract.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
listViewProduct_onItemClick(adapterView, view, i, l);
}
});
loadData();
contractSearchView = view.findViewById(R.id.search_bar);
contractSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
DashboardFragment.this.productListAdapter.getFilter().filter(query);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
DashboardFragment.this.productListAdapter.getFilter().filter(newText);
return false;
}
});
}
private void loadData() {
List<Contract> products = new ArrayList<Contract>();
products.add(new Contract("p03", "Name 1", "4", "Mới", "HD03" ));
products.add(new Contract("p02", "Name 2", "5", "Mới", "HD02"));
productListAdapter = new ContractAdapter(getContext(), products);
listViewContract.setAdapter(productListAdapter);
}
private void listViewProduct_onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
// Product product = (Product) adapterView.getItemAtPosition(i);
// Toast.makeText(getApplicationContext(), product.getName(), Toast.LENGTH_LONG).show();
}
}
Adapter
public class ContractAdapter extends BaseAdapter implements Filterable {
private Context context;
private List<Contract> products;
private List<Contract> filteredData;
private ItemFilter itemFilter = new ItemFilter();
public ContractAdapter(Context context, List<Contract> products){
this.context = context;
this.products = products;
this.filteredData = products;
}
@NonNull
@Override
public View getView(int position, View view, ViewGroup parent) {
ViewHolder viewHolder;
if (view == null) {
viewHolder = new ViewHolder();
view = LayoutInflater.from(context).inflate(R.layout.phan_anh_cardview, parent, false);
viewHolder.textViewContractName = view.findViewById(R.id.ten_hd);
viewHolder.textViewCustomerName = view.findViewById(R.id.ten_dt);
viewHolder.textViewEmployeeName = view.findViewById(R.id.ten_nv);
viewHolder.textViewId = view.findViewById(R.id.ma_hd);
viewHolder.buttonStatus = view.findViewById(R.id.report_status);
view.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) view.getTag();
}
Contract product = filteredData.get(position);
viewHolder.textViewContractName.setText(product.getName());
viewHolder.textViewEmployeeName.setText(product.getNhanvien());
viewHolder.textViewCustomerName.setText(product.getCustomer());
viewHolder.textViewId.setText(product.get_id());
viewHolder.buttonStatus.setText(product.getStatus());
Log.i("view", viewHolder.textViewId.getText().toString());
return view;
}
public int getCount(){
return filteredData.size();
}
public Contract getItem(int position) {
return filteredData.get(position);
}
public long getItemId(int position) {
return position;
}
@NonNull
@Override
public Filter getFilter() {
return itemFilter;
// return super.getFilter();
}
private static class ViewHolder {
public static TextView textViewContractName;
public static TextView textViewCustomerName;
public static TextView textViewEmployeeName;
public static TextView textViewId;
public static Button buttonStatus;
}
private class ItemFilter extends Filter{
@Override
protected FilterResults performFiltering(CharSequence constraint) {
String query = constraint.toString();
FilterResults results = new FilterResults();
List<Contract> originalData = products;
int count = originalData.size();
List<Contract> nList = new ArrayList<>();
for (Contract contract : originalData) {
if(contract.get_id().contains(query) || contract.getName().contains(query) || contract.getCustomer().contains(query)){
nList.add(contract);
}
}
results.values = nList;
results.count = nList.size();
return results;
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
filteredData = (List<Contract>) results.values;
notifyDataSetChanged();
}
}
}
fragment_dashboard.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.dashboard.DashboardFragment">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/tag_spinner_constraint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<SearchView
android:id="@+id/search_bar"
android:layout_width="match_parent"
android:layout_height="45dp"
android:iconifiedByDefault="false"
app:layout_constraintEnd_toEndOf="@id/tag_spinner_constraint"
app:layout_constraintStart_toStartOf="@id/tag_spinner_constraint"
app:layout_constraintTop_toTopOf="@id/tag_spinner_constraint" />
<HorizontalScrollView
android:id="@+id/filter_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/search_bar">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/empty_rooms_btn"
android:layout_width="99dp"
android:layout_height="34dp"
android:layout_marginStart="5dp"
android:layout_marginLeft="5dp"
android:layout_marginTop="4dp"
android:background="@drawable/rounded_button"
android:text="Phòng trống"
android:textSize="12sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/floor_spinner" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/not_full_rooms_btn"
android:layout_width="wrap_content"
android:layout_height="34dp"
android:layout_marginStart="12dp"
android:layout_marginLeft="12dp"
android:layout_marginTop="4dp"
android:background="@drawable/rounded_button"
android:text="Phòng ghép"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@+id/empty_rooms_btn"
app:layout_constraintTop_toBottomOf="@+id/floor_spinner" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/full_rooms_btn"
android:layout_width="105dp"
android:layout_height="34dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="4dp"
android:background="@drawable/rounded_button"
android:text="Phòng đã đầy"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@+id/not_full_rooms_btn"
app:layout_constraintTop_toBottomOf="@+id/floor_spinner" />
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/all_rooms_btn"
android:layout_width="wrap_content"
android:layout_height="34dp"
android:layout_marginLeft="10dp"
android:layout_marginTop="4dp"
android:background="@drawable/rounded_button"
android:text="Tất cả"
android:textSize="12sp" />
</LinearLayout>
</HorizontalScrollView>
</androidx.constraintlayout.widget.ConstraintLayout>
<ListView
android:id="@+id/contract_list"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_marginTop="2dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tag_spinner_constraint">
</ListView>
</androidx.constraintlayout.widget.ConstraintLayout>
phan_anh_cardview.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="8dp">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="162dp"
android:layout_marginTop="5dp"
android:padding="6dp">
<androidx.appcompat.widget.AppCompatButton
android:id="@+id/report_status"
android:layout_width="68dp"
android:layout_height="15dp"
android:background="@drawable/rounded_button"
android:text="Mới"
android:textSize="10sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ma_hd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="18sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ten_hd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="30sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ma_hd" />
<TextView
android:id="@+id/ten_dt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ten_hd" />
<TextView
android:id="@+id/ten_nv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ten_dt" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
rounded_button.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="@color/cardview_dark_background" />
<corners android:bottomRightRadius="30dp"
android:bottomLeftRadius="30dp"
android:topRightRadius="30dp"
android:topLeftRadius="30dp"/>
</shape>
I found error in your code. You shouldn't use static members in ViewHolder. So please replace ViewHolder code as following.
ContractAdapter.java
..............
private static class ViewHolder {
public TextView textViewContractName;
public TextView textViewCustomerName;
public TextView textViewEmployeeName;
public TextView textViewId;
public Button buttonStatus;
}
...............
If so, it will be working.