How to select 1 radio button at a time (RecyclerView)? - java

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();
}
}
});

Related

Why is this code being executed when the user have not selected anything? [duplicate]

I created an Android application with a Spinner and a TextView. I want to display the selected item from the Spinner's drop down list in the TextView. I implemented the Spinner in the onCreate method so when I'm running the program, it shows a value in the TextView (before selecting an item from the drop down list).
I want to show the value in the TextView only after selecting an item from the drop down list. How do I do this?
Here is my code:
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.TextView;
public class GPACal01Activity extends Activity implements OnItemSelectedListener {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Spinner spinner = (Spinner) findViewById(R.id.noOfSubjects);
// Create an ArrayAdapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(this,R.array.noofsubjects_array, android.R.layout.simple_spinner_item);
// Specify the layout to use when the list of choices appears
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(this);
}
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
TextView textView = (TextView) findViewById(R.id.textView1);
String str = (String) parent.getItemAtPosition(pos);
textView.setText(str);
}
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
}
spinner.setOnItemSelectedListener(this); // Will call onItemSelected() Listener.
So first time handle this with any Integer value
Example:
Initially Take int check = 0;
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
if(++check > 1) {
TextView textView = (TextView) findViewById(R.id.textView1);
String str = (String) parent.getItemAtPosition(pos);
textView.setText(str);
}
}
You can do it with boolean value and also by checking current and previous positions. See here
Just put this line before setting the OnItemSelectedListener
spinner.setSelection(0,false)
This works because setSelection(int, boolean) calls setSelectionInt() internally so that when the listener is added, the item is already selected.
Beware that setSelection(int) won't work, because it calls setNextSelectedPositionInt() internally.
Beginning with API level 3 you can use onUserInteraction() on an Activity with a boolean to determine if the user is interacting with the device.
http://developer.android.com/reference/android/app/Activity.html#onUserInteraction()
#Override
public void onUserInteraction() {
super.onUserInteraction();
userIsInteracting = true;
}
As a field on the Activity I have:
private boolean userIsInteracting;
Finally, my spinner:
mSpinnerView.setOnItemSelectedListener(new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View view, int position, long arg3) {
spinnerAdapter.setmPreviousSelectedIndex(position);
if (userIsInteracting) {
updateGUI();
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
});
As you come and go through the activity the boolean is reset to false. Works like a charm.
This worked for me
Spinner's initialization in Android is problematic sometimes
the above problem was solved by this pattern.
Spinner.setAdapter();
Spinner.setSelected(false); // must
Spinner.setSelection(0,true); //must
Spinner.setonItemSelectedListener(this);
Setting adapter should be first part and onItemSelectedListener(this) will be last when initializing a spinner. By the pattern above my OnItemSelected() is not called during initialization of spinner
haha...I have the same question.
When initViews() just do like this.The sequence is the key, listener is the last. Good Luck !
spinner.setAdapter(adapter);
spinner.setSelection(position);
spinner.setOnItemSelectedListener(listener);
To avoid calling spinner.setOnItemSelectedListener() during initialization
spinner.setSelection(Adapter.NO_SELECTION, true); //Add this line before setting listener
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
My solution:
protected boolean inhibit_spinner = true;
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1,
int pos, long arg3) {
if (inhibit_spinner) {
inhibit_spinner = false;
}else {
if (getDataTask != null) getDataTask.cancel(true);
updateData();
}
}
You can do this by this way:
AdapterView.OnItemSelectedListener listener = new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
//set the text of TextView
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
yourSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
yourSpinner.setOnItemSelectedListener(listener);
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
At first I create a listener and attributed to a variable callback; then i create a second listener anonymous and when this is called at a first time, this change the listener
=]
The user interaction flag can then be set to true in the onTouch method and reset in onItemSelected() once the selection change has been handled. I prefer this solution because the user interaction flag is handled exclusively for the spinner, and not for other views in the activity that may affect the desired behavior.
In code:
Create your listener for the spinner:
public class SpinnerInteractionListener implements AdapterView.OnItemSelectedListener, View.OnTouchListener {
boolean userSelect = false;
#Override
public boolean onTouch(View v, MotionEvent event) {
userSelect = true;
return false;
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (userSelect) {
userSelect = false;
// Your selection handling code here
}
}
}
Add the listener to the spinner as both an OnItemSelectedListener and an OnTouchListener:
SpinnerInteractionListener listener = new SpinnerInteractionListener();
mSpinnerView.setOnTouchListener(listener);
mSpinnerView.setOnItemSelectedListener(listener);
create a boolean field
private boolean inispinner;
inside oncreate of the activity
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
if (!inispinner) {
inispinner = true;
return;
}
//do your work here
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
Similar simple solution that enables multiple spinners is to put the AdapterView in a collection - in the Activities superclass - on first execution of onItemSelected(...) Then check to see if the AdapterView is in the collection before executing it. This enables one set of methods in the superclass and supports multiple AdapterViews and therefor multiple spinners.
Superclass ...
private Collection<AdapterView> AdapterViewCollection = new ArrayList<AdapterView>();
protected boolean firstTimeThrough(AdapterView parent) {
boolean firstTimeThrough = ! AdapterViewCollection.contains(parent);
if (firstTimeThrough) {
AdapterViewCollection.add(parent);
}
return firstTimeThrough;
}
Subclass ...
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
if (! firstTimeThrough(parent)) {
String value = safeString(parent.getItemAtPosition(pos).toString());
String extraMessage = EXTRA_MESSAGE;
Intent sharedPreferencesDisplayIntent = new Intent(SharedPreferencesSelectionActivity.this,SharedPreferencesDisplayActivity.class);
sharedPreferencesDisplayIntent.putExtra(extraMessage,value);
startActivity(sharedPreferencesDisplayIntent);
}
// don't execute the above code if its the first time through
// do to onItemSelected being called during view initialization.
}
Try this
spinner.postDelayed(new Runnable() {
#Override
public void run() {
addListeners();
}
}, 1000);.o
Code
spinner.setOnTouchListener(new View.OnTouchListener() {
#Override public boolean onTouch(View view, MotionEvent motionEvent) { isSpinnerTouch=true; return false; }});
holder.spinner_from.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int slot_position, long l) {
if(isSpinnerTouch)
{
Log.d("spinner_from", "spinner_from");
spinnerItemClickListener.onSpinnerItemClickListener(position, slot_position, AppConstant.FROM_SLOT_ONCLICK_CODE);
}
else {
}
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
});
You could achieve it by setOnTouchListener first then setOnItemSelectedListener in onTouch
#Override
public boolean onTouch(final View view, final MotionEvent event) {
view.setOnItemSelectedListener(this)
return false;
}
This worked for me:
spinner.setSelection(0, false);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
spinner.setOnItemSelectedListener(listener);
}, 500);
Based on Abhi's answer i made this simple listener
class SpinnerListener constructor(private val onItemSelected: (position: Int) -> Unit) : AdapterView.OnItemSelectedListener {
private var selectionCount = 0
override fun onNothingSelected(parent: AdapterView<*>?) {
//no op
}
override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
if (selectionCount++ > 1) {
onItemSelected(position)
}
}
}
You can create custom OnItemSelectedListener like this. I've taken val check=0 and in onItemSelected() method i did check if its count is 0? If 0 means its called during initialization. So simply ignore it.
I've also called separate abstract method called onUserItemSelected() I'll call this method is check > 0. This works perfectly fine for me.
abstract class MySpinnerItemSelectionListener : AdapterView.OnItemSelectedListener {
abstract fun onUserItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long)
private var check = 0
override fun onItemSelected(
parent: AdapterView<*>?,
view: View,
position: Int,
id: Long
) {
if (++check > 1) {
onUserItemSelected(parent, view, position, id)
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {}
}
And then you can set listener like this.
mySpinner.onItemSelectedListener = object : MySpinnerItemSelectionListener() {
override fun onUserItemSelected(
parent: AdapterView<*>?,
view: View?,
position: Int,
id: Long
) {
//your user selection spinner code goes here
}
}
Had the same problem and this works for me:
I have 2 spinners and I update them during init and during interactions with other controls or after getting data from the server.
Here is my template:
public class MyClass extends <Activity/Fragment/Whatever> implements Spinner.OnItemSelectedListener {
private void removeSpinnersListeners() {
spn1.setOnItemSelectedListener(null);
spn2.setOnItemSelectedListener(null);
}
private void setSpinnersListeners() {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
spn1.setOnItemSelectedListener(MyClass.this);
spn2.setOnItemSelectedListener(MyClass.this);
}
}, 1);
}
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Your code here
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
}
When the class is initiating use setSpinnersListeners() instead of directly setting the listener.
The Runnable will prevent the spinner from firing onItemSelected right after the you set their values.
If you need to update the spinner (after a server call etc.) use removeSpinnersListeners() right before your update lines, and setSpinnersListeners() right after the update lines. This will prevent onItemSelected from firing after the update.
For me, Abhi's solution works great up to Api level 27.
But it seems that from Api level 28 and upwards, onItemSelected() is not called when listener is set, which means onItemSelected() is never called.
Therefore, I added a short if-statement to check Api level:
public void onItemSelected(AdapterView<?> parent, View arg1, int pos,long id) {
if(Build.VERSION.SDK_INT >= 28){ //onItemSelected() doesn't seem to be called when listener is set on Api 28+
check = 1;
}
if(++check > 1) {
//Do your action here
}
}
I think that's quite weird and I'm not sure wether others also have this problem, but in my case it worked well.
I placed a TextView on top of the Spinner, same size and background as the Spinner, so that I would have more control over what it looked like before the user clicks on it. With the TextView there, I could also use the TextView to flag when the user has started interacting.
My Kotlin code looks something like this:
private var mySpinnerHasBeenTapped = false
private fun initializeMySpinner() {
my_hint_text_view.setOnClickListener {
mySpinnerHasBeenTapped = true //turn flag to true
my_spinner.performClick() //call spinner click
}
//Basic spinner setup stuff
val myList = listOf("Leonardo", "Michelangelo", "Rafael", "Donatello")
val dataAdapter: ArrayAdapter<String> = ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, myList)
my_spinner.adapter = dataAdapter
my_spinner.onItemSelectedListener = object : OnItemSelectedListener {
override fun onItemSelected(parent: AdapterView<*>?, view: View, position: Int, id: Long) {
if (mySpinnerHasBeenTapped) { //code below will only run after the user has clicked
my_hint_text_view.visibility = View.GONE //once an item has been selected, hide the textView
//Perform action here
}
}
override fun onNothingSelected(parent: AdapterView<*>?) {
//Do nothing
}
}
}
Layout file looks something like this, with the important part being that the Spinner and TextView share the same width, height, and margins:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Spinner
android:id="#+id/my_spinner"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="#drawable/bg_for_spinners"
android:paddingStart="8dp"
android:paddingEnd="30dp"
android:singleLine="true" />
<TextView
android:id="#+id/my_hint_text_view"
android:layout_width="match_parent"
android:layout_height="35dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:background="#drawable/bg_for_spinners"
android:paddingStart="8dp"
android:paddingEnd="30dp"
android:singleLine="true"
android:gravity="center_vertical"
android:text="*Select A Turtle"
android:textColor="#color/green_ooze"
android:textSize="16sp" />
</FrameLayout>
I'm sure the other solutions work where you ignore the first onItemSelected call, but I really don't like the idea of assuming it will always be called.
I solved this problem like this:
In the activity lifecycle method whose name is onResume():
I added Spinner.setOnItemSelectedListener(this);
As a result, when our spinner call onclick method in the initialize, it does not work.
onResume method starts working when the finished Android page is displayed.

Checks wrong checkbox on recyclerview

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);
}

RecyclerView radio button won't register only the latest checked item (remember previous too)

I have RecyclerView which has multiple items, those items contain radio buttons, course name (TextView) and hole number (TextView).
What supposes to happen is that when I click the radio button, it should select only that 1, and if there are the previous check it should uncheck it (single selection). Well at the moment It checks only 1 at a time which is ok (so frontend works as it should), but what happens "under the hood"... example:
There are currently 3 items in RecyclerView. I click the third item to be checked, then I click first, and again third. now I click "start game" button, what should happen is that it should take that lastly checked item (in this case the third left lastly selected) and intent its course name and hole number to the next Activity, but instead what happens now is that it intent the first items course name and hole number... Also if I do the same as previous, but instead of clicking first item, I click second, then even tho lastly I clicked that third item, instead intent its course name and hole number, it intents that second items... So it always intents that item which is clicked (at some point) and from those clicked items it checks the first 1 (from top to bottom of a list) and take its intents.
Here is my Adapter where I'm checking which 1 is selected:
public class NewGameCourseAdapter extends RecyclerView.Adapter<NewGameCourseAdapter.NewGameCourseViewHolder> {
private ArrayList<NewGameCourseItem> mCourseList;
private NewGamePlayerAdapter.OnItemsCheckStateListener checkStateListener;
private NewGameCourseAdapter.OnItemClickListener itemClickListener;
public void setOnItemClickListener(NewGameCourseAdapter.OnItemClickListener listener) {
itemClickListener = listener;
}
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemsCheckStateListener(NewGamePlayerAdapter.OnItemsCheckStateListener checkStateListener) {
this.checkStateListener = checkStateListener;
}
public static class NewGameCourseViewHolder extends RecyclerView.ViewHolder {
public RadioButton mRadioButton;
public NewGameCourseViewHolder(#NonNull View itemView, final NewGameCourseAdapter.OnItemClickListener listener) {
super(itemView);
mRadioButton = itemView.findViewById(R.id.radioButton);
}
}
onBindViewHolder:
#Override
public void onBindViewHolder(#NonNull final NewGameCourseViewHolder holder, final int position) {
final NewGameCourseItem currentItem = mCourseList.get(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 isChecked) {
notifyItemChanged(selectedPosition);
selectedPosition = holder.getAdapterPosition();
notifyItemChanged(selectedPosition);
if (itemClickListener != null) {
itemClickListener.onItemClick(position);
}
}
});
This is the Activity where I do the intent:
mStartGame = findViewById(R.id.button_start_game);
mStartGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
for (int i = 0; i < mCourseList.size(); i++) {
/** If radio button is selected, then intent to ActivityGame **/
if (mCourseList.get(i).getRadioButton() == true) {
Intent intent = new Intent(ActivityNewGame2.this, ActivityGame.class);
/** Also intent selected items course name and hole number **/
intent.putExtra("COURSENAME", mCourseList.get(i).getCourseName());
intent.putExtra("HOLESNM", mCourseList.get(i).getHolesNm());
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
break;
}
}
}
});
Summary: in frontend it looks correct, it selects only that radio button which is lastly clicked and uncheck the previous (as it should), but inside, it won't "forget" the previous selections as it should do...
You are doing something weird, if possible make that simple.
Step 1: Create a method to get the selected item in your adapter class
public NewGameCourseItem getSelectedItem() {
return mCourseList.get(selectedPosition);
}
Step 2: Then modify your on click method like below
mStartGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
NewGameCourseItem item = adapter.getSelecteditem();
Intent intent = new Intent(ActivityNewGame2.this, ActivityGame.class);
/** Also intent selected items: course name and hole number **/
intent.putExtra("COURSENAME", item.getCourseName());
intent.putExtra("HOLESNM", item.getHolesNm());
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
});
Step 3: Now modify your onCheckedChanged as below
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
notifyItemChanged(selectedPosition);
selectedPosition = holder.getAdapterPosition();
notifyItemChanged(selectedPosition);
}
Create a class variable in adapter
private int selectedPosition = -1; //change -1 to any default position, need to be selected.
Modify the below function in adapter
#Override
public void onBindViewHolder(#NonNull final NewGameCourseViewHolder holder, final int position) {
final NewGameCourseItem currentItem = mCourseList.get(position);
holder.mRadioButton.setChecked(selectedPosition == position);
holder.mRadioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
if(isChecked) {
int tempSelected = selectedPosition;
selectedPosition = position;
notifyDataSetChanged();
}
}
});
}
Create a new method in adapter as below-
public int getSelectedItemIndex() {
return selectedPosition;
}
I assume adapter is the variable of NewGameCourseAdapter in the Activity class. Modify the button click in the Activity:
mStartGame.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int selectedRecyclerItemPosition = adapter.getSelectedItemIndex();
//Calling intent and pass selected item info
Intent intent = new Intent(ActivityNewGame2.this, ActivityGame.class);
/** Also intent selected items course name and hole number **/
intent.putExtra("COURSENAME", mCourseList.get(selectedRecyclerItemPosition).getCourseName());
intent.putExtra("HOLESNM", mCourseList.get(selectedRecyclerItemPosition).getHolesNm());
startActivity(intent);
overridePendingTransition(R.anim.slide_in_right, R.anim.slide_out_left);
}
});

Checkbox clicking check other checkboxes too

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;
}
}

Clicking RadioButton "A" toggles RadioButton "B" RecyclerView

I have a RecyclerView that displays a list of RadioButtons of countries, to let the user choose his country. I don't want more than on Item clicked, so I've wrote this OnCheckListener in the onBindView method of the adapter, but whenever I click a RadioButton, several other buttons toggles with it.
#Override
public void onBindViewHolder(final com.example.ameer.ta7adialma3rifa.adapters.CountriesAdapter.ViewHolder holder, final int position) {
String name = mData.get(position).getName();
int imgId = mData.get(position).getImageId();
holder.radioButton.setText(name);
holder.flagImageView.setImageResource(imgId);
holder.radioButton.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
RadioButton button = (RadioButton) compoundButton;
if (!button.getText().equals(mData.get(position).getName())){
button.setChecked(false);
}
if (runnable != null){
runnable.run();
}
runnable = new Runnable() {
#Override
public void run() {
holder.radioButton.setChecked(false);
}
};
}
});
}
You should put your radio buttons in a radio group. this way just one of them is being chosen. and I don't know why are using runnable to set the radio button checked! I hope this helps you.

Categories