I have ImageView inside of an item in a RecyclerView. Every time I click on an item, I want the image to become visible and the previous clicked item's image becomes invisible.
public static class MyHolder extends RecyclerView.ViewHolder {
private ImageView image_view;
private TextView text_view_name;
private TextView text_view_abilities;
private ImageView heart_image_view;
public MyHolder(#NonNull final View itemView, final OnItemClickListener listener) {
super(itemView);
image_view = itemView.findViewById(R.id.image_view);
text_view_name = itemView.findViewById(R.id.text_view_name);
text_view_abilities = itemView.findViewById(R.id.text_view_abilities);
heart_image_view = itemView.findViewById(R.id.heart_image_view);
heart_image_view.setImageResource(R.drawable.heart);
heart_image_view.setVisibility(View.GONE);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
heart_image_view.setVisibility(View.VISIBLE);
}
}
});
}
}
#NonNull
#Override
public MyHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.single_item_layout, viewGroup, false);
MyHolder holder = new MyHolder(v, mlistener);
return holder;
}
#Override
public void onBindViewHolder(#NonNull MyHolder myHolder, int position) {
Item item = myList.get(position);
myHolder.text_view_name.setText(item.getTitle());
stringArray = item.getAbilitiesObj();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < stringArray.size(); i++) {
try {
builder.append(stringArray.get(i));
builder.append(", ");
} catch (NumberFormatException ex) {
ex.printStackTrace();
}
myHolder.text_view_abilities.setText(builder);
}
if (myHolder.image_view != null) {
String photoUrl = item.getImageUrl();
Picasso.with(mContext).load(photoUrl).into(myHolder.image_view);
}
}
In MyHolder class where item.setOnClick, I set the clicked item image visible but then every time I click on another item, the image of the new item becomes visible and the image of the previous item does not get invisible.
You need to have another array of integers in your adapter to keep track of the items which is clicked. At first, initialize the array of integers with all ones.
// Define an array like the following in your adapter
private int[] selectedItems = new int[yourDataList.size()]; // Initialize the array to have the same size as your data list.
Then initialize the array with all ones. Try having a function like this in your adapter.
private void initializeSeledtedItems() {
for(int item : selectedItems) item = 1;
}
Now in your onBindViewHolder, set the visibility of the ImageView in your RecyclerView items based on the value found in the selectedItems array.
if(selectedItems[position] == 1) heart_image_view.setVisibility(View.VISIBLE);
else heart_image_view.setVisibility(View.GONE);
In the onClickListener modify the selectedItems array as such that, only the item selected has the value one and all the others have zeros. Then call notifyDataSetChanged to take your changes into effect.
private void setSelectedItem(int position) {
for(int i = 0; i < selectedItems.length(); i++) {
if(i == position) selectedItems[i] = 1;
else selectedItems[i] = 0;
}
}
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
setSelectedItem(position);
notifyDataSetChanged();
}
}
}
});
Hope that helps!
My code is for setting Visibility on recycler view's item , when you click on recycler views item it set VISIBLE on that particular item and INVISIBLE on other items.
this code works for me for setting visibility on clicked item and hiding previous icon.
initialize
int selecteditem =0;
onBindViewHolder
if(selecteditem==position){
holder.icSelect.setVisibility(View.VISIBLE);
}
else{
holder.icSelect.setVisibility(View.INVISIBLE);
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
selecteditem=position;
holder.icselect.setVisibility(View.VISIBLE);
notifyDataSetChanged();
}
});
i uploaded image for basic idea .
enter image description here
Related
I have a validate button inside each item of a recyclerView in order to change the color to green of the current item. When a new item is added in the recyclerview , I want to set the default background (no background color).
I've tried inside the BindView(position) function so by default when a new item is added in the itemsList, the color of the current element (item 0) is green whether I clicked on validate or not and that's not what I want.
I've also tried in the onBindViewHolder function but it doesnt work.
How can I change the color of this item in this recyclerview and this color remains the same whithout considering the index changing in the List if a new item is added?
I want that each new item of this recyclerview to be in the default color (background color white or no background color) and the item +n to be in the color of the corresponding status (validated = green , reschedulded = grey)
Once the validated button has been clicked I want the item to remains in read only mode.
Here is the code :
The adapter:
private Context context;
private List<RideObject> itemList;
public TestListeAdapter(List<RideObject> itemList, Context context) {
this.itemList = itemList;
this.context = context;
}
#NotNull
#Override
public TestListeAdapter.TestListeViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_testliste, null, false);
RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
layoutView.setLayoutParams(lp);
return new TestListeAdapter.TestListeViewHolders(layoutView);
}
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onBindViewHolder(#NotNull TestListeAdapter.TestListeViewHolders holder, final int position) {
holder.bindView(position);
if (holder.validated){
holder.mCard.setCardBackgroundColor(ContextCompat.getColor(context.getApplicationContext(), R.color.teal_700));
}
the viewholder Class :
class TestListeViewHolders extends RecyclerView.ViewHolder {
//MyClickListener listener;
TextView rideId;
ImageView mCheck;
ImageView mreschedulded;
CardView mCard;
TestListeViewHolders(View itemView) {
super(itemView);
mCheck = itemView.findViewById(R.id.validate);
mreschedulded= itemView.findViewById(R.id.reschedulded);
mCard = itemView.findViewById(R.id.card_view);
}
private void bindView(int pos) {
RideObject item = itemList.get(pos);
mCheck.setOnClickListener(view -> {
item.setRDVHour(timePicker.getHour());
item.setRDVMinute(timePicker.getMinute());
validated = true;
item.setValider(true);
item.confirmDriver();
//if (itemList.size() == 1){
//mCard.setCardBackgroundColor(ContextCompat.getColor(context.getApplicationContext(), R.color.teal_700));
//itemView.setBackgroundColor(ContextCompat.getColor(context.getApplicationContext(),R.color.teal_700));
});
mreschedulded.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
timePicker.setEnabled(true);
itemView.setBackgroundColor(ContextCompat.getColor(context.getApplicationContext(),R.color.grey));
}
});
}
}
In the MainActivity:
resultsTestList.add(0, mCurrentRide);
mTestListAdapter.notifyDataSetChanged()
Ive tried the code in the answer but it doesnt work . Currently, the setbackgroundcolor applies just to the first element of the list. I would want that if the first element (item0) goes to second element (item1) the item keep his color background which is not the case with the given answer code
When binding RecyclerView items, you have to think of it as that you need to change the ViewHolder completely disregarding the previous state.
The view holder should not hold key information like validated.
Whether the view holder stays in the validated state or not should depend on the item it is being bind to.
#RequiresApi(api = Build.VERSION_CODES.M)
#Override
public void onBindViewHolder(#NotNull TestListeAdapter.TestListeViewHolders holder, final int position) {
holder.bindView(position);
}
...
private void bindView(int pos) {
RideObject item = itemList.get(pos);
if (item.validated) {
mCard.setCardBackgroundColor(...R.color.teal_700));
else {
mCard.setCardBackgroundColor(...R.color.grey));
mCheck.setOnClickListener(view -> {
item.setRDVHour(timePicker.getHour());
item.setRDVMinute(timePicker.getMinute());
item.validated = true;
item.setValider(true);
item.confirmDriver();
});
mReschedulded.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
timePicker.setEnabled(true);
itemView.setBackgroundColor(ContextCompat.getColor(context.getApplicationContext(),R.color.grey));
}
});
}
}
I have a RecyclerView who play the recording when certain item is clicked. I want the behave when a user clicks on item1 that specific recording is playing and button View is changed which is working fine.
But at the same time when item1 recording is playing and user click on item2 then item1 row Button come back to its original position.
Below Image show the View when item1(Row 1) is clicked. (This is working fine)
I have also test this to control the View in inBindViewHolder method.But it is not working because whenever I clicked holder object control the View of current selected row only.
Below Code Section is placed in the ViewHolder
mPlayAudio.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View view)
{
Log.d(TAG, "onClick: Present in onClick mPlayAudio");
if (listener != null)
{
final int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION)
{
// This section contain the code to play and stop
the audio
// Using below line I only able to change selected
// row button View not other row Button View
mPlayAudio.setImageResource(R.drawable.play);
}
}
}
});
I have also try this with in onBindViewHolder method but still not working.
Below Code added in onBindViewHolder
holder.mPlayAudio.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view)
{
// This section contain code to play and stop audio
//Using below statement I only able to change the
//visibility of current selected row View not others
holder.mPlayAudio.setImageResource(R.drawable.play);
}
}
So I finally was able to try this out on my own project.
Answer
In BindViewHolder, after you have made an item click, save the value of the position of that item. Then call notifyDataSetChanged inside the click event, which will refresh the adapter. Now it obtain your result, inside BindViewHolder have an if statement checking if that value should be set accordingly (or invisible), otherwise display as visible.
Example Code
public class SelectorAdapter extends RecyclerView.Adapter<SelectorAdapter.ItemHolder> implements View.OnClickListener {
private List itemList;
private int selectedKey;
public SelectorAdapter(List list) {
itemList = list;
}
#Override
public void onClick(View v) {
}
/* ViewHolder for each item */
class ItemHolder extends RecyclerView.ViewHolder {
//title
#BindView(R.id.selector_title)
TextView title;
#BindView(R.id.selector_layout)
LinearLayout selector;
ItemHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
#Override
public ItemHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_layout_selector, parent, false);
return new ItemHolder(itemView);
}
#Override
public void onBindViewHolder(ItemHolder holder, int position) {
String title = (String) itemList.get(position);
holder.title.setText(title);
if (position != selectedKey) {
holder.title.setBackgroundResource(R.drawable.selector);
} else {
holder.title.setBackgroundResource(R.drawable.selector_selected);
}
holder.itemView.setOnClickListener(v -> {
Timber.e("selected item: %s", position);
selectedKey = position;
notifyDataSetChanged();
});
}
#Override
public int getItemCount() {
Timber.e("itemCount: %s", itemList.size());
return itemList.size();
}
}
Here is my own project where when I select an item, it changes the background resource to selected, and then the rest are returned to the default state.
Here I clicked on the item to change item background and color. I've stored the clicked item value in the database and change the layout color and text color and recreating the adapter and showing the list again while refreshing.
But layout colors not changed when I get its position. Please show the right path to handle the set of background item color always.
public class LoadVehicleTypeAdapter extends RecyclerView.Adapter<LoadVehicleTypeAdapter.CarTypesHolder> {
private List<TaxiTypeResponse.Message> CarTypesModelsList;
private Context mContext;
VehicleTypeView vehicleTypeView;
int I = -1;
int idd = 0;
int II = 0;
Activity activity;
GoogleMap map;
List<VehicleClick> list;
private SparseBooleanArray selectedItems;
public class CarTypesHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public CustomTextView mCarType;
public CircleImageView mCarTypeImage;
LinearLayout llRoot;
CardView cardView;
setOnitemclick listener;
public void setOnItemClickListner(setOnitemclick listener) {
this.listener = listener;
}
public CarTypesHolder(View view) {
super(view);
mCarType = (CustomTextView) view.findViewById(R.id.frag_cartypes_inflated_name);
mCarTypeImage = (CircleImageView) view.findViewById(R.id.frag_cartype_inflated_frameImage);
llRoot = (LinearLayout) view.findViewById(R.id.root1);
selectedItems = new SparseBooleanArray();
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
listener.ImageClick(v, getAdapterPosition());
}
}
public LoadVehicleTypeAdapter(Context context, List<TaxiTypeResponse.Message> CarTypesModelsList, VehicleTypeView vehicleTypeView, Activity activity, GoogleMap map, List<VehicleClick> lists) {
this.CarTypesModelsList = CarTypesModelsList;
mContext = context;
this.vehicleTypeView = vehicleTypeView;
this.activity = activity;
this.map = map;
this.list = lists;
}
#Override
public CarTypesHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.frag_cartype_inflated_view, parent, false);
return new CarTypesHolder(itemView);
}
#SuppressLint("ResourceType")
#Override
public void onBindViewHolder(final CarTypesHolder holder, int position) {
if (list.size() != 0) {
II = Integer.parseInt(list.get(0).RideId);
//setSelection(Integer.parseInt(list.get(0).RideId));
}
if (II == position) {
holder.llRoot.setBackgroundColor(Color.parseColor("#999999"));
holder.mCarType.setTextColor(Color.parseColor("#FFFFFF"));
} else {
holder.llRoot.setBackgroundColor(Color.parseColor("#f3f3f3"));
holder.mCarType.setTextColor(Color.parseColor("#2196F3"));
}
SharedPreferences sharedPreferences = activity.getSharedPreferences("mSelected", Context.MODE_PRIVATE);
TaxiTypeResponse.Message carTypesModel = CarTypesModelsList.get(position);
holder.mCarType.setText(carTypesModel.getName());
holder.mCarTypeImage.setBackgroundResource(R.drawable.wait);
int color = Color.parseColor(PreferenceHandler.readString(mContext, PreferenceHandler.SECONDRY_COLOR, "#006fb6"));
holder.mCarType.setTextColor(color);
holder.setOnItemClickListner(new setOnitemclick() {
#Override
public void ImageClick(View v, int position1) {
I = position1;
notifyDataSetChanged();
try {
if (list.size() != 0) {
VehicleTypeFragment.myAppRoomDataBase.userDao().delete();
list.clear();
}
VehicleClick vehicleClick = new VehicleClick();
vehicleClick.setRideId(String.valueOf(position1));
VehicleTypeFragment.myAppRoomDataBase.userDao().insert(vehicleClick);
list.add(vehicleClick);
} catch (Exception e) {
}
}
});
if (I == position) {
holder.llRoot.setBackgroundColor(Color.parseColor("#999999"));
holder.mCarType.setTextColor(Color.parseColor("#ffffff"));
Animation bounce = AnimationUtils.loadAnimation(mContext, R.anim.bounce);
holder.llRoot.startAnimation(bounce);
} else {
holder.llRoot.setBackgroundColor(Color.parseColor("#f3f3f3"));
holder.mCarType.setTextColor(Color.parseColor("#2196F3"));
}
Picasso.with(mContext).load(carTypesModel.getImagePath()).into(holder.mCarTypeImage);
}
#Override
public long getItemId(int position) {
return CarTypesModelsList.get(position).getID();
}
#Override
public int getItemCount() {
return CarTypesModelsList.size();
}
public void setSelection(int position) {
II = position;
//notifyDataSetChanged();
}
public interface setOnitemclick {
void ImageClick(View view, int position);
}
#Override
public int getItemViewType(int position) {
return position;
}
}
I am not sure what did you mean by refreshing your list. I am guessing that you are recreating the adapter and showing the list again while you are refreshing. Hence the value of I is initialized with -1 each time you are creating the adapter.
You need to do the initialization as follows. Please consider the following is a pseudo code and you need to implement this of your own.
// While declaring your I
// int I = -1;
int I = getTheStoredValueFromDatabase(); // If there is no entry in database, getTheStoredValueFromDatabase function will return -1
I hope you get the idea. You might consider doing the same for other stored values.
for keep track record you need to add Boolean variable in TaxiTypeResponse.Message boolean isClick=false; and toggle this in
holder.setOnItemClickListner(new setOnitemclick() {
#Override
public void ImageClick(View v, int position) {
CarTypesModelsList.get(position).isClick=!CarTypesModelsList.get(position).isClick;
notifyDataSetChanged();
}
}
and modify below code as follow
if (CarTypesModelsList.get(position).isClick) {
holder.llRoot.setBackgroundColor(Color.parseColor("#999999"));
holder.mCarType.setTextColor(Color.parseColor("#ffffff"));
Animation bounce = AnimationUtils.loadAnimation(mContext, R.anim.bounce);
holder.llRoot.startAnimation(bounce);
}
else{
holder.llRoot.setBackgroundColor(Color.parseColor("#f3f3f3"));
holder.mCarType.setTextColor(Color.parseColor("#2196F3"));
}
Note: onBindViewHolder() is not a place to implement the click
listeners, but I am just providing you the logic for how to implement
single selection in recyclerView.
Now lets jump to the solution,
simply follow the below tutorial and change the variable, fields, and background according to your need, you have to implement the below method in onBindViewHolder() method of RecyclerView
First, initialize the lastClickedPosition and isclicked
int lastPositionClicked = -1;
boolean isClicked = false;
#Override
public void onBindViewHolder(#NonNull final MyViewHolder holder, final int position) {
holder.YOUR_VIEW.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// store the position which you have just clicked and you will change the background of this clicked view
lastPositionClicked = position;
isClicked = true;
// need to refresh the adapter
SlabAdapter.this.notifyDataSetChanged();
}
});
// only change the background of last clicked item
if (isClicked && position == lastPositionClicked) {
// change clicked view background color
} else {
// otherwise set the default color for all positions
}
}
let me know if this works.
on BindViewHolder method you'll use this code and set I=0 on globally
#SuppressLint("ResourceType")
#Override
public void onBindViewHolder(final CarTypesHolder holder, int position) {
SharedPreferences sharedPreferences = activity.getSharedPreferences("mSelected", Context.MODE_PRIVATE);
TaxiTypeResponse.Message carTypesModel = CarTypesModelsList.get(position);
holder.mCarType.setText(carTypesModel.getName());
holder.mCarTypeImage.setBackgroundResource(R.drawable.wait);
int color = Color.parseColor(PreferenceHandler.readString(mContext, PreferenceHandler.SECONDRY_COLOR, "#006fb6"));
holder.mCarType.setTextColor(color);
holder.setOnItemClickListner(new setOnitemclick() {
#Override
public void ImageClick(View v, int position1) {
I = position1;
notifyDataSetChanged();
try {
if (list.size() != 0) {
VehicleTypeFragment.myAppRoomDataBase.userDao().delete();
list.clear();
}
VehicleClick vehicleClick = new VehicleClick();
vehicleClick.setRideId(String.valueOf(position1));
VehicleTypeFragment.myAppRoomDataBase.userDao().insert(vehicleClick);
list.add(vehicleClick);
} catch (Exception e) {
}
}
});
if (I == position) {
holder.llRoot.setBackgroundColor(Color.parseColor("#999999"));
holder.mCarType.setTextColor(Color.parseColor("#ffffff"));
Animation bounce = AnimationUtils.loadAnimation(mContext, R.anim.bounce);
holder.llRoot.startAnimation(bounce);
} else {
holder.llRoot.setBackgroundColor(Color.parseColor("#f3f3f3"));
holder.mCarType.setTextColor(Color.parseColor("#2196F3"));
}
Picasso.with(mContext).load(carTypesModel.getImagePath()).into(holder.mCarTypeImage);
}
I have a ListView which implements a custom adapter that contains a few TextViews and two Buttons.
Now when i try to add an item to that ListView, if it is already in the list i want to change the text of its row's TextView (Quantity) and make it + 1. But i can't quite figure out how to interact with that particular TextView.
Adapter code:
public class ItemAdapter extends ArrayAdapter<Item> {
public ItemAdapter(#NonNull Context context) {
super(context, R.layout.lay_list_items);
}
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
LayoutInflater li = LayoutInflater.from(getContext());
View v = li.inflate(R.layout.lay_list_items, null);
final Item item = getItem(position);
TextView nom = (TextView)v.findViewById(R.id.txtNom);
TextView description = (TextView)v.findViewById(R.id.txtDescription);
final TextView qty = (TextView)v.findViewById(R.id.txtQty);
Button btnAjouter = (Button)v.findViewById(R.id.btnAjouter);
Button btnRetirer = (Button)v.findViewById(R.id.btnRetirer);
nom.setText(item.nom);
description.setText(item.description);
qty.setText("1");
btnAjouter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int qtyCourante = Integer.parseInt(qty.getText().toString());
int newQty = qtyCourante + 1;
qty.setText(Integer.toString(newQty));
}
});
btnRetirer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int qtyCourante = Integer.parseInt(qty.getText().toString());
int newQty = qtyCourante - 1;
if (newQty > 0)
qty.setText(Integer.toString(newQty));
else
ItemAdapter.super.remove(item);
}
});
return v;
}
You need to save the count, and then use it.
Use ArrayList<Integer> or add one more field int count in your Model Class Item. It is better to add one more field in Item class.
Initialize it as 1 for all items.
And use the code,
qty.setText(String.valueOf(item.getCount()));//declare a method to get count field value, here getCount()
In your button click,
btnAjouter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
item.setCount( item.getCount() + 1 ); //declare a method to set value
notifyDataSetChanged();
}
});
And also
btnRetirer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if ( item.getCount() > 0)
item.setCount( item.getCount() - 1 );
else
ItemAdapter.super.remove(item);
notifyDataSetChanged();
}
});
notifyDataSetChanged(); should be invoked to update your changes.
Since you are using an ArrayAdapter as your base Class, if you want to add a new item, you can just call:
adapter.add(newItem);
adapter.notifyDataSetChanged();
and the adapter will help you handle the new item.
Summary
When a user clicks on the RecyclerView item, I would like to add tags to that image from the information that has been stored in a BaaS [Sashido] (X Co-ordinates, Y Co-ordinates and Tag name). But, the problem I'm having isn't getting the position per-say. I create a toast when the image has been clicked, it shows the correct position corresponding to the view itself. (zero for the beginning, so on and so forth)
But how to update the position once the user clicks on another item in the list, so that the tags that correspond to the position in the array in Sashido, match the position in the RecyclerView, because at the moment the first row in the Sashido class is populating all images with that row's tags.
My assumption was to the pass the position to the getTagInformation() method using getLayoutPosition() so that when objects.get(position) array is called, it'll get the same position for Sashido class but it isn't. I feel the adapter must not be updating correctly after the user has clicked on a new item.
onBindViewHolder:
#Override
public void onBindViewHolder(RecyclerViewHolderPreviousPosts holder, int position) {
holder.bind(previousPostsList.get(position), listener);
}
onBind:
void bind(final PreviousPostsDataModel model, final OnItemClickListener listener) { ...
uploadedImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (count == 0) {
imageid = model.getImageId();
Toast.makeText(App.getContext(), "Image ID: " + imageid, Toast.LENGTH_SHORT).show();
Toast.makeText(App.getContext(), "Position: " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
getTagInformation(getLayoutPosition());
} else {
Log.e("qwert", "" + imageid);
imageContainer.removeAllViews();
imageContainer.addView(uploadedImage);
count = 0;
}
}
});
... }
getTagInformation:
private void getTagInformation(final int position) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("FashionFeed");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
Toast.makeText(context, "" + position, Toast.LENGTH_SHORT).show();
JSONArray tagNamesArray = objects.get(position).getJSONArray("tagName");
JSONArray posXArray = objects.get(position).getJSONArray("tagPointX");
JSONArray posYArray = objects.get(position).getJSONArray("tagPointY");
for (int i = 0; i < tagNamesArray.length(); i++) {
for (int t = 0; t < tagNamesArray.length(); t++) {
tagNames.add(tagNamesArray.optString(t));
tagXPositions.add(posXArray.optString(t));
tagYPositions.add(posYArray.optString(t));
}
for (int o = 0; o < tagNamesArray.length(); o++) {
tag = new TextView(App.getContext());
tag.setX(Float.parseFloat(tagXPositions.get(o)));
tag.setY(Float.parseFloat(tagYPositions.get(o)));
tag.setText(tagNames.get(o));
tag.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tag.setMaxLines(1);
tag.setTextSize(11);
tag.setClickable(true);
tag.setHintTextColor(Color.WHITE);
tag.setTextColor(Color.WHITE);
tag.setBackgroundResource(R.drawable.tags_rounded_corners);
imageContainer.addView(tag);
count = 1;
}
}
} else {
Toast.makeText(context, "" + e.getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
I have also tried
public void getTagInformation(String imageid) {
ParseQuery query = ParseQuery.getQuery("FashionFeed");
query.WhereEqualTo("objectId", imageId);
....
}
with the imageId passed into the method and with also me manually entering an objectId that will match, it'll still only produce the tags that belong to that objectId. it just doesn't seem that this query is going through all of the objects. Just getting the tag information from that one object and then setting all the images with those tags.
if you need me to provide anymore code, I'm more than happy to.
Hi #BIW please follow below link link
In onBindViewHolder, you are adding listener every time, so it returns same object every time as recyclerView ViewHolder pattern uses same object to render recyclerView item in onBindViewHolder. So you need to add when you are creating holder object and set listener to it so that you will get a proper position.
package com.subbu.moviemasti.adapter;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import com.squareup.picasso.Picasso;
import com.subbu.moviemasti.Constants;
import com.subbu.moviemasti.R;
import com.subbu.moviemasti.entities.Movie;
import java.util.List;
import butterknife.Bind;
import butterknife.ButterKnife;
/**
* Created by subrahmanyam on 25-11-2015.
*/
public class MovieAdapter extends RecyclerView.Adapter<MovieAdapter.ViewHolder> {
private final List<Movie> movieList;
private onRecyclerViewItemClickListener mItemClickListener;
public MovieAdapter(List<Movie> movieList) {
this.movieList = movieList;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.grid_item, null);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
final Movie movie = movieList.get(position);
String imageUrl = Constants.MOVIE_POSTER_BASE_URL + movie.getPosterPath();
if (imageUrl != null) {
Picasso.with(holder.posterImage.getContext()).load(imageUrl).
placeholder(R.drawable.img_default).
into(holder.posterImage);
}
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public int getItemCount() {
return movieList.size();
}
public void setOnItemClickListener(onRecyclerViewItemClickListener mItemClickListener) {
this.mItemClickListener = mItemClickListener;
}
public interface onRecyclerViewItemClickListener {
void onItemClickListener(View view, int position);
}
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
#Bind(R.id.poster)
ImageView posterImage;
public ViewHolder(View view) {
super(view);
ButterKnife.bind(this, view);
view.setOnClickListener(this);
}
#Override
public void onClick(View v) {
mItemClickListener.onItemClickListener(v, getAdapterPosition());
}
}
}
Where we are creating adaper object, from there we need to set listener
like adapter.setOnItemClickListener(this)
class MyActivity extendsActivity implements onRecyclerViewItemClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
manager = new GridLayoutManager(getActivity(), cols);
gridView.setLayoutManager(manager);
gridView.setAdapter(adapter);
adapter.setOnItemClickListener(this);
}
#Override
public void onItemClickListener(View view, int position) {
//Do wantever you want to do
}
}
From ViewHolder class we need to pass position of a recyclerView or we can write code what you need to execute when click on item.
Solved the problem. It wasn't so much that the position was wrong, it was because I was trying to find the tags before I was populating the list of images due to Parse's FindInBackground() callback, it was being populated far too late.
The solution was that I got the JSONArray that contained the Tag names, x-coordindates and y co-ordinates inside the original query that was populating the original list of images. So they would execute simultaneously, then I passed the JSONArray values into the model, which then was passed to the bind() function in the Adapter.
Before, the problem was that the adapter was binding all of the tags onto every image, so when the click event happened on the image it would only add the tag to the imageContainer that was currently selected (in the current position), not any partiular view in any particular position.
This made it so every time the image was clicked it was always finding the first object in the database and assigning it to the selected image. [due to the click event triggering the getTagInformation() function).
With the automation of the getTagInformation method within the Bind function of the ViewHolder, I was able to populate every image with the correct tags and further manipulate it using an onClickListener assigned to the image as shown below:
RecyclerView Holder:
public class RecyclerViewHolderPreviousPosts extends RecyclerView.ViewHolder implements View.OnClickListener {
// View holder for gridview recycler view as we used in listview
public TextView createdAt;
public ImageView uploadedImage;
public TextView caption;
TextView number_of_likes;
TextView number_of_comments;
TextView number_of_tags;
public ImageView comments;
public RelativeLayout imageContainer;
RecyclerViewHolderPreviousPosts(View view) {
super(view);
// Find all views ids
this.createdAt = (TextView) view
.findViewById(R.id.created_date);
this.uploadedImage = (ImageView) view
.findViewById(R.id.image);
this.caption = (TextView) view
.findViewById(R.id.caption_post);
this.number_of_likes = (TextView) view
.findViewById(R.id.number_of_likes);
this.number_of_comments = (TextView) view
.findViewById(R.id.number_of_comments);
this.number_of_tags = (TextView) view
.findViewById(R.id.number_of_tags);
this.comments = (ImageView) view
.findViewById(R.id.comments_image);
this.imageContainer = (RelativeLayout) view
.findViewById(R.id.image_container);
view.setOnClickListener(this);
}
void bind(PreviousPostsDataModel model1, final int position) { ....
model = previousPostsList.get(position);
getTagInformation();
....}
private void getTagInformation() {
for (int o = 0; o < model.getTagSize(); o++) {
tag = new TextView(App.getContext());
tag.setX(Float.parseFloat(model.getXpoints(o)));
tag.setY(Float.parseFloat(model.getYpoints(o)));
Log.e("x", "" + tag.getX());
Log.e("y", "" + tag.getY());
tag.setText(model.getTagName(o));
tag.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
tag.setMaxLines(1);
tag.setTextSize(11);
tag.setClickable(true);
tag.setHintTextColor(Color.WHITE);
tag.setTextColor(Color.WHITE);
tag.setBackgroundResource(R.drawable.tags_rounded_corners);
imageContainer.addView(tag);
tags.add(tag);
}
}
#Override
public void onClick(View v) {
if (count == 0) {
for (int i = 0; i < tags.size(); i++) {
tags.get(i).setVisibility(View.INVISIBLE);
}
count = 1;
}
else {
for (int j = 0; j < tags.size(); j++) {
tags.get(j).setVisibility(View.VISIBLE);
}
count = 0;
}
}
}
Profile Fragment [Original Query] :
private void populateSelectedUserRecyclerView(String objectid) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("FashionFeed");
query.whereEqualTo("uploader", ParseObject.createWithoutData("_User", objectid));
query.orderByDescending("createdAt");
Log.e("get order", "ordered");
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
Log.e("gets done", "gets into done");
if(e == null) {
if (objects.size() > 0) {
Log.e("does it get here", "it got here");
latestPostList = new ArrayList<>();
for (ParseObject j : objects) {
JSONArray tagNamesArray = j.getJSONArray("tagName");
JSONArray posXArray = j.getJSONArray("tagPointX");
JSONArray posYArray = j.getJSONArray("tagPointY");
latestPostList.add(new PreviousPostsDataModel(tagNamesArray, posXArray, posYArray));
}
}
else {
no_follow_display.setVisibility(View.VISIBLE);
no_follow_display.setText(R.string.no_posts);
no_follow_display.bringToFront();
recyclerView.setVisibility(View.GONE);
}
adapter = new RecyclerViewAdapterPreviousPosts(getActivity(), latestPostList, listener);
recyclerView.setAdapter(adapter);// set adapter on recyclerview
adapter.notifyDataSetChanged();
}
else {
Log.e("failed", "failed" + e.getMessage());
}
}
});
}
Thanks for your help.
If I understand correctly question the problem is that ParseQuery don't return objects in the same order. So the assumptions that position of object in Your RecycleView is the same as in ParseDatabase is wrong.
If u want to get TAG from Sashido You should firstly make some relations to Images e.g additional column. Then make query white extra parameter like:
private static final String UNIQ_TAG_ID= "tagId";
query.whereContainedIn(UNIQ_TAG_ID, id);
or get All ParseObjects like u doing now and find that TAG that correspond to Your image, then take info.