Clicking RadioButton "A" toggles RadioButton "B" RecyclerView - java

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.

Related

How to apply search filter to a recyclerview with categorical filtering?

Right now, I have a recyclerview with items of two categories, and three buttons on the activity which filters them by "all", "design category" and "development category". When a button is clicked, only items of that category is displayed. I also have a search bar, which filters the results by name. After something is typed into the searchbar and the results are filtered, if a categorical button is clicked, it displays all items of that category instead of only items that match the name that is searched.
My only current solution is to clear the searchbar when a button is clicked, but I want to make it so that the searchbar filter still applies after a button is clicked.
HomeActivity.Java:
public class HomeActivity implements RecyclerViewAdapter.RecyclerViewOnClickListener{
#Override
protected void onCreate(Bundle savedInstanceState) {
//other stuffs
final Button allLessonsButton = (Button) findViewById(R.id.allLessonsButton);
allLessonsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onAllLessonsButtonTapped();
}});
final Button designLessonsButton = (Button) findViewById(R.id.designLessonsButton);
designLessonsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onDesignLessonsButtonTapped();
}});
final Button developmentLessonsButton = (Button) findViewById(R.id.developmentLessonsButton);
developmentLessonsButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
onDevelopmentLessonsButtonTapped();
}});
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
adapter.getFilter().filter(newText);
return false;
}
});
}
setupRecyclerView();
}
private void setupRecyclerView() {
lessonRecyclerView = (RecyclerView) findViewById(R.id.lesson_recycler_view);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
lessonRecyclerView.setLayoutManager(linearLayoutManager);
}
private void onAllLessonsButtonTapped() {
currentLessons = allLessons;
adapter = new LessonRecyclerViewAdapter(this, currentLessons, this);
lessonRecyclerView.setAdapter(adapter);
}
private void onDesignLessonsButtonTapped() {
currentLessons = developmentLessons;
adapter = new LessonRecyclerViewAdapter(this, currentLessons, this);
lessonRecyclerView.setAdapter(adapter);
}
private void onDevelopmentLessonsButtonTapped() {
currentLessons = designLessons;
adapter = new LessonRecyclerViewAdapter(this, currentLessons, this);
lessonRecyclerView.setAdapter(adapter);
}
Essentially your users have two different methods to filter the list before displaying them. On one hand, they can choose a category using buttons; or they can type some texts and filter it by searching.
The main problem right now is to discern the two competing methods of filtering. If a user has both clicked a category and typed a query, we don't know which filter method we should respect.
In my opinion, we should always respect the latest action.
One way to solve this problem is, for example, have a variable recording the latest action the user had. Example pseudocode:
bool isSearching = false
when user types something:
isSearching = true
when a category is clicked:
isSearching = false
filtering:
if isSearching then:
filter based on query
else:
filter based on category
You can implement this logic in different events, such as EditText onQueryTextChange or Button onClickListener event.

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

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

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

favorite button in android not working properly

Hii i'm making an app where i have small heart image onclick of that image i've set an onclick listener so when i click on that image it is replaced by another red coloured heart image.
so my problem is when i again click on red heart image it doesnt turn to its normal state which is blank heart vector image as i'm new in android i dont have much knowledge please if someone can guide.
my code for image onclick
#Override
public void onBindViewHolder(FeedViewHolder holder, int position) {
int image_id = images[position];
//holder.background_image_layout.setImageDrawable(null);
//holder.background_image_layout.setImageResource(image_id);
holder.background_image.setBackgroundResource(image_id);
}
#Override
public int getItemCount() {
return images.length;
}
public static class FeedViewHolder extends RecyclerView.ViewHolder {
CustomTextViewMedium first_text,second_text,third_text,fourth_text,fifth_text,sixth_text,
seventh_text;
ImageView favourite_image;
CardView primary_card;
LinearLayout background_image;
ImageView background_image_layout;
CircleImageView profile_image;
public FeedViewHolder(View itemView) {
super(itemView);
background_image = (LinearLayout)itemView.findViewById(R.id.background_image);
primary_card = (CardView)itemView.findViewById(R.id.primary_card);
first_text = (CustomTextViewMedium)itemView.findViewById(R.id.first_text);
second_text = (CustomTextViewMedium)itemView.findViewById(R.id.second_text);
third_text = (CustomTextViewMedium)itemView.findViewById(R.id.third_text);
fourth_text = (CustomTextViewMedium)itemView.findViewById(R.id.fourth_text);
fifth_text = (CustomTextViewMedium)itemView.findViewById(R.id.fifth_text);
sixth_text = (CustomTextViewMedium)itemView.findViewById(R.id.sixth_text);
seventh_text = (CustomTextViewMedium)itemView.findViewById(R.id.seventh_text);
favourite_image = (ImageView)itemView.findViewById(R.id.favourite_image);
background_image_layout = (ImageView) itemView.findViewById(R.id.background_image_layout);
profile_image = (CircleImageView)itemView.findViewById(R.id.profile_image);
favourite_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(favourite_image.isPressed()){
favourite_image.setImageResource(R.drawable.ic_heart);
favourite_image.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
else {
favourite_image.setImageResource(R.drawable.ic_favorite_border_black_24dp);
favourite_image.setScaleType(ImageView.ScaleType.CENTER_CROP);
}
}
});
}
}
Use if condition like this :-
first globally define like this :-
boolean imageChange = true;
then do this in setOnClickListener like this :-
favourite_image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(imageChange ){
favourite_image.setImageResource(R.drawable.ic_heart);
favourite_image.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageChange = false;
}else {
favourite_image.setImageResource(R.drawable.ic_favorite_border_black_24dp);
favourite_image.setScaleType(ImageView.ScaleType.CENTER_CROP);
imageChange = true;
}
}
});
Problem is that favourite_image.isPressed() is not persistent state of the View. It will be true only while user holds its finger on the view.
To overcome this you have two similar options:
Option #1
Instead of checking isPressed you can check some other state, for example isSelected. Since this is ImageView you probably need to set the state manually on click.
public void onClick(View v) {
if(favourite_image.isSelected()){
favourite_image.setImageResource(R.drawable.ic_heart);
favourite_image.setScaleType(ImageView.ScaleType.CENTER_CROP);
favourite_image.setSelected(false)
}
else {
favourite_image.setImageResource(R.drawable.ic_favorite_border_black_24dp);
favourite_image.setScaleType(ImageView.ScaleType.CENTER_CROP);
favourite_image.setSelected(true)
}
}
Options #2
Use some simple boolean to keep track of the selected state, and set/chec its values similarity to above code.

how to set different actions to dynamiclly created button on android (specifically - auto scroll to a textview using a dynamic button)

i created a layout containing multiple text views.
i saved the text view's ids in an ArrayList which is a class variable called _resultId.
now i want to create buttons which suppose to scroll to the correct text view
(the first button to the first text view etc)
the question is: how to pass the correct id to each of the buttons on press method?
i tried using a global variable _counter but when i run the program all the buttons scroll to the last text view
the code of the method:
private void addNavigationView(ViewGroup navigationLayout, ArrayList<Perek> mishnayot)
{
for (int i=0;i<mishnayot.size();i++)
{
_counter=i;
String currentOt=mishnayot.get(i).getOt();
Button button = new Button(getBaseContext());
button.setText(currentOt);
if (_resultId==null)
throw new IllegalAccessError("missing result id link cannot be created");
button.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View arg0) //make it scroll to correct textview
{
new Handler().post(new Runnable()
{
#Override
public void run()
{
View currentView=findViewById(_resultId.get(_counter));
ScrollView scrollView=(ScrollView) findViewById(R.id.resultScroll);
scrollView.scrollTo(0, currentView.getTop());
}
});
}
});
navigationLayout.addView(button);//add the button to panel
}
navigationLayout.setVisibility(View.VISIBLE);
}
after learning more on Runnable interface i Found an answer so for those who will struggle with something similar:
you need to create a new class altogether that implements both runnable and the OnClickListener.
this class will contain extra data and a constructor to match your needs.
when you set the onClick method of the button you create a new object of that class.
for instance in my case the new method looked like:
public class ButtonHandler implements OnClickListener,Runnable
{
private String _data;//data to be passed for the button
private ArrayList<Integer> _resultId;//the id's of the text views
private Activity _activity;
public ButtonHandler(String data,ArrayList<Integer> resultId,Activity activity)
{
_data=data;
_resultId=resultId;
_activity=activity;
}
#Override
public void run()
{
View currentView=_activity.findViewById(_resultId.get(Integer.valueOf(_data)));
ScrollView scrollView=(ScrollView) _activity.findViewById(R.id.resultScroll);
scrollView.scrollTo(0, currentView.getTop());
}
#Override
public void onClick(View v)
{
new Handler().post(this);
}
}
now to call it from the main activity i use:
private void addNavigationView(ViewGroup navigationLayout, ArrayList<Perek> mishnayot)
{
for (int i=0;i<mishnayot.size();i++)
{
_counter=i;
String currentOt=mishnayot.get(i).getOt();
Button button = new Button(getBaseContext());
button.setText(currentOt);
if (_resultId==null)
throw new IllegalAccessError("missing result id link cannot be created");
button.setOnClickListener(new ButtonHandler(i+"",_resultId,this));
navigationLayout.addView(button);//add the button to panel
}
navigationLayout.setVisibility(View.VISIBLE);
}

Categories