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.
Related
I want select only one radio button in recyclerView and get its data in its Activity.
I have gone through following solutions :
Single selection in RecyclerView
Select only one radiobutton in a recyclerview
And I made one solution :
private static int lastCheckedPos = -1;
binding.radioButton.setChecked(mImagesList.get(position).isSelected());
binding.radioButton.setTag(new Integer(position));
//for default check in first item
if(position == 0 && mImagesList.get(0).isSelected() && binding.radioButton.isChecked())
{
radioButton = binding.radioButton;
lastCheckedPos = 0;
}
binding.radioButton.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
RadioButton cb = (RadioButton)v;
int clickedPos = ((Integer)cb.getTag()).intValue();
if(cb.isChecked())
{
if(radioButton != null)
{
radioButton.setChecked(false);
mImagesList.get(lastCheckedPos).setSelected(false);
}
radioButton = cb;
lastCheckedPos = clickedPos;
}
else
radioButton = null;
mImagesList.get(clickedPos).setSelected(cb.isChecked());
}
});
I have written this in onBindViewHolder method.
Now to get data i have written this in adapter :
public String getUserId() {
if(lastCheckedPos == -1)
{
return null;
} else {
return mImagesList.get(lastCheckedPos).getUser_code();
}
}
And get this in activity :
userId = adapter.getUserId();
But I am not able to get any data in activity. It is always showing null. Also if I click twice on radio button then it deselected.
Please ask if anything unclear. Any help would be appreciated.
Thank you :)
Replace int clickedPos = ((Integer)cb.getTag()).intValue(); by int clickedPos =position;
I have a recycler view which has header element and child element at starting time the visibility of child element is gone. I want that when I clicked on header element suppose position zero child elements of that position should be visible (mean expand) I achieve this successfully. The only problem that I am facing is that when I clicked the same position again I want to collapse the same view.
My recycler view onBingViewHolder logic is given below:
holder.doc_type.setText(docDatalist.get(position).getDocTypeDesc());
if (position == expandedPosition )
{
holder.recyclerViewImages.setVisibility(View.VISIBLE);
imagerequestserver(docDatalist.get(expandedPosition), vinappserial, holder);
holder.iconexpandCollapse.setImageResource(R.mipmap.expand_4);
}
else {
holder.recyclerViewImages.setVisibility(View.GONE);
holder.iconexpandCollapse.setImageResource(R.mipmap.expand);
}
holder.myDocumentListCollapse.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (expandedPosition >= 0) {
int prev = expandedPosition;
holder.recyclerViewImages.setVisibility(View.VISIBLE);
notifyItemChanged(prev);
}else {
expandedPosition = holder.getAdapterPosition();
notifyItemChanged(expandedPosition);
}
}
});
You need to add manually add position array which was clicked and then after check its position in viewHolder;
Provide collapse Position List in your constructor
positionSet = new ArrayList<>();
Add and remove appropriate position on Header Click listener click event:
public void onClick(View view) {
int position = getAdapterPosition();
if(positionSet.contains(position)){
positionSet.remove((Integer)position);
}else {
positionSet.add(position);
}
notifyDataSetChanged();
}
}
Manage to notify in onBindViewHolder
if(positionSet.contains(position)){
//visible
}else {
//gone
}
I have search a lot what I did is created a list of items simple number and having check box Which is checked and unchecked, So when I tap fast fast on list it crash
and generate ArrayIndexOutOfBound Exception
So I don't know what is I am doing wrong
here is my code
adapter class
class SingleListItemHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView mItemDate, mFontSizeCategory;
private ImageView isChecked, isTrack, isUnChecked;
private int fontSize = 13;
SingleListItemHolder(View v) {
super(v);
mFontSizeCategory = (TextView) v.findViewById(R.id.tv_font_size_category);
mItemDate = (TextView) v.findViewById(R.id.tv_recycler_view_list_header);
isChecked = (ImageView) v.findViewById(R.id.iv_recycler_view_list_item_selected);
isUnChecked = (ImageView) v.findViewById(R.id.iv_recycler_view_list_item_unselected);
isTrack = (ImageView) v.findViewById(R.id.iv_track);
v.setOnClickListener(this);
this.setIsRecyclable(false);
}
#Override
public void onClick(View v) {
mSingleItemListModels.get(pos).setSelected(false);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
pos = getAdapterPosition();
mSingleItemListModels.get(pos).setSelected(true);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
}
pos = getAdapterPosition();
move above
mSingleItemListModels.get(pos).setSelected(false);
You are getting -1 Position in getAdapterPosition() because when u are click fast it some time throw the -1 position
You can check this out
if (pos != RecyclerView.NO_POSITION) {
//Do your setting part
}
Change this code
#Override
public void onClick(View v) {
mSingleItemListModels.get(pos).setSelected(false);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
pos = getAdapterPosition();
mSingleItemListModels.get(pos).setSelected(true);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
}
Code to
#Override
public void onClick(View v) {
mSingleItemListModels.get(pos).setSelected(false);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
pos = getAdapterPosition();
if (pos != RecyclerView.NO_POSITION) {
mSingleItemListModels.get(pos).setSelected(true);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
}
}
You have to get the item before using pos = getAdapterPosition();
#Override
public void onClick(View v) {
pos = getAdapterPosition();
mSingleItemListModels.get(pos).setSelected(false);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
mSingleItemListModels.get(pos).setSelected(true);
notifyItemChanged(pos, mSingleItemListModels.get(pos));
}
You are misusing getAdapterPosition. It's not a great idea to use it to get the index of the current displayed item. Even more bad that it may also return -1 if you have called a adapter change (which you did twice with notifyItemChanged).
See the docs for it here
Note that if you've called notifyDataSetChanged(), until the next layout pass, the return value of this method will be NO_POSITION.
The value of NO_POSITION is -1. So instead of implementing the ClickListener to your RecyclerView.ViewHolder you should implement it in the onBindViewHolder because there you have the current index.
Use it here
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// the position will be the correct one
// but don't store the position in a class field
// since it may change during scrolling
}
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);
}
});
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.