Changing Recycler View item based on its data - java

So I have a POJO with a question, and in my recycler I wanna show a question itself with answers and correct answer should have the background color.
When I try to add background color, items get colored based on some serious magic.
First few items do not get any color, and closer to the bottom of the recycler here is what happens.
enter image description here
The further the better, when I scroll from the bottom to the top, items at the top get the color as well.
public void bind(Question question) {
int correctAnswerNumber = question.getCorrectAnswer();
switch (correctAnswerNumber) {
case 1:
answer1.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 2:
answer2.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 3:
answer3.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 4:
answer4.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
}
}
The context here is passed from the activity, and I have to ideas what to do.
I tried to remove the logic to the constructor, change the context, address items through holder, didn't change much.

You have a classic case of "stale state from a recycled view item".
Your Problem
You only set the background for a correct answer. When that item view is recycled and used for an incorrect answer, you are not updating it and it keeps the old background that was set on it.
The Solution
Always explicitly set the full state of a recycler item view. In this case, set the background for whatever it should be when it's not a correct answer.
public void bind(Question question) {
int correctAnswerNumber = question.getCorrectAnswer();
// Reset all backgrounds to default before setting the current correct one
answer1.setBackground(getDefaultBackgroundBorder());
answer2.setBackground(getDefaultBackgroundBorder());
answer3.setBackground(getDefaultBackgroundBorder());
answer4.setBackground(getDefaultBackgroundBorder());
switch (correctAnswerNumber) {
case 1:
answer1.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 2:
answer2.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 3:
answer3.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
case 4:
answer4.setBackground(AppCompatResources.getDrawable(context, R.drawable.correct_answer_border));
break;
}
}

Related

Button needs to be clicked twice. Any ideas why?

Basically what I'm trying to do is setting the color of the buttons. The "ganzjahrbutton" includes the other buttons. Therefore I wanna change the color of all the buttons (besides the ganzjahrbutton) to the grey color (162,162,162) if it's clicked.
If any of the other buttons is clicked, they should turn green and the ganzjahrbutton should become grey again. It kinda works, but the buttons need to be pressed twice.
Does anybody have an idea why?
switch (v.getId()){
case R.id.ganzjahrbutton:
ganzjahrbtnstate = !ganzjahrbtnstate;
if (ganzjahrbtnstate==true){
ganzjahrbutton.setBackgroundColor(Color.rgb(30,168,1));
fruhlungbutton.setBackgroundColor(Color.rgb(162,162,162));
sommerbutton.setBackgroundColor(Color.rgb(162,162,162));
herbstbutton.setBackgroundColor(Color.rgb(162,162,162));
winterbutton.setBackgroundColor(Color.rgb(162,162,162));
}
else {ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
case R.id.fruhlingbutton:
fruhlingbtnstate = !fruhlingbtnstate;
if (fruhlingbtnstate==true){fruhlungbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {fruhlungbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
case R.id.sommerbutton:
sommerbtnstate = !sommerbtnstate;
if (sommerbtnstate==true){sommerbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {sommerbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
case R.id.herbstbutton:
herbstbtnstate = !herbstbtnstate;
if (herbstbtnstate==true){herbstbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {herbstbutton.setBackgroundColor(Color.rgb(162,162,161));}
break;
case R.id.winterbutton:
winterbtnstate = !winterbtnstate;
if (winterbtnstate==true){winterbutton.setBackgroundColor(Color.rgb(30,168,1));
ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162)); }
else {winterbutton.setBackgroundColor(Color.rgb(162,162,162));}
break;
Move the lines where you change the boolean states to the end of cases just before break statements
case R.id.ganzjahrbutton:
****FROM HERE*****ganzjahrbtnstate = !ganzjahrbtnstate;****
if (ganzjahrbtnstate==true){
ganzjahrbutton.setBackgroundColor(Color.rgb(30,168,1));
fruhlungbutton.setBackgroundColor(Color.rgb(162,162,162));
sommerbutton.setBackgroundColor(Color.rgb(162,162,162));
herbstbutton.setBackgroundColor(Color.rgb(162,162,162));
winterbutton.setBackgroundColor(Color.rgb(162,162,162));
}
else {ganzjahrbutton.setBackgroundColor(Color.rgb(162,162,162));}
TO HERE*****ganzjahrbtnstate = !ganzjahrbtnstate;****
break;

Best way to create options in RPG

I am following a tutorial I found on youtube on creating a basic RPG with a GUI. The tutorial is very helpful in giving directions on how to handle panels and frames, but the way they handle user decisions seems very impractical. They have a switch case that uses the player's location, and then another switch case within that then handles the actions depending on what button the user enters. Im not saying that it doesn't get the job done, but it leads me to have a LONG switch case. I was wondering what would be the best approach to have a cleaner and more manageable code.
snippet of the code:
//depending on your position, you are given different action options
switch(position) {
//if you are in town, these are your options
case "townGate":
switch(yourOption) {
//talk to the guard
case "c1": talkGaurd(); break;
//attack the guard
case "c2": attackGuard(); break;
}
break;
//if you are talking to the guard, these are your options
case "talkingToGaurd":
switch(yourOption) {
//leave to the outside of the gate
case "c1": townGate(); break;
}
break;
//if you are attacking the guard, these are your options
case "attackingGuard":
switch(yourOption) {
//leave the the outside of the gate
case "c1": townGate(); break;
}
break;
}

Change TextSize with a spinner

I managed to change the color of a certain text with a spinner. But now I wanted to change the size of the same text with another spinner. I put the color cases inside a switch function to change the color.
like that
switch (i) {
case 0:
description.setText(des[i]);
preferences.edit().putInt(SELECTED_COLOR, Color.WHITE).apply();
break;
case 1:
description.setText(des[i]);
preferences.edit().putInt(SELECTED_COLOR, Color.BLUE).apply();
break;
I wrote all down but I dont know how to call the TextSize inside the case.
I thought it would work like that:
switch (d) {
case 0:
description2.setText(des2[d]);
preferences2.edit().putInt(SELECTED_SIZE, ????); <==
}
}
But I cant use TextSize or something like that.
To change the color I used Color.BLUE/RED/GREEN/... but now I want to change the TextSize... It is as always kind of difficult to explain my problem^^ sry for that.
If you want to use shared preferences and a switch statement like you do for your colors, you can do something similar to the following:
In your switch statement, similar to how you are handling color, add the text size associated with the selected spinner index to your shared preferences:
switch(i) {
case 0:
preferences.edit().putInt(SELECTED_SIZE, 16).apply();
break;
case 1:
preferences.edit().putInt(SELECTED_SIZE, 18).apply();
break;
// other cases go here...
}
Then, in the activity that includes the TextView whose text size you want to change (in this example, named textViewToChange), retrieve the saved value, and use it to set the text size:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
int selectedTextSize = preferences.getInt(SELECTED_SIZE, 0);
textViewToChange.setTextSize(TypedValue.COMPLEX_UNIT_SP, selectedTextSize);

How do I set an Edit Text back to it's original state

I have a simple calculator app. When the user presses calculate the edit text where they entered their number changes color and outputs the result. When reset is pressed I would like the line under the edit text to re-appear but it doesn't show up the way I current have my code written. This is a snipped of my current code.
#Override
public void onClick(View v){
switch (v.getId()){
case R.id.calculate:
myFunction.doWork();
voltageInputEditText.setBackgroundColor(Color.DKGRAY);
voltageInputEditText.setTextColor(Color.WHITE);
break;
case R.id.reset:
myFunction.reset();
voltageInputEditText.setText("");
voltageInputEditText.setBackgroundColor(Color.WHITE);
break;
}
}
This is the desired result
This is the current result
This is the look after I run myFunction.(doWork);
When you call setBackgroundColor internally it is calling setBackgroundDrawable with a ColorDrawable, so you're replacing the original background, the one that displays the line inside EditText.
Setting a white background color to begin with would equally remove this line.
It should work if you save the original background drawable via getBackground and later restore it via setBackgroundDrawable.
You should simply save it.
String savedInputText = "";
#Override
public void onClick(View v){
switch (v.getId()){
case R.id.calculate:
myFunction.doWork();
savedInputText = voltageInputEditText.getText();
voltageInputEditText.setBackgroundColor(Color.DKGRAY);
voltageInputEditText.setTextColor(Color.WHITE);
break;
case R.id.reset:
myFunction.reset();
voltageInputEditText.setText(savedInputText);
voltageInputEditText.setBackgroundColor(Color.WHITE);
break;
}
}

Switch statement in non-anonymous private OnClickListener class not working?

I've tried quite a few different tactics to achieve my desired result, but nothing is making these buttons do what they're 'sposed to... Basically I have 14 buttons. Four with the text "X", digitOne, digitTwo, digitThree and digitFour. Then, there are 10 with "1", "2", etc, named "one", "two", etc. All the buttons are tied to the same OnClickListener that will use a switch statement to determine which button was pressed, then find the soonest display button (buttons initially marked "X"), and change that buttons text to the entered digit. What I want to happen is:
Say someone clicks the "5" button. If its the first button pressed, the first "digit" button will change from displaying "X" to "5", and so-on, so-forth. This is not what is happening... In fact, nomatter what I've tried, nothing is happening. Not even an error... An error would be nice, at least I'd know where my logical flaw is -_-. Here's the code:
The button declarations:
one=(Button)findViewById(R.id.button1);
two=(Button)findViewById(R.id.Button2);
three=(Button)findViewById(R.id.Button3);
four=(Button)findViewById(R.id.Button4);
five=(Button)findViewById(R.id.Button5);
six=(Button)findViewById(R.id.Button6);
seven=(Button)findViewById(R.id.Button7);
eight=(Button)findViewById(R.id.Button8);
nine=(Button)findViewById(R.id.Button9);
zero=(Button)findViewById(R.id.Button0);
add=(Button)findViewById(R.id.buttonAdd);
digitOne=(Button)findViewById(R.id.Number1);
digitTwo=(Button)findViewById(R.id.Number2);
digitThree=(Button)findViewById(R.id.Number3);
digitFour=(Button)findViewById(R.id.Number4);
one.setOnClickListener(listener);
two.setOnClickListener(listener);
three.setOnClickListener(listener);
four.setOnClickListener(listener);
five.setOnClickListener(listener);
six.setOnClickListener(listener);
seven.setOnClickListener(listener);
eight.setOnClickListener(listener);
nine.setOnClickListener(listener);
zero.setOnClickListener(listener);
The OnClickListener private inner class (I guess that's what you'd call it. It's inside Activity class):
private OnClickListener listener = new OnClickListener(){
public void onClick(View button) {
switch(button.getId()){
case R.id.Button0:
addANumber(0);
break;
case R.id.button1:
addANumber(1);
break;
case R.id.Button2:
addANumber(2);
break;
case R.id.Button3:
addANumber(3);
break;
case R.id.Button4:
addANumber(4);
break;
case R.id.Button5:
addANumber(5);
break;
case R.id.Button6:
addANumber(6);
break;
case R.id.Button7:
addANumber(7);
break;
case R.id.Button8:
addANumber(8);
break;
case R.id.Button9:
addANumber(9);
break;
}
}
};
And finally, the "addANumber" method being called:
public void addANumber(int i){
if(digitOne.getText()=="X"){
digitOne.setText(i);
}else if(digitTwo.getText()=="X"){
digitTwo.setText(i);
}else if(digitThree.getText()=="X"){
digitThree.setText(i);
}else if(digitFour.getText()=="X"){
digitFour.setText(i);
}
}
I've done this before... I know I'm missing something so blatantly stupid it deserves a smack in the head...
Before all:
digitOne.getText()=="X" should be "X".equals(digitOne.getText())
you need checking for string equality in terms of content, not in term of reference.
Nothing happens because with == none of your if condition is evaluated to true and addANumber() simply results as an empty method

Categories

Resources