I have shown a list of apps installed on device in recyclerView(Image Attached), In this, I categorized apps with imageview(you can see red circle in image)
I set both icons in coding, based on condition, Now I want to show toast onclick of item based on imageView i.e. appCategory , means ...If item have imageView of phone, it shows toast "phone" otherwise "playstore"
that previous condition, I used to filter is not applicable here as it uses FOR Loop for whole list.
image for reference - Link
I tried tag and following code but doesn't worked for me
if (Category_Apps.drawable.constantState ==
ContextCompat.getDrawable(applicationContext, R.drawable.ic_phone)!!.constantState)
{
Toast.makeText(applicationContext, "Phone", Toast.LENGTH_SHORT).show()
}
else
{
Toast.makeText(applicationContext, "Play-store", Toast.LENGTH_SHORT).show()
}
I guess you should save the desired Toast's text in recycle view item itself and you can simply show it on icon click.
public class AppListAdapter extends RecyclerView.Adapter<AppListAdapter.CustomViewHolder> {
private Context context;
private List<AppItem> appItemList;
........
public class CustomViewHolder extends RecyclerView.ViewHolder {
ImageView icon;
.....
public CustomViewHolder(#NonNull View itemView) {
super(itemView);
//other code for item setup
icon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, appItemList.get(getAdapterPosition()).getIconText(), Toast.LENGTH_SHORT).show();
}
});
}
}
}
Happy coding !
Related
I have a RecylcerView holding cards with messages, each has a like and a dislike button. When the like button is clicked the user-ID is stored in my database and the user should not be able to like it again. If he clicks it again his action should reset his like. Same should hold true for dislikes.
In my Adapter in onBindViewHolder I check in my database if the user has already clicked the button. If so, I replace the white up-arrow image with a red arrow. I also set a tag to the ImageView by setTag. Where 0 represents the unvoted case and 1 if the like-button was pressed before :
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final String mUID = getUserID();
final String postID = getPostID(position);
final PostViewHolder holder1 = (PostViewHolder) holder;
//REFERENCE WHERE USER IDs ARE STORED WHEN THEY LIKE THE POST
mRefForUID = rootRef.child("likesUIDs").child(postID);
ValueEventListener valueEventListenerForUID = new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
//IF USER HAS LIKED A REFERENCE IS STORED WITH "mUID+"
if (dataSnapshot.hasChild(mUID+"+")){
//SET RED ARROW IF UP IS CLICKED BEFORE AND SETTAG TO 1
holder1.mUp.setTag(1);
holder1.mUp.setImageResource(R.drawable.arrow_up_red);
} if(dataSnapshot.hasChild(mUID+"-")) {
//SAME AS ABOVE FOR THE DISLIKED CASE
//HERE I COULD SET THE TAG TO -1
} else {
//IF USER ID IS NOT KNOWN HE HAS NOT CLICKED
//SO I SET THE TAG TO 0 FOR THIS CASE
holder1.mUp.setTag(0);
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
};
mRefForUID.addListenerForSingleValueEvent(valueEventListenerForUID);
}
In my ViewHolder I define the onClick events of the buttons (in my case these are ImageViews). If the button was clicked before the onClick event should be different, so I distinguish between these states with the help of my previously initialized tag and a switch case algorithm:
public class PostViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener{
public ImageView mUp;
public ImageView mDown;
public PostViewHolder(View itemView, postClickListener listener){
super(itemView);
mUp = mView.findViewById(R.id.arrowUp);
mDown = mView.findViewById(R.id.arrowDown);
mUp.setOnClickListener(this);
mDown.setOnClickListener(this);
}
#Override
public void onClick(View v) {
if (v.getId() == mUp.getId()){
int tag = (int) mUp.getTag();
int position = getAdapterPosition();
switch(tag){
case 0:
//CASE 0 = NOT CLICKED BEFORE
//MAKE A NORMAL LIKE AND SET THE TAG TO 1 FROM HERE
case 1:
//CASE 1 = UPVOTE IS CLICKED BEFORE
//UNLIKE AND SET THE TAG TO 0 HERE
}
}
}
I leave out the case for the down-vote. So the assignment of the correct ImageView does work. When I open the app I get the red upvote button if it has been upvoted before. But the tag is always 0 when I start the app! So the onBindViewHolder does the following correctly holder1.mUp.setImageResource(R.drawable.arrow_up_red);, but does not set the tag holder1.mUp.setTag(1);.
It particularly does not work when opening the app for the first time. When clicking a couple of times I get the correct tags, since they will get set in the ViewHolder.
I hope to find the mistake or even a better solution for my intention.
I want to implement multi select adapter for my recycler view. I m using Mike Penz's FastAdapter for the same.
I am not sure on how to toggle the selected item view color.
Here is the code snippet, attaching a ClickEventHook<SimpleItem> to the card view in the item so onClick() is called when clicked on the card view,
private void setupFastAdapter() {
mFastAdapter = new FastAdapter<>();
// Configure the FastAdapter.
mFastAdapter.withSelectable(true);
mFastAdapter.withMultiSelect(true);
mFastAdapter.withSelectOnLongClick(false);
mFastAdapter.withSelectionListener(new ISelectionListener<SimpleItem>() {
#Override
public void onSelectionChanged(SimpleItem item, boolean selected) {
// Toggle the card and text colors.
if (selected) {
Logger.i("Selected [%s]", item.getText());
} else {
Logger.i("Unselected [%s]", item.getText());
}
}
});
// Click listeners for views inside the item, add an `EventHook` to the `FastAdapter` by
// implementing either a `ClickEventHook`, `LongClickEventHook`, `TouchEventHook`, `CustomEventHook`
mFastAdapter.withEventHook(new ClickEventHook<SimpleItem>() {
private CardView cardView;
private TextView textView;
#Nullable
#Override
public View onBind(#NonNull RecyclerView.ViewHolder viewHolder) {
//return the views on which you want to bind this event
if (viewHolder instanceof SimpleItem.ViewHolder) {
cardView = ((SimpleItem.ViewHolder) viewHolder).mCardView;
textView = ((SimpleItem.ViewHolder) viewHolder).mTextView;
return cardView;
} else {
return null;
}
}
#Override
public void onClick(View v, int position, FastAdapter<SimpleItem> fastAdapter, SimpleItem item) {
//react on the click event
Logger.i("Clicked [%s]", item.getText());
if (cardView.isSelected()) {
cardView.setCardBackgroundColor(getActivity().getResources().getColor(R.color.app_green_dark));
textView.setTextColor(getActivity().getResources().getColor(R.color.app_white));
} else {
cardView.setCardBackgroundColor(getActivity().getResources().getColor(R.color.app_light_blue_50));
textView.setTextColor(getActivity().getResources().getColor(R.color.primary_text));
}
}
});
}
Color of the card view and text color of the text view are not toggling. And I am not sure how it is implemented correctly.
I have observed onSelectionChanged() method is also not called when the card view in the item is clicked.
Can anyone suggest me an approach to toggle the color of the card view and text on selection and deselection?
Thank you in advance,
Mani
I would suggest to use a ColorStateList or a StateListDrawable for setting state specific backgrounds.
Something like this is used in the sample application.
You can see a simple implementation of such a StateListDrawable here:
StateListDrawable states = new StateListDrawable();
ColorDrawable clrActive = new ColorDrawable(selected_color);
states.addState(new int[]{android.R.attr.state_selected}, clrActive);
states.addState(new int[]{}, ContextCompat.getDrawable(ctx, getSelectableBackground(ctx)));
This even supports animation:
//if possible we enable animating across states
if (animate) {
int duration = ctx.getResources().getInteger(android.R.integer.config_shortAnimTime);
states.setEnterFadeDuration(duration);
states.setExitFadeDuration(duration);
}
I have a Recyclerview, im animating a view inside individual list item, but when I scroll the recyclerview the animation is stopping. Its because recyclerview removes the items form its view so when we scroll back it fetches it back! But now i want that animation to keep going as I would stop it only when i get data from server!
All I want is the animation that I start in the individual items inside the recylerview shouldn't stop even if the recyclerview is scrolled and the view is out of focus and comes back to focus! I need to stop the animation in the code when I get the server data! I have the code where to stop the animation and it works if the item is not scrolled off the view!
btn.onClick -- this button is the onClick for the recyclerview list
item 1 btn.startAnimation(anim.xml) -- starting the animation
onSuccess -- server returns success btn.clearAnimation();
but before the onSuccess if we scroll the list the animation is stopped!
Please help!
By inspiring from crymson's answer i have made little easy and useful solution using tag method of View instead setting a boolean in complicated logic of your custom adapter.
#Override
public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) {
super.onViewDetachedFromWindow(holder);
if (holder.getItemViewType() == TYPE_AD)
((ViewHolderForAd) holder).ivStory.setTag(false);
}
public class ViewHolderForAd extends RecyclerView.ViewHolder {
private ImageView ivStory;
TextView tvName;
public ViewHolderForAd(View view) {
super(view);
ivStory = (ImageView) view.findViewById(R.id.ivStoryImage);
tvName = (TextView) view.findViewById(R.id.tvAppName);
view.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int pos = getAdapterPosition();
if (pos < 0) {
pos = (int) v.getTag();
}
customItemClickListener.onItemClicked(v, pos);
}
});
//ivStory.startAnimation(AnimationUtils.loadAnimation(context, R.anim.pulse_story));
ivStory.setTag(false); //Set default tag false to decrease risk of null
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i) {
//...Your code...
if (!(boolean) holder1.ivStory.getTag()) {
holder1.ivStory.setTag(true);
holder1.ivStory.startAnimation(AnimationUtils.loadAnimation(context, R.anim.pulse_story));
}
//...Your code...//
}
You can use setTag(key, object) instead of setTag(object) if you already tagged something(like position) in your imageView.
Hope this helps someone.
Hard to give you a full solution but have you tried saving the animation state inside the ViewHolder that you are using? I'd recommend saving a boolean flag in the ViewHolder class you defined like isAnimating which is initially set to false and in your onBindViewHolder(...) method you can do something like
if (viewHolder.isAnimating) {
// start animation
} else {
// clear animation
}
viewHolder.btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
viewHolder.isAnimating = true;
// start animation
}
});
I am using Gabrielemariotti's Cardslib library to implement card layout in my android application. I am using a custom layout for my cards. Below is the code for creating custom cards:
Card card = new Card(getActivity().getApplicationContext(), R.layout.status_card);
card.setTitle("sample title");
I have three buttons at the bottom of my card (like buttons in Facebook android app). I want to set onClickListener for these buttons. But I am not sure how to do that.
Please help me here.
Thanks,
You have to define your layout.
Then create a Card with this layout, and override the setupInnerViewElements method.
Inside this method you can define your OnClickListener on your buttons, and you can access to all card's values.
public class CustomCard extends Card {
/**
* Constructor with a custom inner layout
*
* #param context
*/
public CustomCard(Context context) {
super(context, R.layout.carddemo_mycard_inner_content);
}
#Override
public void setupInnerViewElements(ViewGroup parent, View view) {
//Retrieve button
Button myButton = (Button) view.findViewById(R.id.myButton);
if (myButton != null) {
myButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), "Click Listener card=" + getId(),
Toast.LENGTH_LONG).show();
}
});
}
}
}
I have an easy solution for this.
So another way to add onClick listeners, which is a bit easier, is through the XML.
In the xml for the button, you add this line:
android:onClick="methodName"
Where 'methodName' is obviously the name of a method. This will call the method whenever the button is clicked. The next step is obvious - just go into your java activity and create the method that you want called, making sure to take the View as a parameter. So you'd have something like this in your activity class:
public void methodName(View view) {
Log.v("appTag","BUTTON WAS PRESSED");
//whatever you want to do here
}
This is a shortcut to creating a whole onClickListener.
Hope that helps. Good luck :)
EDIT:
Remember, you're passing in a view here, so you can get whatever you want off of that view. Since you commented that you need to get the text off of your card, I'll show you how to do that.
Here is your method for this case:
public void methodName(View view) {
Log.v("appTag","BUTTON WAS PRESSED");
TextView textFromCard = view.findViewById(R.id.THE_ID_YOU_GAVE_YOUR_TEXTVIEW_IN_THE_XML);
String textFromTextView = textFromCard.getText().toString();
//do whatever you want with the string here
}
I want to change the background view when it's pressed (its working). My problem is, If i press the other view (not the same one) in the list, i want to set my background to Black of the newly selected view and change the background to White of the previous selected view. Here is my Implementation
for(final TotalPlayers player : this.playerData){
final ArrayList<View> addedPlayerViews1 = getPlayerView(player);
dropPlayersListView.addView(addedPlayerViews1.get(0));
addedPlayerViews1.get(0).setOnClickListener(new OnClickListener() {
boolean highlight = false;
#Override
public void onClick(View v) {
if (!highlight)
{
addedPlayerViews1.get(0).setBackgroundColor(Color.BLACK);
highlight=true;
}
else {
addedPlayerViews1.get(0).setBackgroundColor(Color.WHITE);
highlight=false;
}
}
});
}
}
addedPlayerViews1.get(1).setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
addedPlayerViews1.get(0).setBackgroundColor(Color.WHITE);
highlight=false;
}
});
I assumed that you can get the other view by get(1).
The problem of your code was you only handled the onClick event of your view where you want to change the background. but you also need to handle the onClick of other view too.