I need to know how to check how to compare or check for an image resource on an image button
First I setup the button.
button1 = (ImageButton) findViewById(R.id.ib1);
button1.setImageResource(R.drawable.smiley);
if( currentTime%2==0 ) {
button1.setImageResource(R.drawable.smiley);
}
else {
button1.setImageResource(R.drawable.smileyhit);
}
Later at some point I need to check if the image resource of the button is the smiley drawable and increase the score.
something like
if( button1.getImageResource() == R.drawable.smiley ) {
score = score + 1;
}
What should I do to compare that? I do not want to use tags. Please help me out!
Use ImageButton.setTag and ImageButton.getTag to identify which image is currently in ImageButton background as:
if( currentTime%2==0 ) {
button1.setImageResource(R.drawable.smiley);
button1.setTag(R.drawable.smiley);
}
else {
button1.setImageResource(R.drawable.smileyhit);
button1.setTag(R.drawable.smileyhit);
}
use button1.getTag to check current image:
if(Integer.parseInt(button1.getTag().toString()) == R.drawable.smiley ) {
score = score + 1;
}
using setTag and getTag you can easily differentiate images.
if( currentTime%2==0 ) {
button1.setImageResource(R.drawable.smiley);
button1.setTag("smiley");
}
else {
button1.setImageResource(R.drawable.smileyhit);
button1.setTag("smileyhit");
}
if(button1.getTag().toString().equalsIgnoreCase("smiley")){
score = score + 1;
}
Maintain an array with currentTime%2==0 in it for each button. One should not depend on the UI to retrieve the state of the app since the UI is recreated at several different points in the life-cycle of an app. All your data which determines the state of the app should be seperated from the UI.
EDIT
Okie.. as you say you have more images, i still would go through array or list rather than depending on UI to get the data.My method would be as follows,
Create constants for each Image resource with an Int value
eg: public static final int image1=1;
create the int array for the number of images and maintain them with initial values.
Each time to you change the image change the corresponding array element accordingly.
To find out which resource is used, check the corresponding array element.
While restoring UI(like onResume) use the array to set the corresponding draw able resource.
Related
I tried to show a random imageView out of 2(one,two) with this
binding.imageView.setImageResource(oneandtwo[random.nextInt(oneandtwo.size)]) it works fine
and
i wanted to increase score when i clicked on imageView
but score increases independent to that, sometimes increases when i clicked on imageView2 and sometimes imageView, i want to increase score when i only clicked on imageView. i couldnt figure out. Thanks in advance.
var score = 0
val oneandtwo: IntArray = intArrayOf(
R.drawable.ic_baseline_looks_one_24,
R.drawable.ic_baseline_looks_two_24
)
binding.imageView.setOnClickListener{
val random = Random
binding.imageView.setImageResource(oneandtwo[random.nextInt(oneandtwo.size)])
if (oneandtwo[random.nextInt(oneandtwo.size)]==(R.drawable.ic_baseline_looks_one_24)){
score++
binding.textView.text = score.toString()
}
}
The number you gave in the image and the number you checked in the if block may not match and will not give the result you want. If you change code like this. Probably your problem will be solved.
binding.imageView.setOnClickListener{
val random = Random().nextInt(oneandtwo.size)
binding.imageView.setImageResource(oneandtwo[random])
if (oneandtwo[random]==(R.drawable.ic_baseline_looks_one_24)){
score++
binding.textView.text = score.toString()
}
}
What you are doing is checking the resourceId of the newly generated image, not the one you just clicked. That's why it not giving the result you want ,i.e, increment on the click of imageView and not on click of imageView2. Try below code. it should work
var score = 0
val oneandtwo: IntArray = intArrayOf(R.drawable.ic_baseline_looks_one_24,R.drawable.ic_baseline_looks_two_24)
/*Initalize the initial image and tag either here or in xml file*/
val random = Random().nextInt(oneandtwo.size)
binding.imageView.setImageResource(oneandtwo[random])
binding.imageView.Tag = oneandtwo[random]
binding.imageView.setOnClickListener{
val imageTag = binding.imageView.Tag
if (imageTag == (R.drawable.ic_baseline_looks_one_24)) {
score++
binding.textView.text = score.toString()
}
val random = Random().nextInt(oneandtwo.size)
binding.imageView.setImageResource(oneandtwo[random])
binding.imageView.Tag = oneandtwo[random]
}
You've got two problems that both the answers cover - if clicking a particular image is meant to give you points, you have to check the image before you change it. And if you're using random items, you need to pick one and keep a reference to it. This:
binding.imageView.setImageResource(oneandtwo[random.nextInt(oneandtwo.size)])
if (oneandtwo[random.nextInt(oneandtwo.size)]==(R.drawable.ic_baseline_looks_one_24))
picks two completely independent numbers which may not match - and they're supposed to be referencing the same item, right? Get your random thing once, use it twice
RahulK's answer should work but here's another way you could do it, with an explicit listener object so you can throw a state variable in there:
binding.imageView.setOnClickListener(object : View.OnClickListener {
// keep track of whether the current image adds to the score when clicked
var givesPoints = false
override fun onClick(view: View) {
// first, we just got clicked, so add to the score if appropriate
if (givesPoints) score++
// you can just call random() on a collection to get a random element from it
val resId = oneAndTwo.random()
// set the image - might be better to do (view as ImageView).setImageResource
// so it sets it on -whatever was clicked- so it's easier to reuse
binding.imageView.setImageResource(resId)
// now set whether this new image gives points or not
givesPoints = resId == R.drawable.ic_baseline_looks_one_24
}
})
So this way, every time you set a new image, the listener knows whether to give points for it next time it's clicked
I don't know how you have this set up, you're only initialising things when the image is clicked so if you need to set them up beforehand (so you can have an image displayed that you an click for points) you probably want everything in a separate function you can call when clicked and during setup:
/** Assigns a random picture to this ImageView - returns true if it's a point-scoring pic */
fun assignRandomPic(imageView: Imageview): Boolean {
val resId = oneAndTwo.random()
imageView.setImageResource(resId)
return resId == R.drawable.ic_baseline_looks_one_24
}
// set an initial image, storing whether it scores points
val scoreMe = assignRandomPic(binding.imageView)
binding.imageView.setOnClickListener(object : View.OnClickListener {
// initialise this as appropriate for the image we just set up
var givesPoints = scoreMe
override fun onClick(view: View) {
if (givesPoints) score++
// set a new pic and store its point-scoring state
givesPoints = assignRandomPic(view as ImageView)
}
})
or you could just do var givesPoints = assignRandomPic(binding.imageView) and init the image inside the click listener, whatever feels better
This is driving me a little mad since I know this should be very simple but I am not getting the desired affect.
I have the following arraylist
private List<String> tagStringArray = new ArrayList<>();
Then later I have a method that creates dynamic buttons, based on ID values pulled across from my Retrofit instance.
In my method, I have a count to help me set the title of the button but I also add the values of count to an ArrayList for use in another method.
I have taken a snip of relevant information from the method mentioned.
count = 1;
if (!questionNumber.equals("") && !questionNumber.equals(null)) {
for (final Object value : list) {
try {
/*Dynamically create new Button which includes the question number
*/
final AppCompatButton btn_question = new AppCompatButton(getActivity());
/*LayoutParams (int width, int height,float weight)
As LayoutParams is defaulted in px, I have called a method called dpToPX to make sure
the dynamically added EditText is the same size on all devices.
*/
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(dpToPx(280), dpToPx(45), 1);
btn_question.setBackgroundColor(Color.parseColor("#3B5998"));
btn_question.setTextColor(Color.WHITE);
btn_question.setText("Question "+count);
//set the Tag based on its position in the XML
tagStringArray.add(String.valueOf((count)));
count++;
If a user clicks on say Question 1 Button, I want my fragment to say Question 1, so to try and achieve that, I have tried doing the following:
String tags = String.valueOf(tagStringArray);
tags = tags.substring(1, tags.length() -1);
String[] currentTag = tags.split(",");
if (currentTag[0].contains("1")) {
tv_setQuestions_edit.setText("Question 1");
}else if(currentTag[1].contains("2")) {
tv_setQuestions_edit.setText("Question 2");
}
But this will always set the title to Question 1 and I am not sure what is going wrong.......
If I use the following toast Toast.makeText(getActivity(), Arrays.toString(currentTag), Toast.LENGTH_LONG).show(); it shows [1,2] so I know they are being added ok.
I did look into using tags by doing:
public static int KEY_COUNT=0; public static int KEY_VALUE=1;
btn_question.setTag(KEY_VALUE,value);
btn_question.setTag(KEY_COUNT,count);
But for some reason, when I add more than one tag (as I need a minimum of 2), my dynamic button is missing from the layout. But for some reason when only 1 tag - like this btn_question.setTag(value); is used, it shows up fine (I have a feeling its some issue with my fragment). Therefore I am trying to think of a workaround in the meantime.
Any help or guidance would be really appreciated.
It's because
currentTag[0].contains("1")
is always true. The first item of currentTag always contains "1".
Instead of doing this, why don't you just do String titleForFragment = myButton.getText() in the onClick method for the button? That way, you can set the same onClickListener on all the buttons, and it will reduce the amount of code you need to write.
I'm creating a memory app (you know where you have to select 2 images and match them). I'm looking for a way to check when there are no images left so I can show a message.
I have this code to check if the images match. I'm working with 2 arrays, 1 holds the imageviews and their position in the grid (playfield) and one holds the reference for which image is on that imageview (cards).
private void checkCards() {
if (cards[value1] == cards[value2]) {
playfield[value1].setBackgroundResource(R.drawable.border_red);
playfield[value2].setBackgroundResource(R.drawable.border_red);
playfield[value1].setClickable(false);
playfield[value2].setClickable(false);
score++;
} else {
playfield[value1].setImageResource(R.drawable.back);
playfield[value2].setImageResource(R.drawable.back);
}
value1 = -1;
value2 = -1;
}
I need to check on one of these conditions:
There are no more imageviews without a red border
There are no more imageviews that are clickable
There are no more imageviews with the R.drawable.back imageresource
However I'm not sure on how to do this? Do any of you have an idea or even a better method?
Thanks in advance!
I would keep a counter of each one, I can think on more complicated solutions, but a pretty straightforward one will be to have a counter and increase that counter when you're assigning the clickables, the borders, etc... e.g:
private void checkCards() {
if (cards[value1] == cards[value2]) {
playfield[value1].setBackgroundResource(R.drawable.border_red);
playfield[value2].setBackgroundResource(R.drawable.border_red);
playfield[value1].setClickable(false);
playfield[value2].setClickable(false);
mCounterClickables--; // one less clickable
mRedDrawables++; // one more Red Drawable
mBlackDrawables--;
score++;
} else {
playfield[value1].setImageResource(R.drawable.back);
playfield[value2].setImageResource(R.drawable.back);
mBlackDrawables++; //
}
value1 = -1;
value2 = -1;
}
Then to validate that you're done:
public boolean imDone() {
return mBlackDrawables == 0 && mCounterClickables== 0
&& mRedDrawables == playfield.length;
}
Does it makes sense?
In this way you don't have to iterate over and over again, you will always have track of what the user has done.
Btw. The initial state of your variables should be something like this:
int mBlackDrawables = 0, mCounterClickables = playfield.length, mRedDrawables = 0;
I have a spinner with a few values and I fill it from my webservice.
Filling the spinner
int i = 0;
var dropItems = new List<SpinItem2>();
DataRow[] result = myOPTvalues.Tables[0].Select("FieldValue=" + item.FieldValue);
foreach (DataRow row in result)
{
var optItem = new PrevzemSpin();
optItem.FieldValue = row["FieldValue"].ToString();
if (optItem.FieldValue.Equals(""))
optItem.FieldValue = null;
optItem.FieldTextValue = row["FieldTextValue"].ToString();
if (optItem.FieldTextValue.Equals(""))
optItem.FieldTextValue = null;
dropItems.Add(new SpinItem2(i, optItem.FieldValue.ToString(), optItem.FieldTextValue.ToString()));
}
i = 1;
foreach (DataRow row in myOPTvalues.Tables[0].Rows)
{
var optItem = new PrevzemSpin();
optItem.FieldValue = row["FieldValue"].ToString();
if (optItem.FieldValue.Equals(""))
optItem.FieldValue = null;
optItem.FieldTextValue = row["FieldTextValue"].ToString();
if (optItem.FieldTextValue.Equals(""))
optItem.FieldTextValue = null;
if (optItem.FieldValue != item.FieldValue)
{
dropItems.Add(new SpinItem2(i, optItem.FieldValue.ToString(), optItem.FieldTextValue.ToString()));
}
++i;
}
For some reason it acts like the item that was inserted first is "selected" on default and then triggers the ItemSelected event which I use to send the selected but I don't want that.
Since there's quite a number of these spinners on my screen it really slows down the activity plus it also sends the incorrect values to the field and since I use the ItemSelect to detect if everything went OK (let's say the service fell or the values themselves changed on server (someone added a new field on the server application) while the user is completing the form etc.)
Is there someway to tell the app not to trigger that on activity load but on actual user interaction?
I can't speak for Android specifically, but I have encountered this many times with Windows.
The solution I usually use is to simply add a boolean loading variable. Set it to true at the beginning of your initialisation and then clear it at the end.
In your event handlers like ItemSelected you can simply check if this is being triggered as the result of the initial load.
private void onItemSelected(....)
{
if(loading)
{
return; //Ignore as form is still loading
}
//Normal event handling logic goes here
....
}
Before I declared GetView:
int LastSpinnerSelectedPosition;
Inside my spinner definition:
LastSpinnerSelectedPosition = 0;
My spinner ItemSelected event:
var CurrentSelectedIndex = SpinnerValue.SelectedItemPosition;
if (CurrentSelectedIndex != LastSpinnerSelectedPosition)
{
// WHATEVER I WANTED TO DO ON ITEM SELECT ANYWAY
// Fix the LastSpinnerSelectedPosition ;)
LastSpinnerSelectedPosition = CurrentSelectedIndex;
}
Simple ;D
Just for clarification, the event fires when an item is selected. The semantics are obviously flawed, but technically the item IS selected when it initially loads since you can then immediately ask the spinner for which item is selected, so as the other answers say, just ignore the first time it is selected since it's guaranteed to be the loading select, and then proceed as normal after that.
I have 20 cards of which there are 10 pair of images. The player is meant to find a match of each card/image.
The problem is that if a player taps or clicks each card twice then that card gets decremented from the remaining ones . I need to disable the click listener of the ImageView. How can do that?
ivOne = (ImageView)findViewById(R.id.ivOne);
ivOne.setId(a[0]);
//final ImageView ivOne = (ImageView)findViewById(R.id.ivOne);
//ivOne.setEnabled(false);
ivOne.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
ivOne.setBackgroundResource(images[a[0]]);
Log.e("r[0]:", Integer.toString(a[0]));
if (firstTap)
{
firstId = v.getId();
firstTap = false;
}
else
{
//ivOne.setEnabled(false);
int secondId = v.getId();
Log.e("secondId", Integer.toString(secondId));
if ((secondId == firstId) && (score != 0))
{
//ivOne.setEnabled(false);
if (ivOneScored == false)
{
score--;
ivOneScored = true;
}
}
firstTap = true;
}
tvScore.setText("Remaining:" + Integer.toString(score));
}
});
I have a memory matching game on the market that works very similar. What I did was make a class that represents the card (with image and id properties) and assign an id (0-9) to the cards and the image as I loaded them into a temporary arraylist of just the 10 image objects.
public class GameTile {
public int id;
public Drawable image;
}
Then I iterated over the list twice and added the cards to the main arraylist that I use for my adapter... after which I used Collections.shuffle to shuffle the cards... Now... on to the selection. AS you know, in a memory game, you only want 2 cards flipped at any time. I am using a gridview to hold my cards... so what I did was use the OnItemClickListener from the gridview and not the imageview. Secondly, when a card is clicked, I add the position to another arraylist called "selected" that never contains more than 2 items... the position of the items we are attempting to match... In the OnItemClickListener, when the event is fired, I check to see if the item already exists in "selected" and return if it does... in effect ignoring the click.
if (selected.contains(position)) {
return;
}
When "selected" contains 2 items, I ignore all clicks until the handler finishes checking for a match.
if (selected.size() > 1) {
return;
}
So when a user has selected 2 items, I set a handler to call a runnable that checks for a match. If a match is made (by comparing the id fields I set when I first loaded the images), I add the two positions to another arraylist that contains only matched items and that handler also clears "selected" and, if there were matches, I change the images to blanks. When all 20 cards have been matched I fire a win which does all of the win stuff and resets the gameboard.
You have to make sure that those cards have the same symbol, but are not the same card.
So your line
if ((secondId == firstId) && (score != 0))
must rather look like something in the lines of
if ((firstCard != secondCard) && (secondId == firstId) && (score != 0))
where firstCard and secondCard identify the card on the table (not the symbol on the card)
If I understand you right, you just need to say view.setOnClickListener(null) if those two match? If you want to disable both of them, you just store a map to link an ID to a View, and then clear the click listener for both "view" and whichever view belongs to the second ID.