I am trying to build an android app that gets some questions from a database and its possible answers (the answers are created dynamically as UI buttons). What I have managed so far is that once the user clicks on an answer, if the answer is right the button's colour becomes green, and if the answer is wrong the colour becomes red. What I want to achieve is in case the answer was wrong, change the button's colour to red and find the button with the correct answer and change it's colour to green. I am currently trying to do this by looping through every child element of the clicked button's parent, and comparing its text with the right answer given from the database. This is what my code looks like:
final TableRow textRow = new TableRow(this);
textRow.addView(questionText, rowParamsQuestions);
layout.addView(textRow, layoutParams);
for(final String option : currentQuestion.getOptions())
{
final Button button = new Button(this);
button.setText(option);
button.setTextSize(16);
button.setBackgroundResource(R.drawable.rounded_shape);
button.setTextColor(Color.WHITE);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button clicked = (Button) v;
if (!answeredQuestions.containsKey(currentQuestion)) {
answeredQuestions.put(currentQuestion, clicked.getText().toString());
if (clicked.getText().equals(currentQuestion.getAnswer())) {
clicked.setBackgroundResource(R.drawable.right_answer);
} else {
clicked.setBackgroundResource(R.drawable.wrong_answer);
for (int i = 0; i < textRow.getChildCount(); i++) {
View child = textRow.getChildAt(i);
if (child instanceof Button) {
if (((Button) child).getText().equals(currentQuestion.getAnswer())) {
child.setBackgroundResource(R.drawable.right_answer);
}
}
}
}
Thank you very much!
Related
I recently started learning to code with Android Studio. And I wanted a button when clicked to toggle between two images, but I cant seem to compare them.
I tried comparing them but it doesn't think they are the same.
ImageView dog = new ImageView(this);
dog.setImageResource(R.drawable.dog);
ImageView goofy = new ImageView(this);
goofy.setImageResource(R.drawable.goofydog);
if(img==dog)
{
img.setImageResource(R.drawable.goofydog);
}
else{
img.setImageResource(R.drawable.dog);
}
You can only compare primitive types (String, Int, Double...) in If statements, if you compare object it will compare the instance of each object which in your case is different.
If you want to toggle between two images based on what your imageView is actually displaying you should compare the Int resources that is displayed like that :
Image img = findViewById(R.id.image_view);
Button button = findViewById(R.id.button);
String current = "";
button.setOnClickListener(new View.OnClickListener( v-> {
#Override
void onClick(View v){
if (img.getDrawable() == ResourcesCompat.getDrawable(getResources(),
R.drawable.dog, null)) {
img.setImageResource(R.drawable.goofyDog);
} else {
img.setImageResource(R.drawable.dog);
}
}
}));
If you want to learn more about using objects in If statement, you can learn more about instance of object here : https://en.wikipedia.org/wiki/Instance_(computer_science)
You can't compare images the way you are doing. If you want to toggle between two images using a button, you can simple do:
Image img = findViewById(R.id.image_view);
Button button = findViewById(R.id.button);
String current = "";
button.setOnClickListener(new View.OnClickListener( v-> {
#Override
void onClick(View v){
if (current = "Dog") {
img.setImageResource(R.drawable.dog);
current = "Dog";
} else {
img.setImageResource(R.drawable.goofydog);
current = "Goofy";
}
}
}));
What I need is for the textview to be added onto a linear layout where it will look organised and nice. Whenever the button is clicked again, it should replace the old textview and update it again.
At the moment, the button onclick listener will produce a textview, but I don't like it because it looks messy and unorganised.
I tried doing this:
varlinear.addView(varkebabTotal);
but it caused an error.
I have looked at other examples but they didn't explain how it will work with an onlick listener.
Here's the code for what happens when the button is clicked:
varKebab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name = "Kebab Wrap";
if (menu.containsKey(name)) {
kebabquantity = list.get(name);
if (kebabquantity == null) {
kebabquantity = 0;
}
kebabquantity++;
list.put(name, kebabquantity);
//kebab qty calc
double kebabTotal = kebabquantity * menu.get(name);
overallTotal = overallTotal + menu.get(name);
varkebabTotal.setText(String.format("%s %s # £%s = £%.2f", kebabquantity.toString(), name, menu.get(name), kebabTotal));
varTotalPrice.setText(String.format("Total = £%.2f", overallTotal));
varlinear.addView(varkebabTotal); // this line caused an error
}
}
});
Edit:
The error I received is when I tested the app, and when I click the button, the app stops. It shuts itself down due to that one line: varlinear.addView(varkebabTotal);
The variables are as follows:
varkebabTotal = (TextView) findViewById(R.id.kebabTotal);
varTotal = (TextView) findViewById(R.id.TotalPrice);
varlinear = (LinearLayout) findViewById(R.id.myLinear);
one method you can try is to set varkebabTotal.setVisibility(View.GONE); when you initialize the TextView, and then on your onClick event, you can change it to varkebabTotal.setVisibility(View.VISIBLE);
i am developing/designing a quiz application in android, on the testActivity i have
a TextView which loads the questions and four answer(alternatives) buttons.
btnAnswer1, btnAnswer2, btnAnswer3, and btnAnswer4.
Problem:When i click on btnAnser1 as my answer, it should remain in selected state, however it should also be possible to unselect(normal state) it if i doubt the answer. and lastly if its selected, and i decide to go for btnAnswer2 whiles btnAnswer1 is selected, immediately i select btnAnswer2, btnAnswer1 should be unselected(normal) whiles btnAnswer2 is selected.
i hope my question is clear and it sounds quiet easy but am still new in android programming so will appreciate the help.
thanks.
optionone = (Button) findViewById(R.id.optionone);
optionone.setTag(1);
optionone.setId(i);
//optionone.setBackgroundColor(Color.parseColor("#F1F1F1"));
optionone.setBackgroundColor(Color.parseColor("#F1F1F1"));
optionone.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.setSelected(true);
checkAnswer();
final int change = (Integer) v.getTag();
if (change == 1) {
optionone.setBackgroundColor(Color.parseColor("#B2B2B2"));
back.setVisibility(View.VISIBLE);
next.setVisibility(View.VISIBLE);
v.setTag(0);
} else {
optionone.setBackgroundColor(Color.parseColor("#F1F1F1"));
back.setVisibility(View.GONE);
next.setVisibility(View.GONE);
v.setTag(1);
}
}
});
Try to use toggle buttons instead of buttons, or just change background color of buttons when they pressed, not state.
I have a 3x3 GridLayout with buttons. These buttons have a onTileClicked() listener. Now I want to get the position of the clicked button in the grid. Here is my code:
public void onTileClicked(View view) {
Button button = (Button) view;
GridLayout.LayoutParams params = (LayoutParams) button.getLayoutParams();
}
But how can i get the row and column of the clicked button? There is params.columnSpec but I don't know what to do with this...
There is no direct way to get the position of the cell. However, you can calculate the position of the clicked button assuming you know the number of columns and rows in the onItemClick listener:
public void onItemClick(AdapterView parent,
View v, int position, long id)
{
int row_no=position/3;
int col_no=position%3;
.
.
}
Thanks for your answer AmmarCSE, but I solved the broblem by just doing something like this:
public void onTileClicked(View view) {
Button button = (Button) view;
if(button.getId()==R.id.btn00)onTileClicked(0, 0, button);
else if(button.getId()==R.id.btn01)onTileClicked(0, 1, button);
else if(button.getId()==R.id.btn02)onTileClicked(0, 2, button);
else if(button.getId()==R.id.btn10)onTileClicked(1, 0, button);
else if(button.getId()==R.id.btn11)onTileClicked(1, 1, button);
else if(button.getId()==R.id.btn12)onTileClicked(1, 2, button);
else if(button.getId()==R.id.btn20)onTileClicked(2, 0, button);
else if(button.getId()==R.id.btn21)onTileClicked(2, 1, button);
else if(button.getId()==R.id.btn22)onTileClicked(2, 2, button);
}
This may be old, but i also looked for a solution and still did not find it.
I needed to make multiple lines of button depending on users choice for a game. Using ID's was not possible because the number of buttons could vary from 2x2 to 9x9.
My button did not need to have a caption, so here is what i did:
layout = (GridLayout) findViewById(R.id.layoutPrincipal);
context = this;
for(int i=0;i<rowCount;i++){
for(int j=0;j<columnCount;j++){
Button mButon= new Button(this);
mButon.setText(""+i+""+j);
mButon.setTextColor(Color.TRANSPARENT);
mButon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Button button = (Button) v;
//button.getText() allows me to retrieve the coordinates.
button.getText()
}
});
layout.addView(mButon);
}
}
Of course this won't work if you need a text on your button. Maybe you could use a tag?
I am facing the same problem and currently the only solution that makes me comfortable is to modify the class and add whatever information you need.
My example is
class ImageView extends android.widget.ImageView {
public ImageView(Context context) {
super(context);
}
//the position of the plane head.
int xPos,yPos;
public void setPosInGrid(int x,int y) {
xPos=x;yPos=y;
}
public int[] getPosInGrid() {
int[] pos=new int[2];
pos[0]=xPos;
pos[1]=yPos;
return pos;
}
}
And now we can use this additional functionality. We can also rewrite the setLayoutParams and integrate the setPosInGrid() into it.
No modification of other codes is required except when you want an ordinary ImageView just use the full identifier "androi.widget.ImageView".
I have an EditText field that represents an ID number. That field can either be filled programmatically, using IDField.setText(String) based on the results of a card swipe, or it can be filled manually using the keyboard.
Once the text is filled both methods (auto login--based on swipe, or manual--based on button click) both run the same sign in script. However when I go to grab the contents of the EditText field, if I edited the text manually I get an empty string returned. If the text was set programmatically then it works perfectly.
This doesn't make any sense to me. Is there a reason that editText.getText().toString() would not return the content that is visibly shown in the textbox?
XML:
<Button
android:id="#+id/btn_swipeCard"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/signInID"
android:layout_toLeftOf="#+id/textView1"
android:onClick="SignInStudent"
android:text="Swipe ID" />
Button Initialization:
IDField = (EditText) layout.findViewById (R.id.signInID);
LoginButton = (Button) findViewById(R.id.button1);
LoginButton.setOnClickListener(new OnClickListener() { public void onClick(View v) { SignInStudent(); } } );
Card Swipe:
// displays data from card swiping
private Runnable doUpdateTVS = new Runnable()
{
public void run()
{
try
{
//Grab ID Number
String[] splitMSG = strMsrData.split("=");
//txtIDNumber.setText(splitMSG[2]);
IDField.setText(splitMSG[2]);
StringBuffer hexString = new StringBuffer();
hexString.append("<");
String fix = null;
for (int i = 0; i < msrData.length; i++) {
fix = Integer.toHexString(0xFF & msrData[i]);
if(fix.length()==1)
fix = "0"+fix;
hexString.append(fix);
if((i+1)%4==0&&i!=(msrData.length-1))
hexString.append(' ');
}
hexString.append(">");
myUniMagReader.WriteLogIntoFile(hexString.toString());
SignInStudent();
}
catch(Exception ex)
{
ex.printStackTrace();
}
}
};
Sign In Logic:
public void SignInStudent()
{
String temp = "http://wwww.tempUrl.com/signIn?ID="+ IDField.getText().toString() + "&DeviceId="+KEY;
webView.loadUrl(temp);
}
The layout is only updated during the onCreate phase of the loop. This is fired when an onResume event is called as well which explains why the fields update after you lock and unlock the device. There are a few workarounds for this such as doing more background processing and then creating a new view with correct values, or using a surfaceView that allows drawing to occur while the program is in its normal execute cycle.
For my application I either do background processing and then move to a new view, or have a view that just keeps calling itself to get the onCreate events to fire again. The solution depends on the application, but that's why the problem occurs.