i have the following code. If the name of the checkbox is in the 'deneme' array that the function takes, I want the checkbox to be checked. but those that don't enter the 'if' are marked strangely. and there are random checked when scrolling up and down
public SubjectRecyclerViewAdapter(ArrayList<Subject> subjects, ArrayList<String> deneme) {
this.subjects = subjects;
this.deneme = deneme;
}
#Override
public void onBindViewHolder(#NonNull SubjectRecyclerViewAdapter.MyViewHolder holder, int position) {
holder.checkBox.setText(subjects.get(position).getCheckBoxSubject());
if (deneme.contains(subjects.get(position).getCheckBoxSubject())) {
holder.checkBox.setChecked(true);
}}
Because the ViewHolders are recycled (meaning they are reused as you scroll) you need to explicitly set the checkbox's state either way (so that it changes whatever previous state the ViewHolder had):
if (deneme.contains(subjects.get(position).getCheckBoxSubject())) {
holder.checkBox.setChecked(true);
} else {
holder.checkBox.setChecked(false);
}
Related
When I click my first second and third checkboxes, it also checks last 3 checkboxes?
this is my adapter:
#Override
public void onBindViewHolder(#NonNull final NewGamePlayerViewHolder holder, int position) {
final NewGamePlayerItem currentItem = mNewGamePlayerList.get(position);
//in some cases, it will prevent unwanted situations
holder.mCheckBox.setOnCheckedChangeListener(null);
//if true, your checkbox will be selected, else unselected
holder.mCheckBox.setChecked(currentItem.isSelected());
holder.mCheckBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
//set your object's last status
currentItem.setSelected(isChecked);
}
});
holder.mName.setText(currentItem.getmText());
}
This is the item:
package com.example.frisbeecaddy;
public class NewGamePlayerItem {
private boolean mCheckBox;
private String mText;
public NewGamePlayerItem(boolean checkBox, String text) {
mCheckBox = checkBox;
mText = text;
}
public boolean getCheckBox() {
return mCheckBox;
}
public String getmText() {
return mText;
}
}
This is copied from here:
CheckBox in RecyclerView keeps on checking different items
but for me isSelected() and setSelected() it says: cannot resolve method...
First, you need to remember what the core meaning of RecyclerView, this sum it all (see RecyclerView glossary of terms):
Recycle (view): A view previously used to display data for a specific adapter position may be placed in a cache for later reuse to display the same type of data again later. This can drastically improve performance by skipping initial layout inflation or construction.
So, your First problem of:
When I click my first second and third checkboxes, it also checks last 3 checkboxes
means that your same RecyclerView item is being reused in another item. To tackle the problem, you need to add mechanism to hold the check state for each item. You could do it either by using a SparseBooleanArray or modifying your object to have a state variable.
The Second problem:
but for me isSelected() and setSelected() it says: cannot resolve method...
is because of the following code:
final NewGamePlayerItem currentItem = mNewGamePlayerList.get(position);
...
//set your object's last status
currentItem.setSelected(isChecked);
where you're trying to call a non-existed method in your NewGamePlayerItem.
You need to modify your object to something like this:
package com.example.frisbeecaddy;
public class NewGamePlayerItem {
private boolean mCheckBox;
private String mText;
private boolean mIsSelected;
public NewGamePlayerItem(boolean checkBox, String text, boolean isSelected) {
mCheckBox = checkBox;
mText = text;
mIsSelected = isSelected;
}
public boolean getCheckBox() {
return mCheckBox;
}
public String getmText() {
return mText;
}
// the added methods here
public boolean isSelected() {
return mIsSelected;
}
public void setSelected(boolean isSelected) {
mIsSelected = isSelected;
}
}
In case any 1 find this problem, I hope this helps some1 in the future. I wanted to share the final solution because I think it helps more than the code I started with and couldn't get any answer which led to this solution.
This was a reference for my solution:
How can I select only one checkbox in Recyclerview and notifydataset changed
I'm only sharing crucial parts of the code, which affect directly to the radio button selection problem.
this was my solution:
public class NewGameCourseAdapter extends RecyclerView.Adapter<NewGameCourseAdapter.NewGameCourseViewHolder> {
private int selectedPosition = -1;// no selection by default
#Override
public void onBindViewHolder(#NonNull final NewGameCourseViewHolder holder, final int position) {
/** This can prevent some unwanted actions in some cases **/
holder.mRadioButton.setOnCheckedChangeListener(null);
holder.mRadioButton.setChecked(selectedPosition == position);
holder.mRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
selectedPosition = holder.getAdapterPosition();
if (selectedPosition == position) {
holder.mRadioButton.setChecked(true);
notifyDataSetChanged();
} else {
holder.mRadioButton.setChecked(false);
notifyDataSetChanged();
}
}
});
I am facing a Firebase RecyclerView problem where I cannot remove unwanted CardViews from my RecyclerViews. In my code I check the city's name and the guide's chosen city to match them. It populates guide's details only if the guide's city matches the picked city, but it also shows empty cardview with default layout.
guideDataRef = FirebaseDatabase.getInstance().getReference().child("Guides");
public void recycler() {
super.onStart();
try {
//Guide RecyclerView
Query guideQuery = guideDataRef.orderByKey();
guideQuery.keepSynced(true);
FirebaseRecyclerOptions guideOptions =
new FirebaseRecyclerOptions.Builder<UserModelClass>().setQuery(guideQuery, UserModelClass.class).build();
guideAdapter = new FirebaseRecyclerAdapter<UserModelClass, guideViewHolder>(guideOptions) {
#Override
protected void onBindViewHolder(#NonNull guideViewHolder holder, final int position, #NonNull final UserModelClass model) {
String pickedcity = model.getPickedCity();
String postname = (String) cityName.getText();
if(pickedcity.equals(postname)) {
final String guide_key= getRef(position).getKey();
holder.setGuideName(model.getName());
holder.setGuideSurname(model.getSurName());
holder.setGuideImage(getApplicationContext(), model.getPhotoURL());
// holder.mView.setVisibility(View.VISIBLE);
//Guide Click listener
holder.mView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent guideHireIntent = new Intent(getApplication(), GuideHireActivity.class);
guideHireIntent.putExtra("guide_id", guide_key);
finish();
startActivity(guideHireIntent);
}
});
}
}
#NonNull
#Override
public guideViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_layout_guides, parent, false);
return new guideViewHolder(view);
}
#Override
public void onError(DatabaseError e){
Toast.makeText(getApplicationContext(), "Error by stopping ", Toast.LENGTH_SHORT).show();
}
#Override
public int getItemCount() {
return super.getItemCount();
}
#Override
public void onDataChanged() {
super.onDataChanged();
notifyDataSetChanged();
}
};
guideAdapter.notifyDataSetChanged();
guideRecyclerView.setAdapter(guideAdapter);
guideAdapter.startListening();
} catch (DatabaseException e) {
Toast.makeText(this, "Error", Toast.LENGTH_SHORT).show();
}
}
enter image description here
enter image description here
I can change the adapter visibility to gone if it does not match with the requirements but the problem is that after making it's visibility gone it is still there holding the place (but invisible - there's still an empty space). How can I avoid populating an item from the recycler view completely, instead of making it invisible if the requirements do not match?
You're not showing what guideDataRef is in your code, so I'm assuming that it's just aDatabaseReference object for everything beneath a \Guides node.
If you're doing that, you're going to get a call for onBindViewHolder for every child at that particular location. This means that you're going to be asked to make a view for every child. You cannot choose whether or not a view will appear for that item.
It looks like you're assuming that your if statement in onBindViewHolder method will skip over those items. But what's actually happening is that you're simply allowing an empty view to occupy that spot in the list.
Instead, you should come up with a query that generates only the items of interest to your list. This means you'll have to tell Firebase to filter for children that meet your criteria.
You can also read the entire contents of the location, manually filter out the items you don't want, and build a list of items you do want. You can then build an custom adapter with that list, and it can then become the input to a ListView or even better to a RecyclerView.
This is not duplicate of 'animateLayoutChanges programmatically'.
I want the default animation effects on my view changes except from the fade out effect on removing the objects. I cannot use disableTransitionType() because it was added in API 16. All I could think of was disabling the android:animateLayoutChanges to false, remove the view and setting it again to true. In my recyclerView I thought of removing the animation by holder.rootView.setLayoutTansition(null). But unfortunately it is giving me NullPointerException.
A part of my code is something like this:
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
SavedMessagePackage current = data.get(position);
final String message = current.message;
holder.message.setText(message);
holder.message.setMaxLines(2);
holder.message.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (holder.button.getVisibility() == View.GONE) {
holder.button.setVisibility(View.VISIBLE);
holder.message.setMaxLines(Integer.MAX_VALUE);
holder.message.setText(message);
}
else if (holder.button.getVisibility() == View.VISIBLE) {
holder.root_view.setLayoutTransition(null); // NullPointerException
holder.button.setVisibility(View.GONE);
holder.message.setMaxLines(2);
holder.root_view.setLayoutTransition(new LayoutTransition());
}
}
});
holder.button.setVisibility(View.GONE);
}
How can I achieve this?
In your case you could have holder or root_view being null, but since holder was accessed successfully before, so root_view is null.
Therefore it's most likely you didn't assign holder.root_view before.
I am making use of recycler view. I have a layout that is highlighted in light red,this layout is included for each item in the recycler view. The light red layout is placed over the background image. I am using setTag method to identify the clicks of the buttons in red layout. That is working properly when i click i get the position. The problem is i want to change the image at specific position.
For example : Consider the heart button. I have set a tag on it like this.
heartButton = findViewById(id);
heartButton.setTag(position);
now i get the position by using the getTag method. But now i want to change the image of the heartButton at the a specific position. Is there something like
heartButton.getTag(position).setImageResouce(drawable);
If not how do i do this then.
use setBackgroundResource(R.drawable.XXX)
http://developer.android.com/reference/android/view/View.html#setBackgroundResource(int)
Proper way to do this is,
You have to keep the state of the heart button stored in the model(POJO) which is passed to custom adapter.
e.g.
class ModelListItem{
public static final int HEART=1,BROKEN_HEART=2;
int heartButtonState;
}
Now in onClick() of heart button, get that object from adapter using position,cosidering you have already figured it out on how to preserve position from heart button
ModelListItem item = (ModelListItem)adapter.getItem(position)
Change the state of heart button;
item.setHeartButtonState(ModelListItem.BROKEN_HEART);
adapter.notifyDatasetChanged();
You already know below explaination but just in case
To work this properly,in your getView methode of adapter you need to put the check on heartButtonState(); and use appropriate image resource.
getView(BOILERPLATE){
BOILERPLATE
switch(item.getheartButtonState()){
case ModelItemList.HEART:
heartbutton.setImageResource(heart_image);
break;
case ModelItemList.BROKEN_HEART:
heartbutton.setImageResource(broken_heart_image);
break;
}
I made a custom click listener and updated the like in the setter getter.But this works only when the view has been moved out of the view (i think it is the scrapeview)
The Setter Getter Class
public class DemoData {
int background;
boolean liked;
public DemoData(int background) {
this.background = background;
}
public int getBackground() {
return background;
}
// public void setBackground(int background) {
// this.background = background;
// }
public boolean isLiked() {
return liked;
}
public void setLiked(boolean liked) {
this.liked = liked;
}
}
The onBindViewHolder function of the recycler view
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
background = (ImageView) holder.view.findViewById(R.id.image);
layout = (LinearLayout) holder.view.findViewById(R.id.layout);
delete = (ImageView) layout.findViewById(R.id.delete);
lock = (ImageView) layout.findViewById(R.id.lock);
delete.setTag("delete_"+position);
lock.setTag("lock_"+position);
if(Constants.demoDatas.get(position).isLiked()){
delete.setImageResource(R.drawable.ic_launcher);
}
else{
delete.setImageResource(android.R.drawable.ic_delete);
}
delete.setOnClickListener(new CustomClickListener(position));
lock.setOnClickListener(new CustomClickListener(position));
}
The custom click listener is as below
public class CustomClickListener implements View.OnClickListener {
int position;
public CustomClickListener(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
String tag = (String) v.getTag();
String identifier[] = tag.split("_");
// this line saves my state in the Setter Getter Class
Constants.demoDatas.get(position).setLiked(true);
}
}