how to select all check boxes in RecyclerView by clicking Button? - android

This code in onclick of the Button in Activity:
if(v.getId()==recomendationSelectAllFriends.getId()){
recomendationAdapter.selectAll(resultEntities.size());
}
This method in Adapter:
public void selectAll(int size){
// what should be written here?
}

public void selectAll(int size){
// what should be written here?
for(DataEntity e: data) { //your list of data in the array
e.isChecked(true)
}
notifyDataSetChanged();
}
where e.isChecked field is bounded to the checkbox of the card.

Add a boolean variable in your model class and name it checked, write getters and setters for that variable.
Now,
In your onBindViewHolder write
if(resultEntities.get(position).isChecked(){
holder.yourCheckBoxName.setChecked(true);
}else{
holder.yourCheckBoxName.setChecked(false);
}
In your function
public void selectAll(){
for(ResultEntity e: resultEntities) {
e.setChecked(true)
}
notifyDataSetChanged();
}

Related

Cannot read country code selected in a spinner Android

I am working on an app in which users have to select a country code, i was successful in creating a spinner for the said purpose as shown in this link:
Creating a spinner for choosing country code
But i am getting problem in reading the value selected in the spinner.
{
String abc = onCountryPickerClick();//abc is always null
}
public String onCountryPickerClick (){
ccp.setOnCountryChangeListener(new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
selected_country_code = ccp.getSelectedCountryCodeWithPlus();
}
});
return selected_country_code;
}
When String abc = onCountryPickerClick(); is being invoked, the selected_country_code value will be assigned to abc.
When your CountryCodePicker.OnCountryChangeListener's onCountrySelected() method is being invoked, the ccp.getSelectedCountryCodeWithPlus();'s value gets assigned to selected_country_code. Since String is immutable, changing selected_country_code's value won't change the value of abc, nor the return selected_country_code; will be invoked.
One of possible solutions would be to change your CountryCodePicker.OnCountryChangeListener anonymous implementation to assign the selected country value to abc e.g.
#Override
public void onCountrySelected() {
selected_country_code = ccp.getSelectedCountryCodeWithPlus();
abc = selected_country_code
}
Callbacks are not synchronous. Unfortunately, you cannot simply do String abc = onCountryPickerClick(); because what you are returning is something that is not yet set. Let's go through your code:
ccp.setOnCountryChangeListener(
new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
selected_country_code = ccp.getSelectedCountryCodeWithPlus();
}
});
The code seems to say that when the country is selected in the spinner, you assign the value of selected_country_code. Assuming this is an action triggered by the user, when you call String abc = onCountryPickerClick();, how can you be sure the user has selected anything? This is the issue. You cannot be sure that the user has already selected the option and returning the value is not enough.
You can solve this in many ways. You can for example keep propagating the callback:
public void onCountryPickerClick(OnCountryChangeListener listener){
ccp.setOnCountryChangeListener(listener);
}
// Anywhere you call this
onCountryPickerClick(new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
// Here do whatever you want with the selected country
}
});
The above approach is not very different than what you have now. There are other options. You could use java observables i.e.:
class CountryCodeObservable extends Observable {
private String value;
public CountryCodeObservable(String value) {
this.value = value;
}
public void setCountryCode(String countryCode) {
value = countryCode;
setChanged();
notifyObservers(value);
}
}
public CountryCodeObservable onCountryPickerClick(){
CountryCodeObservable retValue = new CountryCodeObservable("");
ccp.setOnCountryChangeListener(
new CountryCodePicker.OnCountryChangeListener() {
#Override
public void onCountrySelected() {
retValue.setCountryCode(ccp.getSelectedCountryCodeWithPlus());
}
});
return retValue;
}
// Then when calling this method you can do something like:
CountryCodeObservable observable = onCountryPickerClick();
observable.addObserver((obj, arg) -> {
// arg is the value that changed. You'll probably need to cast it to
// a string
});
The above example lets you add more than one observable. It might be too much for your use case, I just thought it illustrates another approach and also the asynchronicity of this situation.
Again, there are even more ways to solve this, the key is that you can't simply return a string and hope it changes when the user selects anything.

Why deleting several items from recylerView in MVVM does not work in android?

I'm writing a todo app to learn more about android architecture.
I implemented RecyclerView with adapter , which receives data from ViewModel. Now i trying to implement swipe-to-delete with "undo" button in Snackbar.
All works fine, until I'm trying to delete 2 items from RecyclerView at the same time. Only one item is deleted, second appears again. Problem only exists while snackbar not dismissed. I use
Snackbar.Callback.DISMISS_EVENT_ACTION
to handle when user push cancel on snackbar
class FolderFragment
...
adapter = new FolderListAdapter(getContext(), folderViewModel);
folderViewModel.getFolders().observe(this, adapter::setFolders);
...
public void onSwipe() {
Snackbar.make(getView(),
R.string.folder_removed_message, Snackbar.LENGTH_SHORT)
.setAction(R.string.undo, v ->
adapter.undoDelete())
.addCallback(new Snackbar.Callback() {
#Override
public void onDismissed(Snackbar transientBottomBar, int event) {
if (event != Snackbar.Callback.DISMISS_EVENT_ACTION) {
folderViewModel.delete(adapter.getDeletedFolder());
}
}
})
.show();
public class FolderListAdapter extends RecyclerView.Adapter<FolderListAdapter.FolderViewHolder>
...
void setFolders(List<Folder> folders) {
this.folders = folders;
notifyDataSetChanged();
}
public void onItemDismiss(int position) {
mDeletedPosition = position;
mDeletedFolder = folders.get(position);
folders.remove(position);
notifyItemRemoved(position);
}
public void undoDelete() {
folders.add(mDeletedPosition, mDeletedFolder);
notifyItemInserted(mDeletedPosition);
}
...
public class FolderViewModel extends AndroidViewModel
...
public void delete(Folder folder) {
folderRepository.delete(folder);
}
...
See my RecyclerView adapter behavior on link below
behavior
trying to comment lines in adapter which deletes item from list in adapter -not work
logging setList() in adapter - viewmodel not updates LiveData because it work in background, but i dont know how to solve this
project on github

adapter.notifyDataSetChange() doesnt work

I have a recyclerview and it includes several rows.
each row has an imageview(heart shape) for like and dislike and what I need is changing the image of imageview each time by my click.
when I start this activity and my list sets, it works well and the image changes by clicking on imageview, but the problem is when I start another activity and get back to this activity, onclick doesn't work.
It seems my adapter doesn't notify data!
This is my code after clicking on imageview:
public static void afterLikeChanged(Post post) {
if (!post.getPostIsLikedByYou()) {
post.setPostIsLikedByYou(true);
} else {
post.setPostIsLikedByYou(false);
}
mAdapter.notifyDataSetChanged();
}
and on the other side in adapter class:
boolean isliked = post.getPostIsLikedByYou();
if (!isliked) {
holder.imglike.setImageResource(R.drawable.btn_like);
} else {
holder.imglike.setImageResource(R.drawable.btn_liked);
}
any idea guys?!
make interface in adapter for like and dislike click event like below code ..
Note : take boolean value for like or like and make getter setter.
onItemClickListner onItemClickListner;
public interface onItemClickListner {
void onClick(User str);//pass your object types.
}
public void setOnItemClickListner(RecyclerViewAdpater.onItemClickListner onItemClickListner) {
this.onItemClickListner = onItemClickListner;
}
#Override
public void onBindViewHolder(ItemViewHolder holder, int position) {
// below code handle click event on recycler view item.
User data=userlist.get(position);
if (!data.isliked()) {
holder.imglike.setImageResource(R.drawable.btn_like);
} else {
holder.imglike.setImageResource(R.drawable.btn_liked);
}
holder.imageHeart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
onItemClickListner.onClick(data);
}
});
}
then after adapter set into recylcerview call below code..
recyclerViewAdpater.setOnItemClickListner(new RecyclerViewAdpater.onItemClickListner() {
#Override
public void onClick(User str) {
if (str.isLike()){
str.setLike(false);
}
else{
str.setLike(true);
}
recyclerViewAdpater.notifyDataSetChanged();
}
});
You need to update your post list before notify the adapter
Something like this:
public static void afterLikeChanged(int position, Post post) {
if (!post.getPostIsLikedByYou()) {
post.setPostIsLikedByYou(true);
} else {
post.setPostIsLikedByYou(false);
}
// postList is a ArrayList that you passed to your adapter
postList.set(position, post);
mAdapter.notifyDataSetChanged();
}
You can not just call like that. Please try below steps:
Assume your current Activity is A. you will switch to activity named B
Using startActivityForResult(B.class, 0x0) instead of startActivity
Implement this in activity A:
boolean getPostIsLikedByYou = false;// This is the variable you get new value from Activity B
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request we're responding to
if (requestCode == 0x0) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
getPostIsLikedByYou = data.getBoolean("getPostIsLikedByYou");
}
}
}
From Activity B, do this when go back:
Intent resultIntent = new Intent();
enter code here
resultIntent.putBoolean("getPostIsLikedByYou", "your_value_here");
setResult(Activity.RESULT_OK, resultIntent);
Hope this help.
It seems like your code is a bit seperated. Something like this will encapsulate the behaviour. All you want is to change the icon and preserve the state of the posts.
It's important to keep track of what you've saved.
Your adapter class. It's missing a lot of code but something like this.
List<Post> posts; // init this in constructor
public void update(List<Post> posts) {
// do some nullchecking, maybe clone the posts. It's sent as a reference now.
this.posts = posts;
notifyDataSetChanged();
}
#Override
public void onBindViewHolder(final MyViewHolder viewHolder, int position) {
final Post post = posts.get(position);
if (post != null) {
if (post.isLiked()) {
holder.imglike.setImageResource(R.drawable.btn_liked);
} else {
holder.imglike.setImageResource(R.drawable.btn_like); // change name of this
}
}
}
public void afterLikeChanged(Post post) {
post.setIsLiked(!post.isLiked());
notifyDataChanged();
}
class MyViewHolder extends RecyclerView.ViewHolder {
// super, etc...
// this is a lazy way to use it, not safe.
// You should create a listener that sends back the getAdapterPosition()
itemView.setOnClickListener(v -> afterLikeChanged(posts.get(getAdapterPosition())));
}
Now make sure that you're hooking up the adapter to the recyclerview correctly. If it works the first time and not the second time, it seems like you are hooking things up in the wrong places. Use onPause and onResume instead.
Finally, I found the solution!
The problem was I had this line in onResume:
mAdapter = new RecyclerViewAdapterQuestions(this, arrayList);
َAfter removing this line the problem was resolved!
It seems in this section my adapter was resetting with new data, not with my previous array!
Thank you for answering me:)

Android notifyItemRemoved() Wrong Index notified

Good day. I have a small chat app where i want to simply delete the chat item locally.
By debugging around i can reckon that there is something wrong with notifyItemRemoved() as follows :
• I have debugged the returned index from my List and the index was correct for list.
• I have debugged the returned Model Class from the ViewHolder and the returned model class was correct.
• I have debugged my custom equals() method inside my Model and it was comparing correctly returning correct item.
The main complain about my debugging is i dont know why,but the equals() method is being called 2 times...pretty weird though if you would have time please consider this case as well.
The main problem is the notifyItemRemoved() is always removing not the correct item,but always 1 item above the item which must be deleted (in means of deleted i mean deleted from the view as deleting from the list is happening correctly)
So i have no clue what is going on here.
Here is my custom equals() methods
#Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (obj instanceof ChatModel) {
ChatModel chatModel = (ChatModel) obj;
if (chatModel.getMessageId().equals(messageId)) {
return true;
}
}
return false;
}
#Override
public int hashCode() {
return messageId.hashCode();
}
Here is how i insert items into adapter list.
For the list of models->
public void insertChatModelWithItemNotify(List<ChatModel> chatModel, boolean firstPaging) {
if (firstPaging) {
this.chatModelList.addAll(chatModel);
notifyDataSetChanged();
} else {
this.chatModelList.addAll(0, chatModel);
notifyItemRangeInserted(0, chatModel.size());
}
}
For a single model - >
public void insertChatModel(ChatModel chatModel) {
this.chatModelList.add(chatModel);
notifyDataSetChanged();
}
Here is how i remove the item from the list
public void removeItem(ChatModel chatModel) {
int position = this.chatModelList.indexOf(chatModel);
this.chatModelList.remove(chatModel);
notifyItemRemoved(position);
}
Any ideas?
You are probably adding some kind of header to the RecyclerView which makes the object index in your object list different from the View index in the RecyclerView.

How to call a method of RecyclerView adapter in a Fragment

I have a fragment with a recyclerview. Here, I'm using a custom method to update the adapter with new dataset.
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter .ViewHolder>{
.....
public void addNewDataset(ArrayList<Integer> data) {
......
notifyDataSetChanged();
}
}
I have called the method like the following, in my Fragment.
myRecyclerAdapter.addNewDataset(data);
Please help me, Thank you in advance.
Did you try to cast recyclerView adpter than call method like this
((MyRecyclerAdapter)recyclerView.getAdapter()).addNewDataset(data);
Compiler search addNewDataset() method in default adapter
Make public method in adapter.
public void addNewDataset(ArrayList<Integer> data) {
......
notifyDataSetChanged();
}
Now make object of adapter in fragment like:
MyAdapter adapter = new MyAdapter(); //make object of adpater like this
adapter.addNewDartaset(data);
Before calling this addnewDataset please check data object reference is not having null value.
if(data!=null){
myRecyclerAdapter.addNewDataset(data);
}
public class MyRecyclerAdapter extends RecyclerView.Adapter<MyRecyclerAdapter .ViewHolder>{
private ArrayList<Integer> mData;
.....
public void addNewDataset(ArrayList<Integer> data) {
if(mData==null){
mData = new ArrayList<Integer>();
}
//If in case you are passing all new array list of integers
mData = data;
//If you want to add new one data to existing array list
mData.addAll(data);
//Use one condition of code from above on the basis of your requirement.
......
notifyDataSetChanged();
}
}

Categories

Resources