I have a custom view that holds, among other views, a RadioButton.
The SingleRadioItem:
public class SingleRadioItem extends LinearLayout {
private TextView mTextKey;
private RadioButton mRadioButton;
private ImageView mImageSeparator;
public SingleRadioItem(Context context, AttributeSet attrs) {
super(context, attrs);
View view = LayoutInflater.from(context).inflate(R.layout.rtl_single_radio_item, this, true);
mTextKey = (TextView)view.findViewById(R.id.single_radio_item_text_key);
mRadioButton = (RadioButton)view.findViewById(R.id.single_radio_item_button);
mImageSeparator = (ImageView)view.findViewById(R.id.single_image_separator);
}
public void setKey(String key) {
mTextKey.setText(key);
}
public boolean getSelectedState() {
return mRadioButton.isSelected();
}
public void setSelectedState(boolean selected) {
mRadioButton.setSelected(selected);
}
}
I want to create instances of this view, add them to a RadioGroup and add the RadioGroup to a LinearLayout.
When I do so, it allows me to set all the radio buttons as selected, which means, the RadioGroup isn't functioning well (probably because how I do it..)
RadioGroup radioGroup = new RadioGroup(this);
radioGroup.setOrientation(RadioGroup.VERTICAL);
SingleRadioItem radio1 = new SingleRadioItem(this, null);
SingleRadioItem radio2 = new SingleRadioItem(this, null);
radioGroup.addView(radio1);
radioGroup.addView(radio2);
updateDetailsView.addView(radioGroup);
Obviously, when I add RadioButton radio1 = new RadioButton(this); the RadioGroup works well.
Is it even possible to add a view that holds a radio button to a radiogroup and I'm just missing something or not possible at all?
Thanks!
SOLUTION:
To extend #cosmincalistru Answer and help others:
for each SingleRadioItem I added to the LinearLayout I attached a listener like this:
radio1.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (lastRadioChecked != null) {
lastRadioChecked.setCheckedState(false);
}
lastRadioChecked = (SingleRadioItem)v;
lastRadioChecked.setCheckedState(true);
}
});
You also need to set the RadioButton View inside the SingleRadioItem XML to clickable:false.
The RadioButton has to be directly subordinated to the RadioGroup, otherwise your buttons will be considered as from different groups.
The best idea is to use listeners on each RadioButton in your case.
EDIT:
Whenever i want to make a group of RadioButtons as part from a group but can't use the RadioGroup i do something like this :
RadioButton r1,r2,....;
// Instantiate all your buttons;
...
// Set listener on each
for(each RadioButton) {
rx.setOnCheckedChangeListener(OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
//set all buttons to false;
for(each RadioButton) {
rx.setChecked(false);
}
//set new selected button to true;
buttonView.setChecked(true);
}
}
});
}
When you add a view to RadioGroup, only if the view is a instanceof RadioButton only then will the group work correctly. In your case you are adding a LinearLayout. So SingleRadioItem should extend RadioButton.
Related
I've got "for each" loop that creates textView for every obiect from the list and add them to the linear layout. It works great. Then I want to hide all of the textViews when user clicks on toggle button but here I've got problem - only the last textView from the list is being hidden , rest of them is still visible. I tried to solve this problem with many solutions ( for example with getChild()), but nothing works.
final List<FilterItem> filterItemList = filterData.getFilterItemList();
for (FilterItem filterItem : filterItemList) {
final TextView filter = new TextView(MainPanelActivity.this);
filter.setText(filterItem.getFilterItemName());
filter.setTextColor(R.color.black);
linearLayout.addView(filter);
filter.setVisibility(View.GONE);
textLine.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
filter.setVisibility(View.VISIBLE);
} else {
filter.setVisibility(View.GONE);
}
}
});
Note that youre setting a listener for textLine inside the for loop - so for each iteration you set a new listener that changes the visibility of the TextView created in the current iteraton.
Move textLine.setOnCheckedChangeListener() outside of the for loop; and inside onCheckedChanged - loop through all children of linearLayout and set the visibility for each child.
textLine.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
for (View v : linearLayout.getChildren()) {
if (v instanceof TextView) {
if (isChecked) {
v.setVisibility(View.VISIBLE);
} else {
v.setVisibility(View.GONE);
}
}
}
You could keep a list of TextViews when you create them. Then set the click listener outside the for-loop as Dmitri says, which would iterate through the list of TextViews and set the visibility to GONE.
private void setup() {
List<View> textViews = new ArrayList<>();
for (FilterItem filterItem : filterData.getFilterItemList()) {
View view = createTextViewFor(filterItem);
linearLayout.addView(filter);
textViews.add(view);
}
updateVisibility(textViews, View.GONE);
textLine.setOnCheckedChangeListener(
new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
int visibility = isChecked ? View.VISIBLE : View.GONE;
updateVisibility(textViews, visibility);
}
}
);
}
private View createTextViewFor(FilterItem filterItem) {
TextView view = new TextView(MainPanelActivity.this);
view.setText(filterItem.getFilterItemName());
view.setTextColor(R.color.black);
view.addFilter(filterItem);
return view;
}
private void updateVisibility(List<View> views, int visibility) {
for (View view : views) {
view.setVisibility(visibility);
}
}
In case you want to display textView dynamically, I think putting textView inside RecyclerView will be a better idea. RecyclerView has its own Adapter which will make it easy to play with data and textViews. Give recyclerView a try. RecycerView for what you are trying to do can be learnt in few hours and sky is the limit for what you can do with recyclerView :)
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
Hi i created dynamic radiogroup with radiobutton.Now i want to get values from dynamic radiogroup. Below is my code
final RadioGroup rg = new RadioGroup(this);
rg.setId(questionNo);
RadioButton[] rb = new RadioButton[answers.length()];
for (int i = 0; i < answers.length(); i++) {
JSONObject answerObject = answers.getJSONObject(i);
rb[i] = new RadioButton(this);
rb[i].setText(answerObject.getString("AnswerValue"));
rb[i].setId(answerObject.getInt("AnswerId"));
rg.addView(rb[i]);
}
rg.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup arg0, int arg1) {
int selectedId = rg.getCheckedRadioButtonId();
Log.i("ID", String.valueOf(selectedId));
}
});
Button click event
submit_button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
if(rg.getCheckedRadioButtonId()!=-1){
int id= rg.getCheckedRadioButtonId();
View radioButton = rg.findViewById(id);
int radioId = rg.indexOfChild(radioButton);
RadioButton btn = (RadioButton) rg.getChildAt(radioId);
String selection = (String) btn.getText();
Log.i("selection", selection);
}
}
});
I am getting only last index of the radio group.
I know it's too late, But this may help someone else
While creating your Dynamic Radiobutton Group, Create a parent layout(Linear layout or Relative Layout)
All radio groups will be the child of that Layout and all radio button will be a child of the specific radio group.
Creating No of Dynamic Radio Group
Create all Dynamic radio group in a parent layout
Add all radio button to a group
Add all radio group to the parent layout
public RadioButton[] rb;
public RadioGroup grp;
public LinearLayout layoutmain; //Parent layout
for(int i=0;i<qus.size();i++) //No of Questions
{
rb = new RadioButton[size];
grp = new RadioGroup(this);
grp.setId(a+qus.get(i).qusetionId);
for(int j=0;j<qus.get(i).choices.size();j++) //No of Radio button in radio group
{
rb[j] = new RadioButton(this);
rb[j].setText(qus.get(i).choices.get(j).getChoiceText());
grp.addView(rb[j]); // adding button to group
}
layoutmain.addView(grp); // adding group to layout
}
Retrieve All selected button task
From parent, layout get all child
Find all radio group using the child Instance
Create an object for that radio group
using that object get the selected radio button
Button bt = (Button) findViewById(R.id.button);
bt.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
for(int i=0;i<layoutmain.getChildCount();i++) //From the parent layout (Linear Layout) get the child
{
View child = layoutmain.getChildAt(i);
if(child instanceof RadioGroup) //Check weather its RadioGroup using its INSTANCE
{
RadioGroup rg = (RadioGroup) child; //create a RadioButton for each group
int selectedId = rg.getCheckedRadioButtonId(); // get the selected button
RadioButton radiochecked = (RadioButton) findViewById(selectedId);
Log.e("Radio",radiochecked.getText().toString()); //from the button get the selected text
}
}
} });
My every list view item has its own linearlayout component.The list view is in the activity with onItemClick on itself.
In my custom adapter file, I have the onclick on this linearlayout,
private ArrayList<Book> bookArray; // this is the data source
.........
LinearLayout imgLayout = (LinearLayout) rowView.findViewById(R.id.imageLayout);
imgLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) { // fire user Like
//*** how can I get which item is selected here?
But how can I get the item index whose linearlayout is clicked?
Regards
Hammer
Use setTag() and getTag() to remember positon and use it on click of LinerLayout.
in getView
LinearLayout imgLayout = (LinearLayout) rowView.findViewById(R.id.imageLayout);
imgLayout .setTag(position);
and into onclick of LinerLayout take it as
imgLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int position = (Integer)v.getTag();
//....
}
}
You can set the tag for your linear layout and inside your onClick you can get the tag which will return the position for which clickEvent get Trigger.
See below code:
private ArrayList<Book> bookArray; // this is the data source
.........
LinearLayout imgLayout = (LinearLayout) rowView.findViewById(R.id.imageLayout);
imgLayout.setTag(position);
imgLayout.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) { // fire user Like
//*** how can I get which item is selected here?
Log.d(TAG,"Clicked Pos of Row"+v.getTag().toString();
This is my code to add a new linear layout:
public void onClick_addContact(View v)
{
LinearLayout layout = (LinearLayout) findViewById(R.id.layoutLinear);
layout.addView(linearlayout(_intMyLineCount));
_intMyLineCount++;
}
private EditText editText(int _intID) {
EditText editText = new EditText(this);
editText.setId(_intID);
editText.setHint("My lines");
editText.setWidth(180);
editTextList.add(editText);
return editText;
}
private TextView textView(int _intID)
{
TextView txtviewAll=new TextView(this);
txtviewAll.setId(_intID);
txtviewAll.setText("My lines:");
textviewList.add(txtviewAll);
return txtviewAll;
}
private RadioButton button(int _intID)
{
RadioButton btn = new RadioButton(this);
btn.setId(_intID);
btn.setOnClickListener(newContact);
return btn;
}
OnClickListener newContact = new OnClickListener() {
//onClick view
public void onClick(View v) {
LinearLayout layout = (LinearLayout) findViewById(R.id.layoutLinear);
layout.addView(linearlayout(_intMyLineCount));
_intMyLineCount++;
}
};
private LinearLayout linearlayout(int _intID)
{
LinearLayout LLMain=new LinearLayout(this);
LLMain.setId(_intID);
LLMain.addView(textView(_intID));
LLMain.addView(editText(_intID));
LLMain.addView(button(_intID));
LLMain.setOrientation(LinearLayout.HORIZONTAL);
linearlayoutList.add(LLMain);
return LLMain;
}
}
As of now, if any radio button is clicked then a new linear layout gets added. How do I change this, if any radio button is clicked, then the corresponding linear layout gets removed?
Use the setVisibility method. If you know the ID of the layout, you can do do a findViewById and then use myLayout.setVisibility(View.GONE).
LinearLayout layout = (LinearLayout) findViewById(R.id.layoutLinear);
layout.removeView(findViewById(removeId));
Should be helpful..
You set a tag at the new LinearLayout for exmeple "the layout corresponding to the first radio button" and you can retrieve this layout for delete it with findViewByTag.