I am trying to load a list in RecyclerView and show the first row of the list as selected. I have achieved it using the following code:
#Override
public void onBindViewHolder(NavigationDrawerAdapter.ViewHolder holder, final int position) {
if (!mNavClassrooms.get(position).equals("")) {
holder.mTextViewClassroom.setText(mNavClassrooms.get(position)); // Setting the Text with the array of our Titles
holder.mRelLayClassroom.setSelected(mSelectedItems.get(position, false));
/*
The following code was written to make the first item in the Classroom list as selected.
It leads to the item always being selected and hence has been commented out.
*/
if(position == 0 && intOldSelectedItem == -1){
holder.mRelLayClassroom.setSelected(mSelectedItems.get(position, true));
intOldSelectedItem = 0;
mSelectedView = holder.mRelLayClassroom.getChildAt(position);
mSelectedItems.put(position, true);
}
else{
holder.mRelLayClassroom.setSelected(mSelectedItems.get(position, false));
}
} else {
holder.mTextViewClassroom.setText("No classes found");
holder.mTextViewClassroom.setPadding(40, 0, 0, 0);
}
holder.mRelLayClassroom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mSharedPreferences = mContext.getSharedPreferences(Constants.AAPREFERENCES, Context.MODE_PRIVATE);
String strClassroomValue = mNavClassrooms.get(position);
int strClassroomName = mNavClassroomNames.get(position);
SharedPreferences.Editor editor = mSharedPreferences.edit();
editor.putString(Constants.CLASSROOM_VALUE, strClassroomValue);
editor.putInt(Constants.CLASSROOM_NAME, strClassroomName);
editor.commit();
/*
We are storing the position of the selected row in the SparseBooleanArray.
We delete it in case another row has been selected.
*/
if (mSelectedItems.get(position, false)) {
/*
Do nothing
*/
} else {
mSelectedItems.put(position, true);
/*
Making sure that the delete code is called only if some view is selected
*/
if (mSelectedView != null) {
mSelectedView.setSelected(false);
mSelectedItems.delete(intOldSelectedItem);
view.setSelected(false);
}
mSelectedView = view;
intOldSelectedItem = position;
view.setSelected(true);
}
}
However, now the first row stays selected always. I am unable to deselect it. I cannot seem to get this working.
I referred to the following answer to achieve most of this functionlaity.
https://stackoverflow.com/a/29984220/2186220
Any help will be appreciated.
I'm not answering your question by posting a fixed version of your onBindViewHolder method since it's kinda hard to understand and we don't know how the rest of your adapter looks like. So following a RecyclerView Adapter which does what you want: Selecting the first row by default and deselecting it once a other row is selected.
public class Adapter extends RecyclerView.Adapter<Adapter.ViewHolder> {
// ... other fields
// default selection position is the first one
private int selectedPosition = 0;
// ... constructor etc.
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
if(position == selectedPosition){
holder.itemView.setSelected(true);
} else {
holder.itemView.setSelected(false);
}
// Actual selection / deselection logic
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int currentPosition = holder.getLayoutPosition();
if(selectedPosition != currentPosition){
// Temporarily save the last selected position
int lastSelectedPosition = selectedPosition;
// Save the new selected position
selectedPosition = currentPosition;
// update the previous selected row
notifyItemChanged(lastSelectedPosition);
// select the clicked row
holder.itemView.setSelected(true);
}
}
});
// other adapter code
}
// other adapter stuff like onCreateViewHolder, getItemCount, ViewHolder etc.
}
Note: I guess there's no need to use a SparseBooleanArray so simply remove it and replace it with the int field used in the example above.
Initialize your
int intOldSelectedItem=0 and keep one boolean isVisible= false;
And do it as below:
if (holder.getPosition() == intOldSelectedItem) {
if (isVisible) {
//background for selected item
} else {
//background for unselected item
}
} else {
//background for unselected item
}
holder.mRelLayClassroom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (intOldSelectedItem== holder.getPosition()) {
isVisible = !isVisible;
} else {
if (intOldSelectedItem!= 0) {
isVisible = false;
notifyItemChanged(intOldSelectedItem);
}
isVisible = true;
}
intOldSelectedItem= holder.getPosition();
notifyItemChanged(intOldSelectedItem);
}
});
I hope it might help you.
Add background selector to your ViewHolder layout.
Create your selector handler something like this:
public class SingleSelector {
private View oldVIew;
public void setSelection(View newView) {
if (oldVIew == null) {
newView.setSelected(true);
oldVIew = newView;
} else {
oldVIew.setSelected(false);
newView.setSelected(true);
oldVIew = newView;
}
}
}
Set default selection when you need it:
#Override
public void onBindViewHolder(SimpleViewHolder holder, int position) {
if (position == 0) {
singleSelector.setSelection(holder.itemView);
}
}
In your ViewHolder add listener to itemView and pass it to the handler:
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
singleSelector.setSelection(itemView);
}
});
In my case I have radio buttons in a list view. Only one radio button can be selected at one time. My code is working fine.
Problem:
I want to make radio button checked if its checked value is one in my list.
i have tried many methods but I haven't found a solution yet. Following is the code part for radio button from the adapter class:
Adapter.java
if(mpref.GetquestionType().equals("Radio")){
h.radio.setVisibility(View.VISIBLE);
h.radio.setText(data.get(position).answere);
if(data.get(position).checked.equals("1")){
/*What should i do there...*/
}
h.radio.setTag(position);
h.radio.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = (Integer) v.getTag();
Log.i("ID of radiobutton","Order Edit # position : " + pos);
if (position != mSelectedPosition && mSelectedRB != null) {
mSelectedRB.setChecked(false);
((VasNBIActivity) context).removeChecked(data.get(mSelectedPosition).id);
mSelectedRB.setBackgroundResource(R.drawable.button_ackgroun1);
/*data.get(mSelectedPosition).checked="0";*/
}
mSelectedPosition = position;
((VasNBIActivity) context).addChecked(data.get(mSelectedPosition).id);
h.radio.setBackgroundResource(R.drawable.button_background);
/* data.get(mSelectedPosition).checked="1";*/
mSelectedRB = (RadioButton) v;
}
});
if (mSelectedPosition != position) {
h.radio.setChecked(false);
}else {
h.radio.setChecked(true);
if(mSelectedRB != null && h.radio != mSelectedRB){
mSelectedRB = h.radio;
}
}
In removeChecked and addChecked I am adding selected radio button ID to array list for submitting. Any help or hint will be appreciated.
I have a recyclerview in which every item has 3 radiobuttons grouped in a radiogroup. Now a user can select only one radiobutton per item in recyclerview. But I want the user to select only one radiobutton throughout the recyclerview. How can this be achieved?
This is how it looks currently.
I would like to make it possible to check only 1 radiobutton throughout the recycler view. If 1st radio button in first item is checked and after that the user clicks on the 2nd radiobutton in 2nd item, then the 1st radiobutton in the 1st item should get unchecked.
Here is another method to do the same. This is more elegant than my previous answer. But I have kept both as the previous answer provides more flexibility.
private RadioButton lastCheckedRB = null;
...
#Override
public void onBindViewHolder(final CoachListViewHolder holder, final int position) {
holder.priceRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
RadioButton checked_rb = (RadioButton) group.findViewById(checkedId);
if (lastCheckedRB != null) {
lastCheckedRB.setChecked(false);
}
//store the clicked radiobutton
lastCheckedRB = checked_rb;
}
});
Here is what worked for me:
private RadioButton lastCheckedRB = null;
...
#Override
public void onBindViewHolder(final CoachListViewHolder holder, final int position) {
View.OnClickListener rbClick = new View.OnClickListener() {
#Override
public void onClick(View v) {
RadioButton checked_rb = (RadioButton) v;
if(lastCheckedRB != null){
lastCheckedRB.setChecked(false);
}
lastCheckedRB = checked_rb;
}
};
//price_1m, price3m, price_6m are RadioButtons inside a radiogroup
holder.price1m.setOnClickListener(rbClick);
holder.price3m.setOnClickListener(rbClick);
holder.price6m.setOnClickListener(rbClick);
Here, the radio button is stored temporarily in lastCheckedRB. When a new radio button is clicked, the old radiobutton is unchecked. Initially the lastCheckedRB is set to null.
I used this approach
public class OffersRecyclerViewAdapter extends RecyclerView.Adapter<OffersRecyclerViewAdapter.ViewHolder> {
private List<OffersModel> offersList;
private Context context;
private int lastSelectedPosition = -1;
public OffersRecyclerViewAdapter(List<OffersModel> offersListIn, Context ctx) {
offersList = offersListIn;
context = ctx;
}
#Override
public OffersRecyclerViewAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.offer_item, parent, false);
OffersRecyclerViewAdapter.ViewHolder viewHolder =
new OffersRecyclerViewAdapter.ViewHolder(view);
return viewHolder;
}
#Override
public void onBindViewHolder(OffersRecyclerViewAdapter.ViewHolder holder, int position) {
//since only one radio button is allowed to be selected,
// this condition un-checks previous selections
holder.selectionState.setChecked(lastSelectedPosition == position);
}
#Override
public int getItemCount() {
return offersList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
public RadioButton selectionState;
public ViewHolder(View view) {
super(view);
selectionState = (RadioButton) view.findViewById(R.id.offer_select);
selectionState.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
lastSelectedPosition = getAdapterPosition();
notifyDataSetChanged();
}
});
}
}
}
I faced issues with the accepted answer.
Sometimes it makes currently checked radio button unchecked leaving non of the radio buttons selected. This was happening when selecting a radio button in different radio group after selecting a radio button from one group.
Here is the solution, instead of saving last checked RadioButton, save last checked RadioGroup and clear last check if last checked RadioGroup is not the current one and it has a selected RadioButton as shown below.
For more information read http://www.zoftino.com/android-recyclerview-radiogroup
priceGroup = (RadioGroup) view.findViewById(R.id.price_grp);
priceGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
if (lastCheckedRadioGroup != null
&& lastCheckedRadioGroup.getCheckedRadioButtonId()
!= radioGroup.getCheckedRadioButtonId()
&& lastCheckedRadioGroup.getCheckedRadioButtonId() != -1) {
lastCheckedRadioGroup.clearCheck();
Toast.makeText(PackageRecyclerViewAdapter.this.context,
"Radio button clicked " + radioGroup.getCheckedRadioButtonId(),
Toast.LENGTH_SHORT).show();
}
lastCheckedRadioGroup = radioGroup;
}
});
In Kotlin
private var checkedRadioButton: CompoundButton? = null
....
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
this.holder=holder
val option = getItem(position)
holder.txt_place_name.setText(option.toString())
holder.itemView.radioButton.setOnCheckedChangeListener(checkedChangeListener)
if (holder.itemView.radioButton.isChecked) checkedRadioButton =
holder.itemView.radioButton
}
....
private val checkedChangeListener = CompoundButton.OnCheckedChangeListener {
compoundButton, isChecked ->
checkedRadioButton?.apply { setChecked(!isChecked) }
checkedRadioButton = compoundButton.apply { setChecked(isChecked) }
}
KOTLIN 2021
Declare a RadioButton in a variable In your Adapter class
private var lastCheckedRB: RadioButton? = null
Now In your Adapter class onBindViewHolder, Write OnclickListener to RadioButton
holder.YOURRADIOBUTTON.setOnClickListener {
if (lastCheckedRB!=null){
lastCheckedRB?.isChecked=false
}
lastCheckedRB = holder.YOURRADIOBUTTON
}
To add onto G Anil Reddy answer:...
KOTLIN 2023
I have changed
lastCheckedRB = holder.YOURRADIOBUTTON
to:
lastCheckedRB = if (lastCheckedRB == holder.YOURRADIOBUTTON) null else holder.YOURRADIOBUTTON
This is in case the user clicks on the same radio button multiple times. It will uncheck and check each time to user clicks.
Declare a RadioButton in a variable In your Adapter class
private var lastCheckedRB: RadioButton? = null
Now In your Adapter class onBindViewHolder, Write OnclickListener to RadioButton
holder.YOURRADIOBUTTON.setOnClickListener {
if (lastCheckedRB!=null){
lastCheckedRB?.isChecked=false
}
lastCheckedRB = if (lastCheckedRB == holder.YOURRADIOBUTTON) null else holder.YOURRADIOBUTTON
}
Try something similar:
public void onCheckedChanged(RadioGroup radioGroup, int checkedItemId) {
mCheckedId = checkedItemId;
mSelectedPosition = getAdapterPosition();
}
The code above is the listener you register to the RadioGroup inside onCreateViewHolder(). The prefixed items are your fields in the adapter.
In onBindViewHolder():
if (position == mSelectedPosition) {
holder.radioGroup.check(mCheckedId);
} else {
holder.radioGroup.clearCheck();
}
It should work this way.
final String[] country_selcted = new String[1];
holder.rb_team_one.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
if(b==true)
country_selcted[0] =holder.rb_team_one.getText().toString();
else
country_selcted[0] =holder.rb_team_two.getText().toString();
}
});
Now Print country_selcted[0] it gives you to row radio group selection result only
I'm trying to make my first app which has a set of 15 buttons. when you press a button the color changes between two numbers.Then if you press a specificity different "commit" button the buttons won't change colors any more.
My question right now is how would I be able to iterate through the buttons on the screen? I believe I need a assign the buttons a "name", "type", or something like it, and then find all instances where that happens but I cannot find the relevant getter/setter methods.
Here is my code so far:
public void clickHandler(View view) {
Button btn = (Button) view;
int id = btn.getId();
boolean clicked = isChosen(btn);
if( clicked == true && id != 1) {
btn.setBackgroundColor(-3355444);
}
else{
btn.setBackgroundColor(-16777216);
}
}
public boolean isChosen(Button btn){
ColorDrawable buttonColor = (ColorDrawable) btn.getBackground();
int colorId = buttonColor.getColor();
if(colorId == -16777216){
return true;
}
else return false;
}
public boolean player = true;
public void changeTurn(View view) {
TextView t = (TextView) findViewById(R.id.textView3);
if(player == false) {
t.setText("Player 2's turn");
player = true;
}
else{
t.setText("Player 1's turn");
player = false;
}
Hope this piece of code helps
final int buttonCount = 15;
LinearLayout mLayout = (LinearLayout) findViewById(R.id.pager);
for (int i = 0; i < buttonCount; i++) {
TextView textView = new TextView(this);
textView.setTag(String.valueOf(i));
textView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
int buttonID = Integer.valueOf(view.getTag().toString());
updateColorForButtonAtPosition(buttonCount);
}
});
mLayout.addView(textView);
}
private void updateColorForButtonAtPosition (int buttonCount){
// add your functionality here
}
I am trying to populate data in UI fetched through REST service. The data comes up everytime but the UI doesn't get populated sometimes. The UI is kind of listing but listview is not being used. There's a ScrollView which has LinearLayout as its child and then row views are added to the linearlayout. There are times when UI just doesn't get updated even if the data is passed to it.
private void showData(List list) {
if(list != null && list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
} else {
mNoData.setVisibility(View.GONE);
final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.details_layout);
findViewById(R.id.details_progress).setVisibility(View.GONE);
linearLayout.removeAllViews();
LayoutInflater layoutInflater = getLayoutInflater();
View rowView = null;
TextView txtName = null;
Button buttonPlay = null;
for (int i = 0; i < list.size(); i++) {
rowView = layoutInflater.inflate(R.layout.row_view, null);
txtName = (TextView) rowView.findViewById(R.id.row_view_name);
buttonPlay = (Button) rowView.findViewById(R.id.row_view_button_play);
final Item item = (Item) list.get(i);
rowView.setTag(i) ;
txtName.setText(item.getName());
final RecentItem recentItem = RecentsManager.getInstance().getRecentItemFromRefID(item.getId());
if (recentItem !=null) {
buttonPlay.setText(getString("Resume"));
buttonPlay.requestFocus();
}
buttonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (recentItem!=null) {
//do some action
} else {
//do some action
}
finish();
}
});
final int tag = (Integer) rowView.getTag() ;
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do some action
}
}) ;
txtName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do some action
}
});
buttonPlay.setId(i);
if(i < list.size())
buttonPlay.setNextFocusDownId(i+1);
linearLayout.addView(rowView);
if (i == 0) {
buttonPlay.requestFocus();
buttonPlay.setNextFocusUpId(mButtonReminder.getId());
if(mButtonReminder != null) {
mButtonReminder.setNextFocusDownId(buttonPlay.getId());
}
} else {
buttonPlay.setNextFocusUpId(i-1);
}
}
}
}
I have even checked the linearlayout children's count and the count is always equal to list size which means rows are also being added to it but it just doesn't show up on the UI.
What can be the issue?
you are using condition
if(list != null && list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
}
change it to
if(list == null || list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
}
I was able to resolve the issue by doing certain changes as adding fillViewPort="true" for scrollview. Also, there was a background thread which was trying to update the UI because of which UI thread was breaking. This didn't resulted in a crash but the UI updation didn't happened. With these two changes it's working fine.