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.
Related
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 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.
Im trying to load custom callLogs in a listView based on date as section header.In ListAdapter i compare each date with the previous date and set SectionHeaderLayout Visible/Invisible. When the ListView has been loaded the section header are displayed correctly but when i scroll the section headers are set Visible to wrong ListItems.
Please help me to figure out a solution.
This is how im trying to set SectionHeader through the adapter.
if (position == 0) {
checkDate = mDateStr;
holder.sectionHeaderDate.setVisibility(View.VISIBLE);
holder.sectionHeaderText.setText(mDateStr);
}
} else if (checkDate == null || !checkDate.equals(mDateStr)) {
checkDate = mDateStr;
holder.sectionHeaderDate.setVisibility(View.VISIBLE);
holder.sectionHeaderText.setText(mDateStr);
} else {
holder.sectionHeaderDate.setVisibility(View.GONE);
}
Thanks in Advance
I see this is old question, you have probably solved your problem, but I'll answer for others who will have the same problem.
If you want to show header based on previous date you can't do that by remembering last item that was passed to getView function.
The reason is scrolling, i.e. different direction when going up and down.
For example, if you have items
1,
2,
3,
4,
5
when you're going down, and current item is 3, previous was 2, and all will work.
But if you are going up, your previous item for 3 was actually 4, and that's where your problem happens.
so instead of keeping item, you should use positions.
this would be the sketch of solution that you can call inside of your getView function:
private void showHeader(ViewHolder holder, Call item, int position) {
boolean shouldShowHeader = false;
if (position == 0
|| !DateHelper.isSameDay(item.getDateTime(),
items.get(position - 1).getDateTime()))
shouldShowHeader = true;
if (shouldShowHeader) {
holder.header.setVisibility(View.VISIBLE);
holder.date.setText(DateHelper.getSimpleDate(item.getDateTime()));
} else {
holder.header.setVisibility(View.GONE);
}
}
Ok im making app and it have 15 button's and 6 textview's.I want when I press first button to change value of first textview(value is "") to something (number one for example).But problem is when i press second button if first textview is already set to some value to set set second textview to second value.
If you need something else ask in comments (sorry for bad English)
here is what I was doing(this is under onclick)when i press second button
if(textview1.equals("1")){
textview2.setText("2");}
else if (textview1.equals("")){
textview1.setText("2");
}
It sounds like you wish to show last 6 buttons pressed.
Store all pressed buttons in a List (i.e. LinkedList) of size 6. Initially, it will be empty.
Then whenever any button is pressed do two things:
1) add it to the List and delete old elements if size exceeds six.
2) set button values from List.
Second step can be achieved like this:
// all TextViews should be in a list
private List<TextView> textViews;
// declare as field
private List<String> memoryQueue = new ArrayList<String>();
public void update() {
//set fields for the pressed buttons
for (int i=0; i<6 && i<memoryQueue.size(); i++) {
String text = memoryQueue.get(i);
textViews.get(i).setText(text);
}
// set empty fields
for (int i = memoryQueue.size(); i<6; i++) {
textViews.get(i).setText("");
}
}
This code snippet assumes that you store your TextViews in a List.
And Easiest way to keep track of last six button:
public void buttonPressed(Button button) {
//get text based on your button
String text = button.getText();
if (memoryQueue.contains(text)) {
return;
}
memoryQueue.add(text);
if (memoryQueue.size() > 6) {
memoryQueue.remove(0);
}
}
Since you're concerned with the text inside of your text view, you should be using the object's getText method:
if( textview1.getText().equals("1") ){ // Edited
textview2.setText("2");
} else if (textview1.getText().equals("")){ //Edited
textview1.setText("2");
}
At first, you have to get the String text from TextView using getText() method then you can compare that String with another String. Now, change your condition as follows...
if(textview1.getText().toString().equals("1")){
textview2.setText("2");}
else if (textview1.getText().toString().equals("")){
textview1.setText("2");
}
I have a ListView that contains multiple ListView items. The ListView items Layout contains an ImageView. I use this ImageView as a button. When the button is clicked it changes the ImageView from a gray image to a green image. But when I scroll the ImageView out of visible view and then back to it, it returns to its original color. When the ImageView is created it can be either green or gray, it depends on a JSON array. So if an image is green and clicked it turns to gray. Then when its out of visible view and returned to visible view it is green again! How can I make the images maintain their new state?
Here is my code,
if(p.getJSON().equals("NO")){
imageView.setBackgroundResource(R.drawable.gray);
imageView.setTag(0);
}//end if equals NO
if(p.getJSON().equals("YES")){
imageView.setClickable(false);
imageView.setBackgroundResource(R.drawable.green);
imageView.setTag(1);
}//end if equals yes
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View imageView) {
final int status = (Integer) imageView.getTag();
if (status == 0){
imageView.setBackgroundResource(R.drawable.green);
imageView.setTag(1);
}
else{
imageView.setBackgroundResource(R.drawable.gray);
imageView.setTag(0);
}
}//end on click
});
You need to persist the state for the items that you have modified with the button press and then restore that state when your adapter's getView() is called for that item.
There are many ways you can do this: in memory, database, etc. You'll have to pick the method that works best for your purposes.
i.e. - item 3 gets clicked and the image changes from grey to green, store something to represent the state of the image (grey vs. green, a boolean would be great for this exact case) and then persist that data somewhere. Then when getView() gets called again for item 3 (it's about to be displayed again) you set the color of the image based on the data you persisted for item 3.
You could just modify the value in the original JSONArray that backs the ListView, btw.
The reason for this behaviour is because you do not persist the state of the items (if they were clicked or not). Each time the list is scrolled, the getView() is called and it executes the following code and the state is reset:
if(p.getJSON().equals("NO") ){
imageView.setBackgroundResource(R.drawable.gray);
imageView.setTag(0);
}//end if equals NO
if(p.getJSON().equals("YES")){
imageView.setClickable(false);
imageView.setBackgroundResource(R.drawable.green);
imageView.setTag(1);
}//end if equals yes
What is needed is a way to keep track of the state of each item based on its position. So you could confidently tell: item at position k is "YES" or "NO"!
You need to keep track of the items which have been clicked so that when getView() is called, you can update the state of the based on its current value (not based on JSON value).
1) Maintain a map of items positions which are checked, and corresponding state value ("YES" or "NO").
2) If item is clicked, add its (position, new state) to the map. If it is clicked again, update its state inside the map.
3) Use this map and set the state of the item in the getView(), something like:
Private field:
HashMap<Integer, String> map = new HashMap<Integer, String>();
In your getView():
String state = p.getJSON();
if(map.containsKey(position)) {
state = map.get(position);
}
if(state.equals("NO") ){
imageView.setBackgroundResource(R.drawable.gray);
imageView.setTag(0);
}//end if equals NO
if(state.equals("YES")){
imageView.setClickable(false);
imageView.setBackgroundResource(R.drawable.green);
imageView.setTag(1);
}//end if equals yes
final int pos = position;
imageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View imageView) {
final int status = (Integer) imageView.getTag();
if (status == 0){
imageView.setBackgroundResource(R.drawable.green);
imageView.setTag(1);
map.put(pos, "YES")
}
else {
imageView.setBackgroundResource(R.drawable.gray);
imageView.setTag(0);
map.put(pos, "NO")
}
}//end on click
});
Note: this is just one of the many ways of getting what you want, however the basic idea should be the same..