I have a RecyclerView as given in picture below.
I get the food item data from the server and bind them to RecyclerView as above.
Food items are assigned in foodItemList array list which has foodItemTypeList array. In foodItemTypeList array list, values of types and their corresponding prices are stored.
What I want is when the user selects a food type (for example medium), the corresponding unit price is updated.
Here is the FoodItemAdapter class:
public class FoodItemAdapter extends RecyclerView.Adapter<FoodItemAdapter.CustomViewHolder> {
private List<FoodItem> foodItemList;
Context context;
String token;
public class CustomViewHolder extends RecyclerView.ViewHolder {
public TextView food_name, food_unit_price;
Spinner food_item_type;
public ImageView food_item_image;
public Button viewDetail;
public CustomViewHolder(View view) {
super(view);
food_name = (TextView) itemView.findViewById(R.id.food_name);
food_item_type = (Spinner) itemView.findViewById(R.id.food_item_type);
viewDetail = (Button) itemView.findViewById(R.id.viewDetail);
food_unit_price = (TextView) itemView.findViewById(R.id.food_unit_price);
food_item_image = (ImageView) itemView.findViewById(R.id.food_item_image);
}
}
public FoodItemAdapter(Context context, List<FoodItem> foodItemList,String token) {
this.foodItemList = foodItemList;
this.context = context;
this.token = token;
}
#Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.food_items_item, parent, false);
return new CustomViewHolder(itemView);
}
#Override
public void onBindViewHolder(final CustomViewHolder holder, int position) {
FoodItem foodItem = foodItemList.get(position);
holder.food_name.setText(foodItem.getFood_name());
holder.viewDetail.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
}
});
holder.food_unit_price.setText(foodItem.getFood_unit_price()+" AF");
if(foodItem.getFood_item_image()!=null && !foodItem.getFood_item_image().isEmpty()){
Picasso.get()
.load(foodItem.getFood_item_image())
// To fit image into imageView
.resize(50, 50)
.centerCrop()
.into(holder.food_item_image);
} else {
Log.d("Food Item Image:", "Food Item image is either empty or null");
}
List<FoodItemType> foodItemTypeList = new ArrayList<>();
foodItemTypeList = foodItem.getFoodItemTypeList();
ArrayAdapter userAdapter = new ArrayAdapter(context, R.layout.spinner, foodItemTypeList);
holder.food_item_type.setAdapter(userAdapter);
holder.food_item_type.setOnItemSelectedListener(new
AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int
position, long id) {
FoodItemType foodItemType = (FoodItemType) (holder.food_item_type).getSelectedItem();
Toast.makeText(context, "Clicked: " +
foodItemType.getFood_unit_price(), Toast.LENGTH_LONG).show();
FoodItem foodItemNew = new FoodItem(foodItemList.get(holder.getAdapterPosition()).getFood_item_id(),foodItemList.get(holder.getAdapterPosition()).getFood_category_id(),foodItemList.get(holder.getAdapterPosition()).getFood_name(),foodItemList.get(holder.getAdapterPosition()).getFood_item_image(),foodItemList.get(holder.getAdapterPosition()).getFood_item_desc(), foodItemType.getFood_item_type_id(),foodItemType.getFood_item_type_name(),foodItemType.getFood_unit_price(), foodItemList.get(holder.getAdapterPosition()).getFoodItemTypeList());
foodItemList.set(holder.getAdapterPosition(),foodItemNew);
notifyItemChanged(holder.getAdapterPosition());
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
// todo for nothing selected
}
});
}
#Override
public int getItemCount() {
return foodItemList.size();
}
}
A part of my FoodItemsFragment class is as below:
recyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_food_item);
foodItemAdapter = new FoodItemAdapter(getActivity(),foodItemList, token);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(foodItemAdapter);
foodItemAdapter.notifyDataSetChanged();
My problem is: When I scroll RecyclerView, the view is loaded multiple times (a kind of lagging) and when I change the foody type (for example: to medium), nothing happens.
Any kind of help is appreciated.
I would like to suggest you have another field in your FoodItem class, which is selectedFoodType. This will hold the index of the type selected. By default, initialize the value with 0 and when an item is selected from the drop-down list, just update the corresponding FoodItem's selectedFoodType accordingly.
Another thing is, you do not have to create a new FoodItem each time you are changing the type of the FoodItem. You need to have the selectedFoodType only and then call the notifyDataSetChanged().
So the code should look like the following. Inside your onItemSelected function, do the following.
int foodType = foodItemTypeList.get(position);
FoodItem foodItem = foodItemNew.get(holder.getAdapterPosition());
foodItem.setSelectedFoodType = foodType;
notifyDataSetChanged();
Please note that I have not tested this code. Please modify as per your need. Hope that helps!
Related
I'm a bit new to Android development.
I was wondering how I can save state of checkboxes in a RecyclerView. I know there are existing solutions for this, but I have a list of items in another RecyclerView that uses the same set of checkboxes. When you click an item, it should show all checkboxes and check those previously checked checkboxes for that item.
I have seen posts using SharedPreferences to save the state but I have different checkboxes states for different item click in another RecyclerView and I do not know how to save these different states.
This is the Adapter class for the list of checkboxes named CurrentAddonAdapter.java:
public class CurrentAddonAdapter extends RecyclerView.Adapter<CurrentAddonAdapter.ViewHolder17> {
private Context context;
private ArrayList items3,price3;
private List<AddonList> addonlist1;
private OnItemClickListener17 mOnItemClickListener17;
CurrentAddonAdapter(Context context, ArrayList items3, ArrayList price3,List addonlist1,OnItemClickListener17 onItemClickListener17){
this.context = context;
this.items3 = items3;
this.price3 = price3;
this.addonlist1 = addonlist1;
this.mOnItemClickListener17 = onItemClickListener17;
}
#NonNull
#Override
public ViewHolder17 onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(context);
View view = layoutInflater.inflate(R.layout.addoncard,parent,false);
return new ViewHolder17(view,mOnItemClickListener17);
}
private SparseBooleanArray selecteditems = new SparseBooleanArray();
#Override
public void onBindViewHolder(#NonNull final CurrentAddonAdapter.ViewHolder17 holder, int position) {
holder.item1.setText(String.valueOf(items3.get(position)));
holder.price1.setText(String.valueOf(price3.get(position)));
final AddonList currentaddon = addonlist1.get(position);
holder.item1.setChecked(selecteditems.get(position));
holder.item1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(holder.item1.isChecked()){
holder.item1.setChecked(true);
mOnItemClickListener17.onItemCheck(currentaddon);
}
else{
holder.item1.setChecked(false);
mOnItemClickListener17.onItemUncheck(currentaddon);
}
}
});
}
#Override
public int getItemCount() {
return items3.size();
}
public class ViewHolder17 extends RecyclerView.ViewHolder implements View.OnClickListener{
TextView price1;
CheckBox item1;
OnItemClickListener17 onItemClickListener17;
public ViewHolder17(#NonNull View itemView, final OnItemClickListener17 onItemClickListener17) {
super(itemView);
item1 = itemView.findViewById(R.id.addoncheck);
price1 = itemView.findViewById(R.id.priceadd);
this.onItemClickListener17 = onItemClickListener17;
itemView.setOnClickListener(this);
}
#Override
public void onClick(View v) {
onItemClickListener17.onItemClick7(getAdapterPosition());
}
}
public interface OnItemClickListener17{
void onItemClick7(int position);
void onItemCheck(AddonList addonList);
void onItemUncheck(AddonList addonList);
}
}
This is the code for the item click. It shows a dialog box with the list of all checkboxes with CardView elements array named items3 and price3
Cursor viewaddon = db.viewalladdon();
while(viewaddon.moveToNext()){
items3.add(viewaddon.getString(2));
price3.add(viewaddon.getString(3));
addonlist1.add(new AddonList(viewaddon.getString(2)));
}
addrecycler.setHasFixedSize(true);
currentAddonAdapter = new CurrentAddonAdapter(getActivity(),items3,price3,addonlist1,this);
addrecycler.setAdapter(currentAddonAdapter);
addrecycler.setLayoutManager(new LinearLayoutManager(getActivity()));
Please, help. I've been trying to find a solution for weeks and I still can't find one. I just really need this for school.
As I'm new to android, I'm struggling to highlight Recyclerview clicked or current item. I have tried some workarounds but nothing helps. Basically I want to highlight selected item even after it is coming back from respective Fragment. Please check my code and help me to get done. Thanks.
public class ContentaAdapter extends RecyclerView.Adapter<ContentaAdapter.MyViewHolder> {
Context context;
ArrayList<String> ItemTitle;
ArrayList<String> ItemSource;
public ContentaAdapter(Context context, ArrayList<String> ItemTitle, ArrayList<String> ItemSource) {
this.context = context;
this.ItemTitle = ItemTitle;
this.ItemSource = ItemSource;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.home_items_layout, parent, false);
MyViewHolder vh = new MyViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
holder.ItemTitle.setText(ItemTitle.get(position));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Fragment contentdisplay = new ViewContentFragment();
Bundle bundle=new Bundle();
bundle.putStringArrayList("ItemTitle",ItemTitle);
bundle.putStringArrayList("ItemSource",ItemSource);
bundle.putInt("position",position);
bundle.putInt("ItemCounts",ItemTitle.size());
contentdisplay.setArguments(bundle);
((MainActivity)context).replaceFragment(contentdisplay);
}
});
}
#Override
public int getItemCount() {
return ItemTitle.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
TextView ItemTitle;
public MyViewHolder(View itemView) {
super(itemView);
ItemTitle = (TextView) itemView.findViewById(R.id.item_title);
}
}
}
you need to to add isSelected state in to your list item data model and change it onClick.
And when you know state you can change background in ViewHolder
if (isSelected) {
// set selected background here
} else {
// set not selected background here
}
And instead of keeping two lists in adapter you should create one with model ArrayList<DataModel> similar to this:
class DataModel {
String ItemTitle;
String ItemSource;
Boolean isSelected;
}
also you shouldn't pass both list to other fragment, instead take only what you need, for example yourList.get(position);
I have a RecyclerView.Adapter which has some Arrays there.
ArrayList with Strings and ArrayList with Integer. Strings are like url and Integer is the photo.
When the app is open for first time the first item is selected.
I have another method for click which makes another item as selected and this works, but the problem is that the first item stays as selected and so for every image click makes as selected, I want only one item to be selected and take a color.
This is my code.
Adapter of RecyclerView
public class ListViewAdapter extends RecyclerView.Adapter<ListViewAdapter.ViewHolder>{
private int selectedItem;
private ArrayList<Integer> mImages = new ArrayList<>();
private ArrayList<String> mSearchUrl = new ArrayList<>();
private Context mContext;
public ListViewAdapter(ArrayList<Integer> images, ArrayList<String> SearchUrl, Context context) {
mImages = images;
mContext = context;
mSearchUrl = SearchUrl;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.s_engine_item, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull final ViewHolder viewHolder, final int i) {
selectedItem = 0;
if (selectedItem == i) {
viewHolder.image.setBackgroundColor(Color.parseColor("#30000000"));
}
Glide.with(mContext).load(mImages.get(i))
.into(viewHolder.image);
viewHolder.searchUrl.setText(mSearchUrl.get(i));
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.image.setBackgroundColor(Color.parseColor("#30000000"));
selectedItem = i;
}
});
}
#Override
public int getItemCount() {
return mImages.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
ImageView image;
TextView searchUrl;
public ViewHolder(#NonNull View itemView) {
super(itemView);
image = itemView.findViewById(R.id.ivEngine);
searchUrl = itemView.findViewById(R.id.ivEngineText);
}
}
}
And this is the MainActivity.class
public void intSearch() {
mImages.add(R.drawable.s_bing);
mSearchUrl.add("https://www.bing.com/search?q=");
mImages.add(R.drawable.s_google);
mSearchUrl.add("https://www.google.com/search?q=");
mImages.add(R.drawable.s_yahoo);
mSearchUrl.add("www.yahoo.com");
mImages.add(R.drawable.amazon_white256);
mSearchUrl.add("www.amazon.com");
mImages.add(R.drawable.amazon_white256);
mSearchUrl.add("www.amazon.com");
mImages.add(R.drawable.amazon_white256);
mSearchUrl.add("www.amazon.com");
initRecyclerView();
}
private void initRecyclerView() {
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.HORIZONTAL, false);
RecyclerView recyclerView = findViewById(R.id.lvEngines);
recyclerView.setLayoutManager(layoutManager);
ListViewAdapter adapter = new ListViewAdapter(mImages, mSearchUrl, this);
recyclerView.setAdapter(adapter);
}
Initialize your selected item globally
public class ListViewAdapter extends RecyclerView.Adapter<ListViewAdapter.ViewHolder>{
private int selectedItem = 0;
.....
Then inside your onBindViewHolder whenever you click a new Image notify your adapter for changes in the last selected item cell.
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int previousSelectedItem = selectedItem;
selectedItem = i;
notifyItemChanged(previousSelectedItem);
viewHolder.image.setBackgroundColor(Color.parseColor("#30000000"));
}
});
Just remove this line from onBindViewHolder
selectedItem = 0;
and add an else to the background condition, like:
if (selectedItem == i) {
viewHolder.image.setBackgroundColor(Color.parseColor("#30000000"));
}else{
viewHolder.image.setBackgroundColor(“YOUR_DEFAULT_COLOR”);
}
and update the onClick:
viewHolder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selectedItem = i;
notifyDataSetChanged();
}
});
I have Adapter in my project and few fragments where I populate fragments with celebrity names and date of birth as it is given in below image
I will like to call a different url to launch for each item
For First Item
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.stackoverflow.com")));
For Second Item
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.youtube.com")));
and so on
Below is my Adapter Class
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<Model> mDataset;
private ImageLoader mImageLoader;
// 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 static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView nameText;
public TextView phoneText;
public NetworkImageView image;
#SuppressLint("WrongViewCast")
public ViewHolder(View v) {
super(v);
nameText = v.findViewById(R.id.name_text);
phoneText = v.findViewById(R.id.phone_text);
image = v.findViewById(R.id.imgAvatar);
image.setDefaultImageResId(R.mipmap.ic_launcher);
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(v.getContext(),"Position: "+getAdapterPosition(), Toast.LENGTH_SHORT).show();
}
});
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<Model> myDataset, Context mCOntext) {
Log.d("TEST",myDataset.get(0).getName());
mDataset = myDataset;
mImageLoader = MySingleton.getInstance(mCOntext).getImageLoader();
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.card_view, parent, false);
// set the view's size, margins, paddings and layout parameters
ViewHolder vh = new ViewHolder(v);
return vh;
}
public interface ItemClickListener {
void onItemClick(View view, int position);
}
// Replace the contents of a view (invoked by the layout manager)
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
//holder.mTextView.setText(mDataset.get(position).getName());
Log.d("TEST","Printing Names onBindView Holder"+mDataset.get(position).getName());
holder.nameText.setText(mDataset.get(position).getName());
holder.phoneText.setText(mDataset.get(position).getPhone());
holder.image.setImageUrl(mDataset.get(position).getImage(),mImageLoader);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
}
and my Fragment is
public class english extends Fragment implements Response.Listener , Response.ErrorListener {
View view;
RecyclerView mRecyclerView;
private RecyclerView.LayoutManager mLayoutManager;
private Context context;
private List<Model> contactList = new ArrayList<>();
private String url ="https://api.androidhive.info/json/contacts.json";
Button btn;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
view = inflater.inflate(R.layout.home_fragment,container,false);
context = getContext();
mLayoutManager = new GridLayoutManager(context,2);
mRecyclerView = (RecyclerView)view.findViewById(R.id.my_recycler_view);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setHasFixedSize(true);
mRecyclerView.setLayoutManager(mLayoutManager);
getContactList();
return view;
}
private void getContactList(){
Log.d("TEST","Getting Contact list");
Controller.getInstance(context).makeNetworkCalls(Request.Method.GET,url,this,this);
}
#Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Error: " + error.getMessage());
Toast.makeText(context, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
#Override
public void onResponse(Object response) {
Log.d("TEST","Got The response" +response);
if (response == null) {
Toast.makeText(context, "Couldn't fetch the contacts! Pleas try again.", Toast.LENGTH_LONG).show();
return;
}
List<Model> items = new Gson().fromJson(response.toString(), new TypeToken<List<Model>>(){}.getType());
contactList.addAll(items);
MyAdapter rcAdapter = new MyAdapter(contactList,context);
mRecyclerView.setAdapter(rcAdapter);
}
}
Please Help.
its Simple
First Create URL Array
in The Adapter Classs
ArrayList<String> UrlsToTran=new ArrayList<>();
in The Adapter Class Constructor
MyAdapter(Context mContext)
{
//Assing Context
//Assign The Urls
UrlsToTran.add("www.stackoverflow.com");
UrlsToTran.add("www.facebook.com");
//And Add More Values As U need
}
Then Add OnClick Listener
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
//holder.mTextView.setText(mDataset.get(position).getName());
Log.d("TEST","Printing Names onBindView
Holder"+mDataset.get(position).getName());
holder.nameText.setText(mDataset.get(position).getName());
holder.phoneText.setText(mDataset.get(position).getPhone());
holder.image.setImageUrl(mDataset.get(position).getImage(),mImageLoader);
holder.image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v)
{
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(UrlsToTran.get(position).toString())));
}
});
}
First, for every item in your adapter create an OnClickListener like this:
holder.image.setOnClickListener(v->{
});
Now Create an interface between the adapter and the fragment/activity that shows the list
public interface ModelListener {
void onModelClicked(Model model);
}
In your activity/fragment listen to an item click and send the intent
new ModelListener(){
public void onModelClicked(Model model){
startActivity(new Intent(.., model.getUrl()));
}
}
I have created a RecyclerView, and in the Adapter I am hoping to create a ClickListener. I want each item in the RecyclerView to send a unique response after click. In other words, a click is loading a different fragment for each specific RecyclerView item. Right now, the RecyclerView is not responding, as I have logged it and even added a Toast without any luck:
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private ArrayList<LatestPoll> mDataSet;
int lastPosition = -1;
// 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 {
// each data item is just a string in this case
protected TextView pollQuestion;
protected ImageView pollImage;
protected RelativeLayout individualItem;
public ViewHolder(View v) {
super(v);
pollQuestion = (TextView) v.findViewById(R.id.latest_item_question);
pollImage = (ImageView) v.findViewById(R.id.pollThumbNailImage);
individualItem = (RelativeLayout) v.findViewById(R.id.individual_item);
individualItem.setOnClickListener(this);
}
#Override
public void onClick(View v) {
v.getId();
int itemPosition = getLayoutPosition();
String item = String.valueOf(mDataSet.get(itemPosition));
Toast.makeText(getActivity().getApplicationContext(), item, Toast.LENGTH_LONG).show();
Log.v("TESTING", "ITEM CLICKED!");
}
}
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(ArrayList<LatestPoll> myDataset) {
mDataSet = myDataset;
}
// Create new views (invoked by the layout manager)
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.latest_item, parent, false);
// set the view's size, margins, paddings and layout parameters
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
//The OutOfBoundsException is pointing here
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Log.v("ON_BIND", "ON_BINDVIEWHOLDER CALLED");
LatestPoll latestPoll = mDataSet.get(position);
holder.pollQuestion.setText(latestPoll.getQuestion());
Picasso.with(getActivity())
.load(latestPoll.getPollImage())
.fit()
.placeholder(R.drawable.loading_spinnter_white)
.into(holder.pollImage);
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataSet.size();
}
}
private void onLoad() {
if (mFragmentListener != null) {
mFragmentListener.onFragmentLoaded();
}
}
public interface FragmentListener {
void onFragmentLoaded();
}
}
You need to set onclick listener to the parent layout inside the onBindViewHolder .
holder.parentID.setOnClickListener(mRecyclerViewListener);
In your View holder
parentID = iteView.findViewById(R.id.parent);