简体   繁体   中英

How to implement Recyclerview with EditText in each item and Filter the list with SearchView?

I implemented EditText in each item and filtered it using SearchView , both are working fine separately .But, the problem is when I input some value in EditText field of an item and filter the list using search, the value entered stays in the same position where it's given. ie the new items comes as a result of search has the same value I gave to the item before searching

public class ItemMasterAdapter extends RecyclerView.Adapter<ItemMasterAdapter.ItemMasterViewHolder> implements Filterable{
private Context context;
private List<Order> itemList;
private List<Order> itemListFull;
private LayoutInflater inflater;

public static ArrayList<EditModel> editModelArrayList;

public ItemMasterAdapter(Context context, List<Order> itemList, ArrayList<EditModel> editModelArrayList1)
{
    this.context = context;
    this.itemList = itemList;
    itemListFull=new ArrayList<>(itemList);
    this.inflater = LayoutInflater.from(context);
    this.editModelArrayList = editModelArrayList1;
}

@NonNull
@Override
public ItemMasterViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i)
{
    View imView = inflater.inflate(R.layout.list_item_master, viewGroup, false);
    return new ItemMasterViewHolder(imView);
}

@Override

public void onBindViewHolder(@NonNull ItemMasterViewHolder itemMasterViewHolder, int i)
{

    Order iList = itemList.get(i);
   itemMasterViewHolder.itemNameTextView.setText(iList.itemName);
   itemMasterViewHolder.inputQtyEditText.setText(editModelArrayList.get(i).getEditTextValue());
}

@Override
public int getItemCount()
{
    return itemList.size();
}

@Override
public long getItemId(int position)
{
    return super.getItemId(position);
}

@Override
public int getItemViewType(int position)
{
    return super.getItemViewType(position);
}

public class ItemMasterViewHolder extends RecyclerView.ViewHolder
{
    ImageView itemImageView;
    TextView itemNameTextView, itemQtyTextView, itemPriceTextView, itemStockTextView;
    EditText inputQtyEditText;

    public ItemMasterViewHolder(@NonNull View itemView)
    {
        super(itemView);

        itemNameTextView = itemView.findViewById(R.id.mtv_item_name);
        inputQtyEditText = itemView.findViewById(R.id.et_input_item_stock);
        inputQtyEditText.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) {
                String inputValue=inputQtyEditText.getText().toString();
                Order iList = itemList.get(getAdapterPosition());
                editModelArrayList.get(itemList.indexOf(iList)).setEditTextValue(inputValue);
            }

            @Override
            public void afterTextChanged(Editable s)
            {

            }
        });
    }
}



@Override
public Filter getFilter()
{
    return itemFilter;
}

private Filter itemFilter=new Filter() {
    @Override
    protected FilterResults performFiltering(CharSequence constraint) {
        List<Order> filteredItemList=new ArrayList<>();

        if(constraint==null || constraint.length()==0)
        {
            filteredItemList.addAll(itemListFull);

        }

        else
        {
            String filteredPattern=constraint.toString().toLowerCase().trim();

            for(Order item : itemListFull)
            {
                if(item.itemName.toLowerCase().contains(filteredPattern))
                {
                    filteredItemList.add(item);
                }
            }
        }

        FilterResults results=new FilterResults();
        results.values=filteredItemList;
        return results;
    }

    @Override
    protected void publishResults(CharSequence constraint, FilterResults results)
    {
        itemList.clear();
        itemList.addAll((List)results.values);
        notifyDataSetChanged();
    }
};}

import static com.mrcodekiddie.tobuytoday.ItemMasterAdapter.editModelArrayList;

public class ShopOrderActivity extends AppCompatActivity {
RecyclerView mRecyclerView;
List<Order> itemList;

private Toolbar toolbar;
ItemMasterAdapter itemMasterAdapter;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_shop_order);
    toolbar=findViewById(R.id.app_bar_order);
    setSupportActionBar(toolbar);
    getSupportActionBar().setDisplayHomeAsUpEnabled(false);
    getSupportActionBar().setTitle("KID");


    itemList=new ArrayList<Order>();

    itemList.add(new Order("001","burger"));
    itemList.add(new Order("002","pizza"));
    itemList.add(new Order("003","sandwich"));
    itemList.add(new Order("004","lemonade"));
    itemList.add(new Order("005","cold coffee"));
    itemList.add(new Order("006","hot coffee"));
    itemList.add(new Order("007","black coffee"));
    itemList.add(new Order("008","green tea"));
    itemList.add(new Order("010","Idly"));
    itemList.add(new Order("011","Dhosai"));
    itemList.add(new Order("012","Pongal"));
    itemList.add(new Order("013","Poori"));
    itemList.add(new Order("014","Ooothappam"));
    itemList.add(new Order("015","Vadai"));
    itemList.add(new Order("016","Parotta"));
    itemList.add(new Order("017","pani poori"));
    itemList.add(new Order("018","bele poori"));
    itemList.add(new Order("019","Omlete"));
    itemList.add(new Order("020","kalakki"));
    itemList.add(new Order("021","Half Boil"));
    itemList.add(new Order("022","Full Boil"));


    mRecyclerView=findViewById(R.id.mRecyclerView);
    mRecyclerView.setHasFixedSize(false);

    mRecyclerView.setLayoutManager(new LinearLayoutManager(ShopOrderActivity.this));
    editModelArrayList = populateList();

     itemMasterAdapter=new ItemMasterAdapter(this,
            itemList,editModelArrayList);
    mRecyclerView.setAdapter(itemMasterAdapter)
}

@Override
protected void onResume() {
    super.onResume();
    itemList=new ArrayList<Order>();

}

private ArrayList<EditModel> populateList() {
    ArrayList<EditModel> list = new ArrayList<>();

    for(int i = 0; i <itemList.size(); i++)
    {
        EditModel editModel = new EditModel();
        editModel.setEditTextValue("");
        list.add(editModel);
    }
    return list;
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    MenuInflater inflater=getMenuInflater();
    inflater.inflate(R.menu.search_menu,menu);

    MenuItem searchItem=menu.findItem(R.id.action_search);

    SearchView searchView = (SearchView) searchItem.getActionView();
     searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
         @Override
         public boolean onQueryTextSubmit(String query) {
             return false;
         }

         @Override
         public boolean onQueryTextChange(String newText) {

             itemMasterAdapter.getFilter().filter(newText);
             return false;
         }
     });
    return true;
}}

public class EditModel {
private String editTextValue;

public EditModel(){ }

public String getEditTextValue()
{
    return editTextValue;
}

public void setEditTextValue(String editTextValue)
{
    this.editTextValue = editTextValue;
} }

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    card_view:cardCornerRadius="6dp"
    card_view:cardElevation="4dp"
    card_view:cardUseCompatPadding="true">


    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="4dp">

        <EditText
            android:id="@+id/et_input_item_stock"
            android:layout_width="65dp"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="10dp"
            android:backgroundTint="@color/accent"
            android:imeOptions="actionDone"
            android:inputType="numberDecimal"
            android:justificationMode="inter_word"
            android:textAlignment="center"
            android:textColor="@android:color/background_dark"
            />


        <TextView
            android:id="@+id/mtv_item_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="7dp"
            android:maxWidth="220dp"
            android:text="Dummy Item"
            android:textColor="@color/primary_text"
            android:textSize="12pt"

            />
    </RelativeLayout>

</androidx.cardview.widget.CardView>
</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".ShopOrderActivity">

<androidx.appcompat.widget.Toolbar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/app_bar_order"
    android:theme="@style/AppTheme"
    app:titleTextColor="@color/white"
    android:background="@color/primary"
    app:popupTheme="@style/AppTheme">

</androidx.appcompat.widget.Toolbar>
<RelativeLayout
    android:id="@+id/tv_item_header"
    android:layout_below="@id/app_bar_order"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">


</RelativeLayout>

<androidx.recyclerview.widget.RecyclerView
    android:layout_below="@id/tv_item_header"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/mRecyclerView"
   >

</androidx.recyclerview.widget.RecyclerView>

Here's the whole code link !

Instead of :

Order iList = itemList.get(getAdapterPosition());

editModelArrayList.get(itemList.indexOf(iList)).setEditTextValue(inputValue);

Directly use :

editModelArrayList.get(getLayoutPosition()).setEditTextValue(inputValue);

Also instead of using the position i:

itemMasterViewHolder.inputQtyEditText.setText(editModelArrayList.get(i).getEditTextValue());

You should use

itemMasterViewHolder.inputQtyEditText.setText(editModelArrayList.get(itemMasterViewHolder.getLayoutPositon()).getEditTextValue());

So the simple issue is, that position i is not reliable when the list keeps changing.... when the list keeps changing use getAdapterPosition or getLayoutPosition of the viewholder. I prefer getLayoutPosition as it always returns the correct position whereas getAdapterPosition very rarely returns the wrong position

if you delete/add/change any item in the data set and notify the RecyclerView Using notify methods, RecyclerView will not call onBindViewHolder method and update all item's positions, It will only update the position of the new ones for the new calls of onBindViewHolder and this will cause inconsistency between displayed items and position value.

see the following post for more details:

Why not to use position passed in mutable recycler view lists

in Your view (Activity or Fragment that the recyclerview on it ) class implement

SearchView.OnQueryTextListener

then you have to override some methods one of them is

@Override public boolean onQueryTextChange(String s) {}

this method called when the serachView Text changes(or if u use Edit Text You can implements OnTextChangeListener ) and in this method :

@Override
public boolean onQueryTextChange(String s) {
    if (TextUtils.isEmpty(s)) { //check if text is empty show all items
        lstFiltered=items;
        setListAdapter(items);
    } else {
        filterInput(s);
    }

    return true;
}

lstFiltered is a List of RecyclerView Item Model that when items that passed input text for search we add these items in this List

and

items is all of items

and filterInput() method is :

private void filterInput(String s) {

    lstFiltered = new ArrayList<>();
    for (int i = 0; i < items.size(); i++) { //for filtering items
        if (/* condition that you want to filter items */) {
            lstFiltered.add(items.get(i));
        }
    }
    setListAdapter(lstFiltered); //set Recycler Adapter or mAdapter.notifyDataSetChanged(
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM