Goal: keep track of selected items of a recyclerview using a changing Imageview for each row. Pratically i'm implementing a sort of checkbox.
Checking works fine:
but when I try to search for some items, checked items change: only first item of my list is checked:
I'll post my code below:
Shop Selected Interface
public interface NearestShopActivityAdapterListener {
void onShopSelected(FShop shop, View view);
}
My View Holder
public class MyHolder extends RecyclerView.ViewHolder{
public TextView name, address;
public ImageView logo;
public MyHolder(View itemView) {
super(itemView);
name = (TextView) itemView.findViewById(R.id.activityNearestShopListItemUhop);
address = (TextView) itemView.findViewById(R.id.activityNearestShopListItemAddress);
logo = (ImageView) itemView.findViewById(R.id.activityNearestShopListItemImage);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onShopSelected(filteredShopList.get(getAdapterPosition()),view);
}
});
}
onShopSelected function
#Override
public void onShopSelected(FShop shop, View view) {
if(checkList.contains(shop.getShopId())){
mImgViewCheckBox = (ImageView) view.findViewById(R.id.checkBoxNearestShop);
mImgViewCheckBox.setImageResource(R.drawable.checkbox_selector_not_checked);
checkList.remove(shop.getShopId());
}else {
mImgViewCheckBox = (ImageView) view.findViewById(R.id.checkBoxNearestShop);
mImgViewCheckBox.setImageResource(R.drawable.ic_checked);
checkList.add(shop.getShopId());
}
}
Where I am wrong? I would try to associate the ImageView mImgViewCheckBox with the Shop id and not with its position in the recyclerview, but I have no idea on how to do it.
Thnak you in advance.
i have done this things in contact details. i provide my adapter and method you can change code your according needs .
InviteContactAdapter.java
public class InviteContactAdapter extends RecyclerView.Adapter<InviteContactAdapter.ItemViewHolder> implements Filterable {
private List<UserContact> mContactList = new ArrayList<>();
private List<UserContact> mContectFilter = new ArrayList<>();
private Context mContext;
private CustomFilter mFilter;
public List<String> mEmailList = new ArrayList<>();
public InviteContactAdapter(Context context, List<UserContact> mContactList) {
mContext = context;
this.mContactList = mContactList;
this.mContectFilter = mContactList;
mFilter = new CustomFilter();
}
public onItemClickListener onItemClickListener;
public void setOnItemClickListener(InviteContactAdapter.onItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
#Override
public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.invite_contact_row_layout, viewGroup, false);
return new ItemViewHolder(view);
}
public interface onItemClickListener {
void onClick(UserContact contact);
}
#Override
public Filter getFilter() {
return mFilter;
}
#Override
public void onBindViewHolder(final ItemViewHolder itemViewHolder, int i) {
final UserContact contact = mContectFilter.get(i);
itemViewHolder.mTvUserNane.setText(contact.getUserName().trim());
itemViewHolder.mTvUserEmail.setText(contact.getUserEmail().trim());
if (contact.isSelect())
itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
else
itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);
itemViewHolder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (contact.isSelect()) {
contact.setSelect(false);
itemViewHolder.mIvSelect.setImageResource(R.drawable.un_check_contact);
} else {
contact.setSelect(true);
itemViewHolder.mIvSelect.setImageResource(R.drawable.check_contect);
}
}
});
}
#Override
public int getItemCount() {
return mContectFilter.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder {
private TextView mTvUserNane, mTvUserEmail;
private ImageView mIvSelect;
public ItemViewHolder(View itemView) {
super(itemView);
mTvUserEmail = itemView.findViewById(R.id.icrlTvUserEmail);
mTvUserNane = itemView.findViewById(R.id.icrlTvUserName);
mIvSelect = itemView.findViewById(R.id.icrlIvSelect);
}
}
public List<String> getEmail() {
mEmailList.clear();
for (UserContact contact : mContectFilter) {
if (contact.isSelect()) {
mEmailList.add(contact.getUserEmail());
}
}
return mEmailList;
}
/**
* this class for filter data.
*/
class CustomFilter extends Filter {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
FilterResults results = new FilterResults();
if (charSequence != null && charSequence.length() > 0) {
ArrayList<UserContact> filters = new ArrayList<>();
charSequence = charSequence.toString().toUpperCase();
for (int i = 0; i < mContactList.size(); i++) {
if (mContactList.get(i).getUserName().toUpperCase().contains(charSequence) || mContactList.get(i).getUserEmail().toUpperCase().contains(charSequence)) {
UserContact contact = new UserContact();
contact.setUserName(mContactList.get(i).getUserName());
contact.setUserEmail(mContactList.get(i).getUserEmail());
filters.add(contact);
}
}
results.count = filters.size();
results.values = filters;
} else {
results.count = mContactList.size();
results.values = mContactList;
}
return results;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mContectFilter = (ArrayList<UserContact>) filterResults.values;
notifyDataSetChanged();
}
}
}
then after bind contact data into recycler view and search data based on name and email..
make set adapter method ..
private void setAdapter(){
if (!mContactList.isEmpty()) {
inviteContactAdapter = new InviteContactAdapter(getActivity(), mContactList);
mRvData.setAdapter(inviteContactAdapter);
inviteContactAdapter.setOnItemClickListener(new InviteContactAdapter.onItemClickListener() {
#Override
public void onClick(UserContact contact) {
mEmailList.add(contact.getUserEmail());
}
});
} else {
mTvEmpty.setVisibility(View.VISIBLE);
}
}
then after make search data method ...
/**
* this method sort data.
*/
private void sortData(View root) {
mEtSearchData = (EditText) root.findViewById(R.id.icffEtSearch);
mEtSearchData.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) {
if (inviteContactAdapter != null) {
inviteContactAdapter.getFilter().filter(s);
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
after getting contact data it will be work. and you can change code your according.
i have also some lets say template that I am using every time when I need recycler view.
The diffrence is that I am using one more additional property in every item of list, so basically you are not depending on filtering, sorting or something else.
This is XML for activity:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.arnela.nihad.expresssaladbar.RecyclerViewExample.RecyclerViewActivity">
<SearchView
android:id="#+id/searchViewBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_weight="1"
android:iconifiedByDefault="false"
android:queryHint="HINT"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:clipToPadding="false"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/searchViewBox" />
</android.support.constraint.ConstraintLayout>
Java class of RecyclerViewActivity is next one:
public class RecyclerViewActivity extends AppCompatActivity {
private RecyclerView mRecyclerList;
private RecyclerViewAdapter mRecyclerAdapter;
private List<DataVm> mSourceList = new ArrayList<>();
private SearchView txtSearchBox;
private Data data;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recyler_view);
data = new Data();
mSourceList.addAll(data.getSourceList(""));
// this is recycler view from xml
mRecyclerList = findViewById(R.id.recycler_view);
InitRecyclerView();
txtSearchBox = findViewById(R.id.searchViewBox);
txtSearchBox.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
mSourceList.clear();
mSourceList.addAll(data.getSourceList(s));
mRecyclerAdapter.notifyDataSetChanged();
return false;
}
#Override
public boolean onQueryTextChange(String s) {
mSourceList.clear();
mSourceList.addAll(data.getSourceList(s));
mRecyclerAdapter.notifyDataSetChanged();
return false;
}
});
}
public void InitRecyclerView() {
mRecyclerList.setLayoutManager(new LinearLayoutManager(RecyclerViewActivity.this));
mRecyclerAdapter = new RecyclerViewAdapter(mSourceList, new IClickListenerAddRemove() {
#Override
public void onPositionClicked(int position, boolean isPicked) {
mSourceList.get(position).setPicked(isPicked);
}
});
mRecyclerList.setAdapter(mRecyclerAdapter);
}
}
Then, I have two helper class, one is for creating mockup data, with method for searching:
public class Data {
private List<DataVm> sourceList = null;
public Data() {
this.sourceList = new ArrayList<>();
// Items of the list and set all items to isPicked to false
sourceList.add(new DataVm(1, "Title 1", "Description 1", "", false));
sourceList.add(new DataVm(2, "Title 2", "Description 2", "", false));
sourceList.add(new DataVm(3, "Title 3", "Description 3", "", false));
sourceList.add(new DataVm(4, "Title 4", "Description 4", "", false));
sourceList.add(new DataVm(5, "Title 5", "Description 5", "", false));
sourceList.add(new DataVm(6 , "Title 6 ", "Description 6 ", "", false));
sourceList.add(new DataVm(7 , "Title 7 ", "Description 7 ", "", false));
sourceList.add(new DataVm(8 , "Title 8 ", "Description 8 ", "", false));
sourceList.add(new DataVm(9 , "Title 9 ", "Description 9 ", "", false));
sourceList.add(new DataVm(10, "Title 10", "Description 10", "", false));
sourceList.add(new DataVm(11, "Title 11", "Description 11", "", false));
sourceList.add(new DataVm(12, "Title 12", "Description 12", "", false));
}
public List<DataVm> getSourceList(String searchTitle) {
if (searchTitle.equals(""))
return sourceList;
List<DataVm> filteredList = new ArrayList<>();
for (DataVm item : sourceList) {
if (item.getTitle().contains(searchTitle)) {
filteredList.add(item);
}
}
return filteredList;
}
public void setSourceList(List<DataVm> sourceList) {
this.sourceList = sourceList;
}
}
And second helper class is basically class item for each row:
public class DataVm {
private int ItemId;
private String Title;
private String Description;
private String Image;
private boolean IsPicked;
public DataVm (int itemId, String title, String description, String image, boolean isPicked) {
ItemId = itemId;
Title = title;
Description = description;
Image = image;
IsPicked = isPicked;
}
public int getItemId() {
return ItemId;
}
public void setItemId(int itemId) {
ItemId = itemId;
}
public String getTitle() {
return Title;
}
public void setTitle(String title) {
Title = title;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
public boolean isPicked() {
return IsPicked;
}
public void setPicked(boolean picked) {
IsPicked = picked;
}
}
Finally, two last classes are Adapter for list, and view holder for it.
Adapter class:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<DataVm> mItemList;
private IClickListenerAddRemove listener;
public RecyclerViewAdapter(List<DataVm> itemList, IClickListenerAddRemove listener) {
mItemList = itemList;
this.listener = listener;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.salad_creation_item_template, parent, false);
return new RecyclerViewHolder(view, listener);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
RecyclerViewHolder holder = (RecyclerViewHolder) viewHolder;
DataVm item = mItemList.get(position);
holder.setTitle(item.getTitle());
holder.setDescription(item.getDescription());
holder.setIsPicked(item.isPicked());
if (item.isPicked())
holder.setButtonDrawable(R.drawable.ic_remove_24dp);
else
holder.setButtonDrawable(R.drawable.ic_add_24dp);
}
#Override
public int getItemCount() {
return mItemList == null ? 0 : mItemList.size();
}
}
And the last one is view holder for list:
public class RecyclerViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView txtTitle;
private TextView txtDescription;
private ImageButton btnChecking;
private WeakReference<IClickListenerAddRemove> listenerRef;
private boolean mIsPicked = false;
public RecyclerViewHolder(View root, IClickListenerAddRemove listener) {
super(root);
listenerRef = new WeakReference<>(listener);
txtTitle = root.findViewById(R.id.txtTitle);
txtDescription = root.findViewById(R.id.txtDescription);
btnChecking = root.findViewById(R.id.btnAction);
btnChecking.setOnClickListener(this);
}
public void setIsPicked(boolean mIsPicked) {
this.mIsPicked = mIsPicked;
}
public void setTitle(CharSequence text) {
txtTitle.setText(text);
}
public void setDescription(CharSequence text) {
txtDescription.setText(text);
}
public void setButtonDrawable(int drawableId) {
btnChecking.setImageResource(drawableId);
}
#Override
public void onClick(View v) {
if (v.getId() == btnChecking.getId()) {
if (!mIsPicked) {
btnChecking.setImageResource(R.drawable.ic_remove_24dp);
mIsPicked = true;
}
else {
btnChecking.setImageResource(R.drawable.ic_add_24dp);
mIsPicked = false;
}
listenerRef.get().onPositionClicked(getAdapterPosition(), mIsPicked);
}
}
}
Structure of this looks like this:
Related
I am doing Search view with RecyclerView every thing work fine like data show in RecyclerView on search data also filter and showing result but when i touch data it give old position means filter position not showing on toast, if we search typing z in search view it show all data start with z but when i click data start with z it show me on toast data which is old means data start with a
I am getting same problem with list there i found solution with ListView Object
list.getItemAtPosition this solve problem the same problem in RecyclerView
here is interface
public interface RecyclerViewClickListener {
public void recyclerViewListClicked(View v, int position);}
this code getting problem
recycleitemclicklistener = new RecyclerViewClickListener() {
#Override
public void recyclerViewListClicked(View v, int position) {
if (positionvalue.equals("CommonCustomer")) {
CommonSetterANDGetter getclick= commonSetterANDGetters.get(position);
Toast.makeText(maincontext, "denm"+ getclick.getValueNameCustomer()+getclick.getIdCustomer(), Toast.LENGTH_SHORT).show();
}
}
};
this is Adaptor
public class SearchAdapter extends
RecyclerView.Adapter<SearchAdapter.ViewHolder> implements Filterable {
private ArrayList<CommonSetterANDGetter> mArrayList;
private ArrayList<CommonSetterANDGetter> mFilteredList;
private String positionvalue = null;
RecyclerViewClickListener itemclicklistener;
Context maincontext;
public SearchAdapter(Context maincontext, ArrayList<CommonSetterANDGetter> arrayList, String positionvalue, RecyclerViewClickListener recycleitemclicklistener) {
this.maincontext = maincontext;
this.mArrayList = arrayList;
this.mFilteredList = arrayList;
this.itemclicklistener = recycleitemclicklistener;
this.positionvalue=positionvalue;
}
#Override
public SearchAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = null;
if(positionvalue.equals( "StockSummary_List")) {
view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.stocksummary_petty, viewGroup, false);
}else if(positionvalue.equals( "CommonCustomer")){
view= LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.customersearch_petty,viewGroup,false);
}
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(SearchAdapter.ViewHolder viewHolder, int i) {
if(positionvalue.equals( "StockSummary_List")) {
viewHolder.itemCodeStock.setText(mFilteredList.get(i).getItemCodeStock());
viewHolder.itemNameStock.setText(mFilteredList.get(i).getItemNameStock());
viewHolder.issuedStock.setText("Iss :" + mFilteredList.get(i).getIssuedStock() + mFilteredList.get(i).getUmoStock());
viewHolder.recievedStock.setText("Rec :" + mFilteredList.get(i).getRecievedStock() + mFilteredList.get(i).getUmoStock());
viewHolder.closingStock.setText("Clo :" + mFilteredList.get(i).getClosingStock() + mFilteredList.get(i).getUmoStock());
// viewHolder.umoStock.setText(mFilteredList.get(i).getUmoStock());
}else if(positionvalue.equals( "CommonCustomer")){
viewHolder.custName_commonCustdetail.setText(mFilteredList.get(i).getValueNameCustomer());
}
}
#Override
public int getItemCount() {
return mFilteredList.size();
}
#Override
public Filter getFilter() {
return new Filter() {
#Override
protected FilterResults performFiltering(CharSequence charSequence) {
String charString = charSequence.toString();
if (charString.isEmpty()) {
mFilteredList = mArrayList;
} else {
ArrayList<CommonSetterANDGetter> filteredList = new ArrayList<>();
for (CommonSetterANDGetter commonsetget : mArrayList) {
if (positionvalue.equals("StockSummary_List")) {
if (commonsetget.getItemCodeStock().toLowerCase().contains(charString) || commonsetget.getItemNameStock().toLowerCase().contains(charString)) {
filteredList.add(commonsetget);
}
}else if(positionvalue.equals( "CommonCustomer")){
if (commonsetget.getValueNameCustomer().toLowerCase().contains(charString)) {
filteredList.add(commonsetget);
}
}
}
mFilteredList = filteredList;
}
FilterResults filterResults = new FilterResults();
filterResults.values = mFilteredList;
return filterResults;
}
#Override
protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
mFilteredList = (ArrayList<CommonSetterANDGetter>) filterResults.values;
notifyDataSetChanged();
}
};
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
TextView itemCodeStock, itemNameStock, issuedStock, recievedStock, closingStock, umoStock;// stock Sum
TextView custName_commonCustdetail;// common detail cust
public ViewHolder(View view) {
super(view);
if(positionvalue.equals( "StockSummary_List")) {
itemCodeStock = (TextView) view.findViewById(R.id.itemcode_stocksum);
itemNameStock = (TextView) view.findViewById(R.id.itemname_stocksum);
issuedStock = (TextView) view.findViewById(R.id.issue_stocksum);
recievedStock = (TextView) view.findViewById(R.id.recieve_stocksum);
closingStock = (TextView) view.findViewById(R.id.closing_stocksum);
}else if(positionvalue.equals( "CommonCustomer")){
custName_commonCustdetail= (TextView) view.findViewById(R.id.commonname_customerdetail);
custName_commonCustdetail.setOnClickListener(this);
}
}
#Override
public void onClick(View v) {
itemclicklistener.recyclerViewListClicked(v, this.getAdapterPosition());
}
}
}
I have list of data in MenuItemsModel(model) class along with image url and two strings fetching from the API. How can I load the image url with Picasso and how to bind the loaded image to recyclerview?
Here is my code
Code for model class
public class MenuItemsModel {
public int image;
public String itemName;
public String itemCost;
public MenuItemsModel(int image, String itemName, String itemCost) {
this.image = image;
this.itemName = itemName;
this.itemCost = itemCost;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public String getItemName() {
return itemName;
}
public void setItemName(String itemName) {
this.itemName = itemName;
}
public String getItemCost() {
return itemCost;
}
public void setItemCost(String itemCost) {
this.itemCost = itemCost;
}
}
Here is my RecyclerAdapter class
public class MenusRecyclearView extends
RecyclerView.Adapter<MenusRecyclearView.RecyclerViewHolder> {
Context context;
List<MenuItemsModel> menuItemsModel;
public MenusRecyclearView(Context context, List<MenuItemsModel> menuItemsModel) {
this.context = context;
this.menuItemsModel = menuItemsModel;
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.menu_items_list, parent, false);
return new RecyclerViewHolder(view, context, menuItemsModel);
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
holder.imageView.setImageResource(menuItemsModel.get(position).getImage());
holder.ItemName.setText(menuItemsModel.get(position).getItemName());
holder.ItemCost.setText(menuItemsModel.get(position).getItemCost());
//Picasso.with(context).load(menuItemsModel.get(position).getImage()).into(holder.imageView);
}
#Override
public int getItemCount() {
return menuItemsModel.size();
}
public class RecyclerViewHolder extends RecyclerView.ViewHolder implements
View.OnClickListener {
public ImageView imageView;
public TextView ItemName, ItemCost;
Context ctx;
List<MenuItemsModel> menuItemsModels;
public RecyclerViewHolder(View view, Context ctx, List<MenuItemsModel> menuItemsModels) {
super(view);
this.ctx = ctx;
this.menuItemsModels = menuItemsModels;
view.setOnClickListener(this);
imageView = view.findViewById(R.id.biriyani_menu_item);
ItemName = view.findViewById(R.id.item_name);
ItemCost = view.findViewById(R.id.item_cost);
}
#Override
public void onClick(View v) {
int position = getAdapterPosition();
MenuItemsModel model = this.menuItemsModels.get(position);
Intent i = new Intent(this.ctx, CategoryDescription.class);
i.putExtra("ImageId", model.getImage());
i.putExtra("ItemName", model.getItemName());
i.putExtra("ItemCost", model.getItemCost());
this.ctx.startActivity(i);
}
}
}
** Here is my MainActivity class **
public class BiryanisActivity extends AppCompatActivity implements
View.OnClickListener, NetworkOperationListener{
RecyclerView recyclerView;
MenusRecyclearView menusRecyclearView;
RecyclerView.LayoutManager layoutManager;
List<MenuItemsModel> menuItemsModel;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.biriyanis_activity);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setDisplayShowHomeEnabled(true);
menuItemsModel = new ArrayList<>();
recyclerView = (RecyclerView) findViewById(R.id.recyclearview_menu);
layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setHasFixedSize(true);
recyclerView.setItemAnimator(new DefaultItemAnimator());
menusRecyclearView = new MenusRecyclearView(this, menuItemsModel);
recyclerView.setAdapter(menusRecyclearView);
HttpAdapter.getMenuItemsList(this,"MenuItemsList");
//prepareData();
}
/* public void prepareData() {
MenuItemsModel data = new MenuItemsModel(R.drawable.item5, "Chicken Dhum
Biriyani", "Rs.240");
menuItemsModel.add(data);
MenuItemsModel data1 = new MenuItemsModel(R.drawable.item2, "Chicken
Chilli Biriyani", "Rs.260");
menuItemsModel.add(data1);
MenuItemsModel data2 = new MenuItemsModel(R.drawable.item3, "Chicken
Tandhuri Biriyani", "Rs.280");
menuItemsModel.add(data2);
MenuItemsModel data3 = new MenuItemsModel(R.drawable.item4, "Chicken
Moghulai Biriyani", "Rs.230");
menuItemsModel.add(data3);
MenuItemsModel data4 = new MenuItemsModel(R.drawable.item1, "Chicken
Special Biriyani", "Rs.220");
menuItemsModel.add(data4);
MenuItemsModel data5 = new MenuItemsModel(R.drawable.item1, "Chicken
Mandi Biriyani", "Rs.210");
menuItemsModel.add(data5);
}*/
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
}
return false;
}
#Override
public void onClick(View view) {
}
#Override
public void operationCompleted(NetworkResponse response) {
if (response.getStatusCode() == 200) {
if (response.getTag().equals("MenuItemsList")) {
try {
JSONObject jsonObjects = new JSONObject(response.getResponseString());
if (jsonObjects.getString("Data").equals("null")) {
Toast.makeText(this, "No Data Found", Toast.LENGTH_SHORT).show();
return;
}
JSONArray jsonArray = jsonObjects.getJSONArray("Data");
for (int j=0; j<jsonArray.length(); j++) {
JSONObject jsonObject = jsonArray.getJSONObject(j);
MenuItemsModel data = new Gson().fromJson(jsonObject.toString(),MenuItemsModel.class);
//Picasso.with(this).load(data.getImage()).into();
Picasso.with(this).load(data.getImage()).into(holder.imageView);
/* int image = data.getImage();
String name = data.getItemName();
String cost = data.getItemCost();
//picaso(image, imageView);*/
menuItemsModel.add(data);
}
MenusRecyclearView menusRecyclearView = new MenusRecyclearView(this,menuItemsModel);
recyclerView.setAdapter(menusRecyclearView);
} catch (JSONException e) {
e.printStackTrace();
}
}
} else {
Toast.makeText(this, "Failed to Connect Server, Please try again later", Toast.LENGTH_SHORT).show();
}
}
public void picaso(String path, ImageView imageView) {
if (!path.equals("")) {
Picasso.with(this).load(path).into(imageView);
}
}
}
Well, you are on the right track. You need to uncomment this line:
//Picasso.with(context).load(menuItemsModel.get(position).getImage()).into(holder.imageView);
And, the .getImage() needs to become your URL. That means, you should store the image url inside MenuItemsModel. Now your image is an int, and should be of a type of String so you can pass the URL to it.
Also see this answer here:
https://stackoverflow.com/a/41157030/5457878
Trying to create a generic adapter for the RecyclerView.
Already explored other solutions:
RecyclerView generic adapter with DataBinding
Add click listener to Generic RecyclerView Adapter
https://github.com/ravirupareliya/Recyclerview-Generic-Adapter/blob/master/app/src/main/java/com/rrr/genericrecyclerview/adapter/RecyclerAdapter.java
However want to implement it in a bit different way.
Here is how my adapter looks like:
public abstract class GenericAdapter<T> extends RecyclerView.Adapter<BaseHolder<T>> {
private OnRecyclerItemClickListener mListener;
private List<T> mItems;
private final LayoutInflater mLayoutInflater;
public GenericAdapter(Context context) {
mLayoutInflater =
(LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mItems = Collections.emptyList();
}
#Override
public BaseHolder<T> onCreateViewHolder(ViewGroup parent, int viewType) {
// assume that viewType is a resource id returned by getItemViewType
// also other solutions are welcome
View view = mLayoutInflater.inflate(viewType, parent, false);
// TODO: how to create the view holder ??
}
#Override
public void onBindViewHolder(BaseHolder<T> holder, int position) {
T item = mItems.get(position);
holder.onBind(item, mListener);
}
#Override
public int getItemCount() {
return mItems != null ? mItems.size() : 0;
}
public void setItems(List<T> items) {
mItems = items;
notifyDataSetChanged();
}
public void setItemClickListener(OnRecyclerItemClickListener listener) {
mListener = listener;
}
}
This is a base view holder from which I want to extend all other holders:
public abstract class BaseHolder<T> extends RecyclerView.ViewHolder {
public BaseHolder(View itemView) {
super(itemView);
}
public abstract void onBind(T item, OnRecyclerItemClickListener listener);
}
The problem is in onCreateViewHolder method.
How do I create the view holder?
Should I somehow implement abstract BaseHolder or should I somehow change the adapter class declaration extends i.e. instead BaseHolder here RecyclerView.Adapter> should be some generic implementation of BaseHolder? I tried > but it doesn't work
Thanks in advance for any piece of advice
P.S. It's been a long time, but if someone is interested,
at the time I solved it and published in a Generic RecyclerView Adapter library.
It finally makes it quite easy to create adapters.
I am still using it in multiple production projects.
EDIT:
So the adapter finally looks like:
public abstract class GenericRecyclerViewAdapter<T, L extends BaseRecyclerListener, VH extends BaseViewHolder<T, L>> extends RecyclerView.Adapter<VH> {
#Override
public abstract VH onCreateViewHolder(ViewGroup parent, int viewType);
// ...
}
Thus, ViewHolder creation is delegated to the adapter implementation, i.e.:
public class SimpleAdapter extends GenericRecyclerViewAdapter<User, OnRecyclerItemClickListener, UserViewHolder> {
// ...
#Override
public UserViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// or return here any specific ViewHolder according to the viewType
return new UserViewHolder(inflate(R.layout.item_user, parent), getListener());
}
}
And the ViewHolder is a:
public abstract class BaseViewHolder<T, L extends BaseRecyclerListener> extends RecyclerView.ViewHolder {
// ...
}
This is what I did in my "Generic Adapter":
You pass the Class of your holder which is corresponding to your current View like this:
public class FooHolder extends BaseHolder<Foo> {
... // your code with the constructor matching super goes here
}
Then in your adapter constructor you add a parameter as follows:
public GenericAdapter(Context context, Class<? extends BaseHolder> holderClass) {
...
this.holderClass = holderClass;
}
Then in your onCreateViewHolder method you can make an instance of that class like this:
#Override
public BaseHolder<T> onCreateViewHolder(ViewGroup parent, int viewType) {
...
viewHolder = (BaseHolder) holderClass.getConstructor(View.class).newInstance(view);
}
If you wants to use single generic adapter which have different-2 layouts items and different models for different screen, you need to try this :
Create a java class adapter "StoreListAdapter.java"
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collection;
/**
* Created by Deepak Sharma on 31/10/17.
*/
public class StoreListAdapter<T> extends RecyclerView.Adapter<StoreListAdapter.ViewHolder> implements Filterable {
private Collection<T> mItems;
private Context context;
private int mLayout;
IClickable iClickable;
private boolean isAnimationAllowed;
private StoreSearchFilter<T> mSearchFilter;
public StoreListAdapter(Context context)
{
this.context = context;
}
public void setData(Collection<T> items, boolean isAnimationAllowed)
{
mItems = items;
this.isAnimationAllowed = isAnimationAllowed;
}
public void setCallback(int layout, IClickable iClickable)
{
this.mLayout = layout;
this.iClickable = iClickable;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(mLayout, viewGroup, false);
iClickable.init(view);
StoreListAdapter.ViewHolder viewHolder = new StoreListAdapter.ViewHolder(view);
view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
// viewHolder.itemView.getLayoutParams().width = width;
viewHolder.itemView.getLayoutParams().height = height+24;
return viewHolder;
}
#Override
public void onBindViewHolder(StoreListAdapter.ViewHolder viewHolder, int i) {
iClickable.execute(viewHolder, mItems.toArray()[i],viewHolder.getAdapterPosition());
if (isAnimationAllowed)
setAnimation(viewHolder.itemView, i);
}
#Override
public int getItemCount() {
return mItems.size()>0?mItems.size():0;
}
#Override
public Filter getFilter() {
if (mSearchFilter == null)
mSearchFilter = new StoreSearchFilter<T>((ArrayList<StoreModel>) mItems, new IFilteredList<T>() {
#Override
public void onListFiltered(ArrayList<T> list) {
setData(list, false);
notifyDataSetChanged();
}
});
return mSearchFilter;
}
public class ViewHolder extends RecyclerView.ViewHolder {
private final TextView mTextView;
//private CheckBox mCheckBox;
ViewHolder(View v) {
super(v);
mTextView = (TextView)v.findViewById(R.id.list_item);
}
}
public interface IClickable<T> {
public void init(View view);
public void execute(StoreListAdapter.ViewHolder holder, T object, int position);
}
/**
* Here is the key method to apply the animation
*/
private void setAnimation(View viewToAnimate, int position)
{
// If the bound view wasn't previously displayed on screen, it's animated
/*if (position > lastPosition)
{*/
Animation animation = AnimationUtils.loadAnimation(context, android.R.anim.slide_in_left);
viewToAnimate.startAnimation(animation);
//lastPosition = position;
/*}*/
}
}
create a store model "StoreModel.java":
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
/**
* Created by Deepak Sharma on 31/10/17.
*/
public class StoreModel implements Parcelable {
private String storeName;
private int storeId;
private String storeAddress;
private String storePhone = "(310)816-2365";
private String storeCity;
private int prizesAvailable;
private double storeLatitude;
private double storeLongitude;
private List<Games> gamesList;
public StoreModel(int id,String sName, String add, String city, int prizes, double lat, double lon, ArrayList<Games> list)
{
this.storeId = id;
this.storeName = sName;
this.storeAddress = add;
this.storeCity = city;
this.prizesAvailable = prizes;
this.storeLatitude = lat;
this.storeLongitude = lon;
this.gamesList = list;
}
public String getStoreName() {
return storeName;
}
public void setStoreName(String storeName) {
this.storeName = storeName;
}
public String getStoreAddress() {
return storeAddress;
}
public void setStoreAddress(String storeAddress) {
this.storeAddress = storeAddress;
}
public String getStoreCity() {
return storeCity;
}
public void setStoreCity(String storeCity) {
this.storeCity = storeCity;
}
public int getPrizesAvailable() {
return prizesAvailable;
}
public void setPrizesAvailable(int prizesAvailable) {
this.prizesAvailable = prizesAvailable;
}
public double getStoreLatitude() {
return storeLatitude;
}
public void setStoreLatitude(double storeLatitude) {
this.storeLatitude = storeLatitude;
}
public double getStoreLongitude() {
return storeLongitude;
}
public void setStoreLongitude(double storeLongitude) {
this.storeLongitude = storeLongitude;
}
public List<Games> getGamesList() {
return gamesList;
}
public void setGamesList(List<Games> gamesList) {
this.gamesList = gamesList;
}
public String getStorePhone() {
return storePhone;
}
public void setStorePhone(String storePhone) {
this.storePhone = storePhone;
}
#Override
public boolean equals(Object obj) {
if (obj == this)
return true; //If objects equal, is OK
if (obj == null)
return false;
if (!(obj instanceof StoreModel))
return false;
if (obj instanceof StoreModel) {
StoreModel store = (StoreModel)obj;
return ((storeId == store.storeId) && (storeName.equalsIgnoreCase(store.storeName)));
// return (storeId == store.storeId) && y == store.y);
}
return false;
}
#Override
public int hashCode() {
return storeId;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.storeName);
dest.writeString(this.storeAddress);
dest.writeString(this.storePhone);
dest.writeString(this.storeCity);
dest.writeInt(this.prizesAvailable);
dest.writeDouble(this.storeLatitude);
dest.writeDouble(this.storeLongitude);
dest.writeList(this.gamesList);
}
protected StoreModel(Parcel in) {
this.storeName = in.readString();
this.storeAddress = in.readString();
this.storePhone = in.readString();
this.storeCity = in.readString();
this.prizesAvailable = in.readInt();
this.storeLatitude = in.readDouble();
this.storeLongitude = in.readDouble();
this.gamesList = new ArrayList<Games>();
in.readList(this.gamesList, Games.class.getClassLoader());
}
public static final Parcelable.Creator<StoreModel> CREATOR = new Parcelable.Creator<StoreModel>() {
#Override
public StoreModel createFromParcel(Parcel source) {
return new StoreModel(source);
}
#Override
public StoreModel[] newArray(int size) {
return new StoreModel[size];
}
};
}
Create a "store_item.xml" :
<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/coordinator_game_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="#+id/store_item_cardview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardBackgroundColor="#android:color/transparent"
card_view:cardElevation="0dp"
android:layout_marginTop="#dimen/dp_five">
<TextView
android:id="#+id/txtStoreName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Store Name"
android:textSize="18sp" />
</android.support.v7.widget.CardView>
</android.support.design.widget.CoordinatorLayout>
Now in you Activity or Fragment class, call this method to set Adapter:
private void setBottomViewAdapter() {
// use this setting to improve performance if you know that changes
// in content do not change the layout size of the RecyclerView
mRecyclerStore.setHasFixedSize(true);
// use a linear layout manager
LinearLayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mRecyclerStore.setLayoutManager(mLayoutManager);
// specify an adapter (see also next example)
mStoreList = new ArrayList<>();
mStoreList.add(new StoreModel(1001, "Von's", "9860 National Blvd., Los Angeles", "Culver City", 12, 28.624035, 77.365541, getGamesList(8)));
mStoreList.add(new StoreModel(1002, "Jack", "1311 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.622665, 77.364082, getGamesList(6)));
mStoreList.add(new StoreModel(1003, "Ian", "1430 S Fairfax Ave., Los Angeles", "Culver City", 8, 28.620899, 77.365258, getGamesList(2)));
mStoreList.add(new StoreModel(1004, "Jessica Alberto", "1372 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.623890, 77.374136, getGamesList(10)));
mStoreList.add(new StoreModel(1005, "Robert", "2545 National Blvd, Los Angeles", "Culver City", 6, 28.631175, 77.375661, getGamesList(4)));
mStoreList.add(new StoreModel(1006, "Clark", "1372 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.627153, 77.381809, getGamesList(11)));
mStoreList.add(new StoreModel(1007, "Jason", "9860 National Blvd., Los Angeles", "Culver City", 12, 28.626569, 77.371963, getGamesList(3)));
mStoreList.add(new StoreModel(1008, "Papon", "1372 Wilshire Blvd., Santa Monica", "Mid City", 10, 28.623155, 77.371677, getGamesList(2)));
mStoreList.add(new StoreModel(1009, "Von's", "2545 National Blvd, Los Angeles", "Culver City", 11, 28.611569, 77.38545, getGamesList(13)));
mStoreList.add(new StoreModel(1010, "Robert Downey Jr.", "1430 S Fairfax Ave., Los Angeles", "Culver City", 8, 28.623127, 77.369113, getGamesList(4)));
mStoreList.add(new StoreModel(1011, "Ben Affleck", "1335 Wilshire Blvd., Santa Monica", "Mid City", 4, 28.62373, 77.39452, getGamesList(12)));
mStoreListAdapter = new StoreListAdapter(getActivity());
boolean isAnimate = false;
mStoreListAdapter.setData(mStoreList, isAnimate);
mStoreListAdapter.setCallback(R.layout.store_item, new StoreListAdapter.IClickable() {
#Override
public void init(View view) {
// Toast.makeText(getActivity(), "Initialized", Toast.LENGTH_SHORT).show();
}
#Override
public void execute(StoreListAdapter.ViewHolder viewHolder, Object object, int position) {
final StoreModel model = (StoreModel) object;
View view = viewHolder.itemView;
StoreListAdapter.ViewHolder holder = viewHolder;
final CoordinatorLayout fabGameview = (CoordinatorLayout) view;
final CardView cardView = (CardView) fabGameview.findViewById(R.id.store_item_cardview);
TextView txtStoreName = (TextView) cardView.findViewById(R.id.txtStoreName);
cardView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean isAddedToBackStack = true;
StoreDetailsAndProductListFragment storeDetailsAndProductListFragment = new StoreDetailsAndProductListFragment();
Bundle bundle = new Bundle();
bundle.putParcelable(ExtrasUtil.STORE, model);
storeDetailsAndProductListFragment.setArguments(bundle);
showOtherFragment(storeDetailsAndProductListFragment, getActivity().getFragmentManager(), isAddedToBackStack);
}
});
}
});
mRecyclerStore.setAdapter(mStoreListAdapter);
}
Create an interface :
import java.util.ArrayList;
/**
* Created by Deepak Sharma on 3/8/2017.
*/
public interface IFilteredList<T> {
public void onListFiltered(ArrayList<T> list);
}
Create a custom Filterable class StoreSearchFilter.java:
import android.widget.Filter;
import java.util.ArrayList;
import java.util.List;
public final class StoreSearchFilter<T> {
// private final Pattern pattern;
private ArrayList<StoreModel> mList;
private IFilteredList<T> callback;
public StoreSearchFilter(final String regex)
{
// pattern = Pattern.compile(regex);
}
public StoreSearchFilter(ArrayList<StoreModel> list, IFilteredList<T> listener)
{
this.mList = list;
this.callback = listener;
}
#Override
protected Filter.FilterResults performFiltering(CharSequence constraint) {
Filter.FilterResults results = new Filter.FilterResults();
if (constraint == null || constraint.length() == 0) {
results.values = mList;
results.count = mList.size();
}
else {
// Some search copnstraint has been passed
// so let's filter accordingly
ArrayList<StoreModel> filteredContacts = new ArrayList<StoreModel>();
if (mList!=null && mList.size()>0)
{
// We'll go through all the contacts and see
// if they contain the supplied string
for (StoreModel model : mList) {
// TODO Here search for the store name match
if (model.getStoreName().toUpperCase().contains(constraint.toString().toUpperCase())) {
// if `contains` == true then add it
// to our filtered list
filteredContacts.add(model);
}
// TODO Here search for the product name match
else {
List<Games> gameList = model.getGamesList();
if (gameList!=null && gameList.size()>0)
{
for (Games game : gameList) {
if (game.getProductName().toUpperCase().contains(constraint.toString().toUpperCase())) {
filteredContacts.add(model);
break;
}
}
}
}
}
}
// Finally set the filtered values and size/count
results.values = filteredContacts;
results.count = filteredContacts.size();
}
// Return our FilterResults object
return results;
}
#Override
protected void publishResults(CharSequence constraint, Filter.FilterResults results) {
callback.onListFiltered((ArrayList<T>) results.values);
}
}
I'm trying to change the icon of a button in my recycler view every time the activity starts based off a boolean value in my custom object. I assume this has to be done within the adapter since not every groups button will have the same background.
Below is the code for my recycler view adapter:
public class RecipeListAdapter extends RecyclerView.Adapter<RecipeListAdapter.ViewHolder>{
private List<Recipe> mRecipeSet;
private Button mAddToGroceriesButton;
public RecipeListAdapter(List<Recipe> recipes){
mRecipeSet = recipes;
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
//This is what will handle what happens when you click a recipe in the recycler view
private TextView mRecipeName;
private TextView mPrepTime;
private TextView mCookTime;
private TextView mServingSize;
private RelativeLayout mRecipeTextSection;
public ViewHolder(View v) {
super(v);
mRecipeName = (TextView) v.findViewById(R.id.recipe_list_recycler_view_recipe_name);
mServingSize = (TextView) v.findViewById(R.id.recipe_list_recycler_view_serving_size);
mPrepTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_prep_time);
mCookTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_cook_time);
mRecipeTextSection = (RelativeLayout) v.findViewById(R.id.recycled_item_section_view);
mRecipeTextSection.setOnClickListener(this);
mAddToGroceriesButton = (Button) v.findViewById(R.id.add_to_grocery_list);
mAddToGroceriesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Recipe recipeToGrocery = mRecipeSet.get(position);
//RecipeDB dbHelper = new RecipeDB(v.getContext());
//dbHelper.addGroceryItem(recipeToGrocery);
if(!recipeToGrocery.isInList()) {
RecipeDB dbHelper = new RecipeDB(v.getContext());
dbHelper.addGroceryItem(recipeToGrocery);
recipeToGrocery.setInList(true);
dbHelper.updateRecipe(recipeToGrocery);
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
Toast.makeText(v.getContext(), recipeToGrocery.getRecipeName() + " added to grocery list.", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(v.getContext(), "That recipe is already in the list.", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onClick(View v){
int position = getAdapterPosition();
Intent i = new Intent(v.getContext(), RecipeTextView.class);
Recipe selectedRecipe = mRecipeSet.get(position);
i.putExtra("view_recipe_key", selectedRecipe);
v.getContext().startActivity(i);
}
}
public void add(int position, Recipe item) {
mRecipeSet.add(position, item);
notifyItemInserted(position);
}
public void remove(Recipe item) {
int position = mRecipeSet.indexOf(item);
mRecipeSet.remove(position);
notifyItemRemoved(position);
}
public RecipeListAdapter(ArrayList<Recipe> myRecipeset) {
mRecipeSet = myRecipeset;
}
// Create new views (invoked by the layout manager)
#Override
public RecipeListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recipe_item_recycled, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Recipe recipe = mRecipeSet.get(position);
String recipeName = recipe.getRecipeName();
String prepTime = "Prep Time: " + String.valueOf(recipe.getPrepTime()) + " minutes";
String cookTime = "Cook Time: " + String.valueOf(recipe.getCookTime()) + " minutes";
String servingSize = "Servings: " + String.valueOf(recipe.getServings());
holder.mRecipeName.setText(recipeName);
//Only display values if they are not null
if(recipe.getServings() != null) {
holder.mServingSize.setText(servingSize);
}
if (recipe.getPrepTime() != null) {
holder.mPrepTime.setText(prepTime);
}
if(recipe.getCookTime() != null) {
holder.mCookTime.setText(cookTime);
}
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
if(mRecipeSet != null) {
return mRecipeSet.size();
}
return 0;
}
}
I know how to change the background of the button when it's clicked with
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
but it's obviously not going to save the state of that button when the activity restarts. I'm just not sure of how to check the boolean value for each group upon activity start up and change the button background accordingly.
I tried using
if(recipe.isInList()){
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
}
in the onBindViewHolder method but it didn't do anything, and I'm pretty sure that wouldn't be the correct place for it anyways. I know the boolean is working properly since I use it in other places and it works fine.
Here's the relevant XML code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/apk/res/android"
android:layout_margin="7dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:id="#+id/recycled_item_section_view"
android:elevation="30dp"
android:background="#drawable/background_border"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Recipe name"
android:textSize="24dp"
android:textColor="#color/black"
android:id="#+id/recipe_list_recycler_view_recipe_name"
android:paddingBottom="3dp"
android:maxWidth="275dip"
android:singleLine="false"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18dp"
android:textColor="#color/black"
android:layout_below="#id/recipe_list_recycler_view_recipe_name"
android:id="#+id/recipe_list_recycler_view_serving_size"
android:paddingBottom="3dp"/>
<Button
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#mipmap/ic_playlist_add_black_24dp"
android:height="36dp"
android:padding="8dp"
android:layout_alignParentRight="true"
android:id="#+id/add_to_grocery_list"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/recipe_list_recycler_view_serving_size"
android:layout_alignParentLeft="true"
android:textSize="18dp"
android:textColor="#color/black"
android:id="#+id/recipe_list_recycler_view_prep_time"
android:paddingBottom="3dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/recipe_list_recycler_view_prep_time"
android:textSize="18dp"
android:textColor="#color/black"
android:layout_alignParentLeft="true"
android:id="#+id/recipe_list_recycler_view_cook_time"/>
</RelativeLayout>
Recipe class:
public class Recipe implements Parcelable {
//These are all of the qualities a recipe contains, we will create an arraylist of this in the activity
private String mRecipeName;
private int mID;
private String mServings;
private String mPrepTime;
private String mCookTime;
private boolean isInList;
private List<String> mIngredients;
private List<String> mDirections;
public Recipe(){
}
public Recipe(int id, String name, String serving, String prep, String cook, List<String>
ingredientsList, List<String> directionsList, boolean inList){
this.mID = id;
this.mRecipeName = name;
this.mServings = serving;
this.mPrepTime = prep;
this.mCookTime = cook;
this.mIngredients = ingredientsList;
this.mDirections = directionsList;
this.isInList = inList;
}
public Recipe(String name, String serving, String prep, String cook, List<String>
ingredientsList, List<String> directionsList, boolean inList){
this.mRecipeName = name;
this.mServings = serving;
this.mPrepTime = prep;
this.mCookTime = cook;
this.mIngredients = ingredientsList;
this.mDirections = directionsList;
this.isInList = inList;
}
public String getRecipeName() {
return mRecipeName;
}
public int getID() {
return mID;
}
public void setID(int id){
mID = id;
}
public String getServings() {
return mServings;
}
public String getPrepTime() {
return mPrepTime;
}
public void setRecipeName(String recipeName) {
mRecipeName = recipeName;
}
public void setServingSize(String servings) {
mServings = servings;
}
public void setPrepTime(String prepTime) {
mPrepTime = prepTime;
}
public void setServings(String servings) {
mServings = servings;
}
public List<String> getIngredients() {
return mIngredients;
}
public List<String> getDirections() {
return mDirections;
}
public String getCookTime() {
return mCookTime;
}
public void setCookTime(String cookTime) {
mCookTime = cookTime;
}
public void setIngredients(List<String> ingredients) {
mIngredients = ingredients;
}
public void setDirections(List<String> directions) {
mDirections = directions;
}
public boolean isInList() {
return isInList;
}
public void setInList(boolean inList) {
isInList = inList;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mRecipeName);
dest.writeInt(this.mID);
dest.writeString(this.mServings);
dest.writeString(this.mPrepTime);
dest.writeString(this.mCookTime);
dest.writeByte(this.isInList ? (byte) 1 : (byte) 0);
dest.writeStringList(this.mIngredients);
dest.writeStringList(this.mDirections);
}
protected Recipe(Parcel in) {
this.mRecipeName = in.readString();
this.mID = in.readInt();
this.mServings = in.readString();
this.mPrepTime = in.readString();
this.mCookTime = in.readString();
this.isInList = in.readByte() != 0;
this.mIngredients = in.createStringArrayList();
this.mDirections = in.createStringArrayList();
}
public static final Creator<Recipe> CREATOR = new Creator<Recipe>() {
#Override
public Recipe createFromParcel(Parcel source) {
return new Recipe(source);
}
#Override
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
}
And main activity class that uses the adapter:
public class RecipeList extends AppCompatActivity{
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private int REQUEST_CODE=1;
private Button mNavigateGroceryButton;
RecipeDB dbHelper = new RecipeDB(this);
List<Recipe> recipes;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recipes = dbHelper.getAllRecipes();
setContentView(R.layout.activity_recipe_list);
mRecyclerView = (RecyclerView) findViewById(R.id.list_recycler_view);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new RecipeListAdapter(recipes);
mRecyclerView.setAdapter(mAdapter);
mNavigateGroceryButton = (Button) findViewById(R.id.navigate_to_groceries_button_list_view);
mNavigateGroceryButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Intent i = new Intent(RecipeList.this, ExpandableListViewActivity.class);
//Log.d("Navigate", "navigate pressed" );
startActivity(i);
}
});
}
#Override
public void onBackPressed() {
}
public boolean onOptionsItemSelected(MenuItem item){
//Handles menu buttons
switch (item.getItemId()){
case R.id.recipe_list_add_recipe_actionbar_button:
//This button creates a new empty Recipe object and passes it to the EditRecipe class
//The Recipe object is passed as a parcelable
Recipe passedRecipe = new Recipe();
Intent i = new Intent(RecipeList.this, EditRecipe.class);
i.putExtra("passed_recipe_key", (Parcelable) passedRecipe);
startActivityForResult(i, REQUEST_CODE);
return true;
default:
Log.d("Name,", "default called");
return super.onOptionsItemSelected(item);
}
}
public void addNewReRecipe(Recipe recipe){
dbHelper.addRecipe(recipe);
recipes = dbHelper.getAllRecipes();
mAdapter = new RecipeListAdapter(recipes);
mRecyclerView.setAdapter(mAdapter);
}
//Makes the menu bar appear as it is in the action_bar_recipe_list_buttons menu layout file
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_bar_recipe_list_buttons, menu);
return true;
}
//This code is called after creating a new recipe. This is only for creating, and not editing.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE){
if(resultCode == Activity.RESULT_OK) {
Recipe createdRecipe = data.getExtras().getParcelable("recipe_key");
addNewReRecipe(createdRecipe);
}
}
}
}
Looks like you need to declare your button at the top of your ViewHolder with your other views. So move the declaration from the top of your adapter:
private Button mAddToGroceriesButton;
Then in your onBindViewHolder method you can get a reference to your button through the holder and set the background:
if(recipe.isInList()) {
holder.mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
}
Try this,
public class RecipeListAdapter extends RecyclerView.Adapter<RecipeListAdapter.ViewHolder>{
private List<Recipe> mRecipeSet;
private Button mAddToGroceriesButton;
public RecipeListAdapter(List<Recipe> recipes){
mRecipeSet = recipes;
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
//This is what will handle what happens when you click a recipe in the recycler view
private TextView mRecipeName;
private TextView mPrepTime;
private TextView mCookTime;
private TextView mServingSize;
private RelativeLayout mRecipeTextSection;
public ViewHolder(View v) {
super(v);
mRecipeName = (TextView) v.findViewById(R.id.recipe_list_recycler_view_recipe_name);
mServingSize = (TextView) v.findViewById(R.id.recipe_list_recycler_view_serving_size);
mPrepTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_prep_time);
mCookTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_cook_time);
mRecipeTextSection = (RelativeLayout) v.findViewById(R.id.recycled_item_section_view);
mAddToGroceriesButton = (Button) v.findViewById(R.id.add_to_grocery_list);
}
}
public void add(int position, Recipe item) {
mRecipeSet.add(position, item);
notifyItemInserted(position);
}
public void remove(Recipe item) {
int position = mRecipeSet.indexOf(item);
mRecipeSet.remove(position);
notifyItemRemoved(position);
}
public RecipeListAdapter(ArrayList<Recipe> myRecipeset) {
mRecipeSet = myRecipeset;
}
// Create new views (invoked by the layout manager)
#Override
public RecipeListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recipe_item_recycled, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Recipe recipe = mRecipeSet.get(position);
String recipeName = recipe.getRecipeName();
String prepTime = "Prep Time: " + String.valueOf(recipe.getPrepTime()) + " minutes";
String cookTime = "Cook Time: " + String.valueOf(recipe.getCookTime()) + " minutes";
String servingSize = "Servings: " + String.valueOf(recipe.getServings());
holder.mRecipeName.setText(recipeName);
//Only display values if they are not null
if(recipe.getServings() != null) {
holder.mServingSize.setText(servingSize);
}
if (recipe.getPrepTime() != null) {
holder.mPrepTime.setText(prepTime);
}
if(recipe.getCookTime() != null) {
holder.mCookTime.setText(cookTime);
}
mRecipeTextSection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Intent i = new Intent(v.getContext(), RecipeTextView.class);
Recipe selectedRecipe = mRecipeSet.get(position);
i.putExtra("view_recipe_key", selectedRecipe);
v.getContext().startActivity(i);
});
Recipe recipeToGrocery = mRecipeSet.get(position);
if(!recipeToGrocery.isInList()) {
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
}
else{
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_26dp);//set another image
}
mAddToGroceriesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Recipe recipeToGrocery = mRecipeSet.get(position);
//RecipeDB dbHelper = new RecipeDB(v.getContext());
//dbHelper.addGroceryItem(recipeToGrocery);
if(!recipeToGrocery.isInList()) {
RecipeDB dbHelper = new RecipeDB(v.getContext());
dbHelper.addGroceryItem(recipeToGrocery);
recipeToGrocery.setInList(true);
dbHelper.updateRecipe(recipeToGrocery);
notifyDataSetChanged();
}
else {
Toast.makeText(v.getContext(), "That recipe is already in the list.", Toast.LENGTH_SHORT).show();
}
}
});
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
if(mRecipeSet != null) {
return mRecipeSet.size();
}
return 0;
}
}
This is my Adapter class:
public class ItemsAdapter extends RecyclerView.Adapter<ItemsAdapter.RecyclerViewHolder> {
ArrayList<Item> arrayList=new ArrayList<>();
public ItemsAdapter(ArrayList<Item> arrayList, Context context) {
this.arrayList = arrayList;
this.context = context;
}
Context context;
public void update(ArrayList<Item> items)
{
this.arrayList=items;
this.notifyDataSetChanged();
}
#Override
public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=LayoutInflater.from(context).inflate(R.layout.displays_searchitems,parent,false);
RecyclerViewHolder recyclerViewHolder=new RecyclerViewHolder(view);
return recyclerViewHolder;
}
#Override
public void onBindViewHolder(RecyclerViewHolder holder, int position) {
Item item=arrayList.get(position);
holder.ets_ean1.setText(item.getItem_ean());
holder.ets_company.setText(item.getItem_company());
holder.ets_name.setText(item.getItem_name());
holder.ets_desc.setText(item.getItem_desc());
holder.ets_brand.setText(item.getItem_brand());
}
#Override
public int getItemCount() {
return arrayList.size();
}
public static class RecyclerViewHolder extends RecyclerView.ViewHolder{
EditText ets_company,ets_name,ets_desc,ets_brand,ets_ean1;
public RecyclerViewHolder(View view) {
super(view);
ets_company= (EditText) view.findViewById(R.id.ets_company);
ets_name=(EditText) view.findViewById(R.id.ets_name);
ets_desc=(EditText) view.findViewById(R.id.ets_desc);
ets_brand=(EditText) view.findViewById(R.id.ets_brand);
ets_ean1=(EditText) view.findViewById(R.id.ets_ean1);
}
}
My POJO class:
public class Item {
private int item_number;
private String item_ean;
private String item_desc;
private String item_name;
private String item_company;
private String item_brand;
public Item(int item_number, String item_ean, String item_desc, String item_name, String item_company, String item_brand) {
this.item_number = item_number;
this.item_ean = item_ean;
this.item_desc = item_desc;
this.item_name = item_name;
this.item_company = item_company;
this.item_brand = item_brand;
}
public Item() {
}
public int getItem_number() {
return item_number;
}
public void setItem_number(int item_number) {
this.item_number = item_number;
}
public String getItem_ean() {
return item_ean;
}
public void setItem_ean(String item_ean) {
this.item_ean = item_ean;
}
public String getItem_desc() {
return item_desc;
}
public void setItem_desc(String item_desc) {
this.item_desc = item_desc;
}
public String getItem_name() {
return item_name;
}
public void setItem_name(String item_name) {
this.item_name = item_name;
}
public String getItem_company() {
return item_company;
}
public void setItem_company(String item_company) {
this.item_company = item_company;
}
public String getItem_brand() {
return item_brand;
}
public void setItem_brand(String item_brand) {
this.item_brand = item_brand;
}
Activity class:
public class Search extends Activity {
TextView textView;
EditText editText,editText1;
ToggleButton toggleButton;
private DBController dbcontroller;
private SQLiteDatabase database;
RecyclerView recyclerView;
RecyclerView.LayoutManager layoutManager;
private static final int CAMERA_PHOTO = 111;
private ImageView ImgPhoto;
private Uri imagaeToUploadUri;
ArrayList<HashMap<String, String>> selected = new ArrayList<>();
ArrayList<HashMap<String, String>> pselected = new ArrayList<>();
private ArrayList<Item> arrayList=new ArrayList<>();
ItemsAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_search);
editText = (EditText) findViewById(R.id.et_sdata);
textView = (TextView) findViewById(R.id.textView);
dbcontroller = new DBController(this);
textView = (TextView) findViewById(R.id.txt_message);
toggleButton = (ToggleButton) findViewById(R.id.tggl_btn);
ImgPhoto = (ImageView) findViewById(R.id.imageView);
editText1 = (EditText) findViewById(R.id.ets_ean1);
recyclerView= (RecyclerView) findViewById(R.id.customList);
adapter=new ItemsAdapter(arrayList,this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
}
#Override
protected void onResume() {
super.onResume();
editText.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 string = s.toString();
if (string.length() > 0 && string.charAt(string.length() - 1) == '\n') {
displayItems();
}
}
#Override
public void afterTextChanged(Editable s) {
}
});
}
public void displayItems() {
String s2 = editText.getText().toString();
ArrayList<HashMap<String, String>> allItems = dbcontroller.searchdata(s2);
//ArrayList<HashMap<String, String>> predicted = dbcontroller.getpdata(s4);
ArrayList<Item> itemList=new ArrayList<Item>();
s2 = s2.replace("\\n", "").replace("\n", "");
long ean_num=Long.parseLong(s2.trim());
Item item=new Item();
if (allItems.size() == 0) {
allItems = dbcontroller.getpdata(s2);
for (HashMap<String, String> map : allItems)
{
long ean_num_pred = Long.parseLong(map.get("EAN"));
selected=pselected;
selected.add(map);
item.setItem_ean(map.get("item_ean"));
item.setItem_company(map.get("item_company"));
item.setItem_name(map.get("item_name"));
item.setItem_brand(map.get("item_brand"));
item.setItem_desc(map.get("item_desc"));
itemList.add(item);
Log.d("Cpredictor","Items are"+item);
boolean isInserted = dbcontroller.insertReport(editText.getText().toString(), "2");
Log.d("coredictor", "the value is " + ean_num);
Log.d("coredictor", "the predicted value is " + ean_num_pred);
textView.setText("(S)"+s2+"(P)"+map.get("item_ean"));
textView.setTextColor(Color.GREEN);
editText.setText("");
if (isInserted = true)
{
Toast.makeText(Search.this, "Data inserted", Toast.LENGTH_LONG).show();
}else{
Toast.makeText(Search.this, "Data not inserted", Toast.LENGTH_LONG).show();
}
toggleButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (((ToggleButton) v).isChecked()) {
boolean isUpdated = dbcontroller.updatePrediction(editText.getText().toString(), "4");
Toast.makeText(getBaseContext(), "Toggle is on" + isUpdated, Toast.LENGTH_LONG).show();
editText.setText("");
} else {
boolean isUpdated = dbcontroller.updatePrediction(editText.getText().toString(), "3");
Toast.makeText(getBaseContext(), "Toggle is off", Toast.LENGTH_LONG).show();
editText.setText("");
}
}
});
}
} else {
for (HashMap<String, String> map : allItems)
{
if (map.get("EAN").equals(s2))
{
item=new Item();
item.setItem_ean(map.get("item_ean"));
item.setItem_company(map.get("item_company"));
item.setItem_name(map.get("item_name"));
item.setItem_brand(map.get("item_brand"));
item.setItem_desc(map.get("item_desc"));
itemList.add(item);
boolean isInserted = dbcontroller.insertReport(editText.getText().toString(), "1");
selected=pselected;
selected.add(map);
textView.setText("ITEM FOUND!!!!!");
textView.setTextColor(Color.BLUE);
editText.setText("");
if (isInserted = true)
Toast.makeText(Search.this, "Data inserted", Toast.LENGTH_LONG).show();
else
Toast.makeText(Search.this, "Data not inserted", Toast.LENGTH_LONG).show();
}
}
}
adapter.update(itemList);
//ListAdapter adapter = new SimpleAdapter(Search.this,selected,R.layout.displays_searchitems, new String[]{"EAN", "COMPANY", "NAME", "DESCRIPTION", "BRAND"}, new int[]{
// R.id.ets_ean1, R.id.ets_company, R.id.ets_name, R.id.ets_desc, R.id.ets_brand});
//tomList.setAdapter(adapter);
}
I'm trying to display the data from the database(sqlite).
The logic is working fine. I've put log and i can see it's showing the perfect data. But i dont know why the data is not displayed in my recyclerview.
Guys i need help.
Replace
adapter.update(itemList);
with
arrayList.clear();
arrayList.addAll(itemList);
adapter.notifyDataSetChanged()
inside displaysItem method.
Granular updates is better than Calling notifyDatasetchanged().Be specific and use notifyitem inserted.
public void addItems(List<T> Items)
{
for(T object:Items)
{
add(object);
}
}
public void add(final T object) {
arrayList.add(object);
notifyItemInserted(getItemCount() - 1);
}
#Override
public int getItemCount() {
return arrayList== null ? 0 : arrayList.size();
}