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;
}
}
Related
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);
}
I am working on a Learning app, it has a Tabview so I'm working with Fragments.
The last fragment has buttons on top to navigate through the multiple levels. Below that there is a Recyclerview which contains a Cardview with a Question on the left and an Edittext on the right to answer.
Currently the IME Option is actionSend and I want to not only skip to the next Edittext but also evaluate the Answer that was given. I achieved this already by implementing an OnClickListener but it's quite annoying having to click each Cardview in the Recyclerview to get Feedback, so I want to copy it to the setOnEditorActionListener function for the Editext. The problem I have is that I don't know how to get the position of the current Cardview item (to evaluate the givenAnswer with the corresponding item in the Questionlist) in the Recyclerview without actually clicking it just by changing the Editext.
private RecyclerView myrecyclerview;
private ArrayList<Question> QuestionList;
private QuestionAdapter recyclerAdapter;
private EditText givenAnswer;
public void ClickManager(final ArrayList<Question> list){
//works perfectly when the item is clicked
recyclerAdapter.setOnItemClickListener(new QuestionAdapter.OnItemClickListener() {
#Override
public void onItemClick(final int position) {
View itemView = myrecyclerview.getLayoutManager().findViewByPosition(position);
final EditText givenAnswer = itemView.findViewById(R.id.answer);
ClickEvaluation(list,givenAnswer,position);
}
});
givenAnswer.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
boolean handled = false;
if (i == EditorInfo.IME_ACTION_SEND){
ClickEvaluation(list,givenAnswer,position); //can't access any position
handled = true;
}
return handled;
}
});
}
The evaluation function:
public void ClickEvaluation(final ArrayList<Question> list, EditText givenAnswer, int position){
Question currenQuestion = list.get(position);
if (currenQuestion.correct(givenAnswer.getText().toString())){
currenQuestion.gaveCorrectAnswer();
score += 1;
current.setText(String.format("%d",score));
}else{
currenQuestion.showCorrectAnswer();
}
givenAnswer.setText("");
recyclerAdapter.notifyItemChanged(position);
}
Thanks a lot in advance!
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();
}
}
});
I am new for android, I have ListView with custom adapter, I pass one string if matches in ListView item want to change list item text color from Activity.
Here my code:
MyActivity:
public void handleResult(String rawResult) {
if(Utility.isNotNull(rawResult.getText().toString())) {
for(int i=0;i<listView.getAdapter().getCount();i++){
if(rawResult.equals(listItems.get(i).getStockItems())){
// listView.getChildAt(i).setBackgroundColor(ContextCompat.getColor(context, R.color.hint));
/* Here I want to change list item text color*/
adapter.notifyDataSetChanged();
}
}
}
}
Thanks in advance!
In your model class add one paramter like this
public class DataHolder{
private String StockItems;
private int isSelected;
public DataHolder(String StockItems, int isSelected) {
this.StockItems = StockItems;
this.isSelected = isSelected;
}
public String getStockItems() {
return StockItems;
}
public void setStockItems(String StockItems) {
this.StockItems = StockItems;
}
public int getiIsSelected() {
return isSelected;
}
public void setIsSelected(String isSelected) {
this.isSelected = isSelected;
}
}
initialise IsSelected zero
public void handleResult(String rawResult) {
if(Utility.isNotNull(rawResult.getText().toString())) {
for(int i=0;i<listView.getAdapter().getCount();i++){
if(rawResult.equals(listItems.get(i).getStockItems())){
listItems.get(i).setIsSelected(1);
adapter.notifyDataSetChanged();
}
}
}
}
In your cusom adapter class check
if(listItems.get(i).getiIsSelected()==1)
{
//set red text color
}
else
{
//set black text color
}
UI tasks can only be done on the UI Thread. If u want to run it from the handler, you have to define a runOnUiThread method. Take a look at this ans
how to use runOnUiThread
try this code:
for(int i=0;i<listView.getChildCount();i++) {
// yours code
View item = listView.getChildAt(i);
item.setBackgroundResource(R.drawable.your_image); //change image
((TextView)item.findViewById(R.id.text1)).setTextColor(Color.RED); //text1 is your cusotm listview item's text id
adapter.notifyDataSetChanged();?
}
I assume you use TextView , To change his text color, first you need to get him, when you create your Item, add id to TextView
with xml
<TextView
android:id="#+id/myId"...
Or if you use java
textView.setId(R.id.myId)
and in your code :
((TextView)listView.getChildAt(i).findViewById(R.id.myId)).setTextColor(ContextCompat.getColor(context, R.color.hint));
If you want to set the Item Background with your Drawble Image you can use
.setBackground(getResources().getDrawable(R.drawable.yourDrawble));
Make one method in your Adapter class to update text color and create one flag in Adapter that is initially false ,Use below method to do this
boolean isChangeColor = false;
String colorCode = "#FFFFFF";
private void updateTextColor(boolean isChangeColor , String colorCode) {
this.isChangeColor=isChangeColor;
this.colorCode=colorCode;
notifyDataSetChanged();
}
And in getView()
if(isChangeColor) {
textView.setTextColor(Color.parseColor(colorCode));
} else {
colorCode = "#FFFFFF";
textView.setTextColor(Color.parseColor(colorCode));
}
I am making use of recycler view. I have a layout that is highlighted in light red,this layout is included for each item in the recycler view. The light red layout is placed over the background image. I am using setTag method to identify the clicks of the buttons in red layout. That is working properly when i click i get the position. The problem is i want to change the image at specific position.
For example : Consider the heart button. I have set a tag on it like this.
heartButton = findViewById(id);
heartButton.setTag(position);
now i get the position by using the getTag method. But now i want to change the image of the heartButton at the a specific position. Is there something like
heartButton.getTag(position).setImageResouce(drawable);
If not how do i do this then.
use setBackgroundResource(R.drawable.XXX)
http://developer.android.com/reference/android/view/View.html#setBackgroundResource(int)
Proper way to do this is,
You have to keep the state of the heart button stored in the model(POJO) which is passed to custom adapter.
e.g.
class ModelListItem{
public static final int HEART=1,BROKEN_HEART=2;
int heartButtonState;
}
Now in onClick() of heart button, get that object from adapter using position,cosidering you have already figured it out on how to preserve position from heart button
ModelListItem item = (ModelListItem)adapter.getItem(position)
Change the state of heart button;
item.setHeartButtonState(ModelListItem.BROKEN_HEART);
adapter.notifyDatasetChanged();
You already know below explaination but just in case
To work this properly,in your getView methode of adapter you need to put the check on heartButtonState(); and use appropriate image resource.
getView(BOILERPLATE){
BOILERPLATE
switch(item.getheartButtonState()){
case ModelItemList.HEART:
heartbutton.setImageResource(heart_image);
break;
case ModelItemList.BROKEN_HEART:
heartbutton.setImageResource(broken_heart_image);
break;
}
I made a custom click listener and updated the like in the setter getter.But this works only when the view has been moved out of the view (i think it is the scrapeview)
The Setter Getter Class
public class DemoData {
int background;
boolean liked;
public DemoData(int background) {
this.background = background;
}
public int getBackground() {
return background;
}
// public void setBackground(int background) {
// this.background = background;
// }
public boolean isLiked() {
return liked;
}
public void setLiked(boolean liked) {
this.liked = liked;
}
}
The onBindViewHolder function of the recycler view
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
background = (ImageView) holder.view.findViewById(R.id.image);
layout = (LinearLayout) holder.view.findViewById(R.id.layout);
delete = (ImageView) layout.findViewById(R.id.delete);
lock = (ImageView) layout.findViewById(R.id.lock);
delete.setTag("delete_"+position);
lock.setTag("lock_"+position);
if(Constants.demoDatas.get(position).isLiked()){
delete.setImageResource(R.drawable.ic_launcher);
}
else{
delete.setImageResource(android.R.drawable.ic_delete);
}
delete.setOnClickListener(new CustomClickListener(position));
lock.setOnClickListener(new CustomClickListener(position));
}
The custom click listener is as below
public class CustomClickListener implements View.OnClickListener {
int position;
public CustomClickListener(int position) {
this.position = position;
}
#Override
public void onClick(View v) {
String tag = (String) v.getTag();
String identifier[] = tag.split("_");
// this line saves my state in the Setter Getter Class
Constants.demoDatas.get(position).setLiked(true);
}
}