onClick logic based on image displayed - java

How do you change what onClick is doing based on the image that is displayed when clicked? I have an ImageView that changes the image to one of a set randomly in an onClick method. I would like this to set a score based on the image when clicked, and am unsure of how to accomplish this. I'm currently updating the score when the image changes as part of the prototype, but for actual game play this won't work. Not looking for the answer, so much as being pointed in the right direction. My first thought was to pull the image name as a string and compare that, but doing that every time an image is clicked seems inefficient. I can post the onClick method for the ImageView if requested, but it's not really relevant. Any help is appreciated.
Edit: To clarify, I'm not having any particular problem. I'm just wrong on my approach. What I have updates the score when the image changes, and I want to complete this based on the image that is being clicked. Should this be done with string comparison, or is there a better way to complete this? I haven't been able to find anything related to this so far.
final ImageView block1 = (ImageView) findViewById(R.id.coin1);
block1.setOnClickListener(new View.OnClickListener() {
#SuppressLint("SetTextI18n")
#Override
public void onClick(View view) {
final TypedArray imgs = getResources().obtainTypedArray(R.array.apptour);
final Random rand = new Random();
final int rndInt = rand.nextInt(imgs.length());
final int resID = imgs.getResourceId(rndInt, 0);
TextView id = (TextView) findViewById(R.id.ID);
block1.setImageResource(resID);
if (rndInt == 0 || rndInt == 1) {
score++;
id.setText("Score: " + score);
} else if (rndInt == 2) {
score += 5;
id.setText("Score: " + score);
} else {
id.setText("Game Over");
}
}
});

Related

The animation for my programatically created button acts weird in my application

So I am facing a weird bug I cannot explain - I cannot even reproduce it sometimes.
Basic context:
I have an application, which lists objects. Every object has a name and a point value. For every object, the addCustomSpinner function creates a "ticket" (a custom view, kind-of-spinner) and shows them in a scrollview so the user can select the one needed. There are four different 'containers' for four different kind of objects - so the layout can be populated with four kind of "ticket" package.
The data for the objects are collected from a database. The addCustomSpinner is called with a for cycle for every object in the database, and - Important - before the for method, the Layout it populates with the tickets is cleared (removeAllViews).
Inside addCustomSpinner, everything is created as "new" - like the button in question.
addCustomSpinner creates this button and adds a new onClickListener. Inside onClickListener, a new boolean is created - this is used to show a different animation when the button is clicked again. On first click (boolean = true), the arrow turns 180 degrees and faces upwards, on second click (boolean = false) the arrow turns 180 degrees and faces downwards. Works like a charm, until...
The bug I am facing:
Sometimes - as I already mentioned, not every time - if I click the button for one "ticket", then leave it 'opened' and click on an another one, and leave it 'opened' also, THEN I choose to populate the layout with a different kind of "ticket" package - The arrow faces upwards by default on every ticket in every package! Sometimes - again, just sometimes - with the same pattern I can turn it back, but it happens just "by accident".
I don't understand how the animation and state of the buttons can be connected, if every created ticket is new, every button is new, every onClickListener is new, and every boolean inside onClickListener is new. And if these are connected somehow, then why can that be that every behavior is "unique" for the buttons, nothing else shows any connection - even this is just a "sometimes" bug, a pretty rare one.
Can anybody help me why this happens?
What I tried:
Well, tried to trace the issue - but since it happens just by accident, I have no clue, I just searched if I can do anything else than the boolean to add different animation for the clicks. Sadly using ObjectAnimator is not a good solution for me - not the same result at least, since my animated arrow not only rotates, but it also changes its color. Shapeshifter seemed like a good idea to create animations easily, but now as I see it, maybe a simple rotation will be my ultimate solution.
Here's the code for the button:
customButton.setOnClickListener(new View.OnClickListener() {
boolean isCustomButtonClicked = true;
#Override
public void onClick(View v) {
if (isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue_back);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(View.VISIBLE);
isCustomButtonClicked = false;
} else if (!isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(GONE);
isCustomButtonClicked = true;
}
}
});
EDIT:
The full addCustomSpinner():
private void addCustomSpinner(Routes mRouteItemToAdd, String placeName) {
//creating a new View for my custom layout created in xml
View customRoutesView = new View(this);
LinearLayout.LayoutParams customViewParams = new LinearLayout.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
customRoutesView.setLayoutParams(customViewParams);
customRoutesView = LayoutInflater.from(this).inflate(
R.layout.custom_view_layout, routeLayout, false
);
//Setting up the views inside the custom view
ImageView imageViewDiffImage = customRoutesView.findViewById(R.id.routeDiffImageView);
TextView textViewRouteName = customRoutesView.findViewById(R.id.routeNameTextView);
TextView textViewRouteDiff = customRoutesView.findViewById(R.id.routeDiffTextView);
ImageButton customButton = customRoutesView.findViewById(R.id.customButton);
RadioButton climberNameOne = customRoutesView.findViewById(R.id.climberNameOne);
RadioButton climberNameTwo = customRoutesView.findViewById(R.id.climberNameTwo);
Button climbedItButton = customRoutesView.findViewById(R.id.climbed_it_button);
RadioGroup climberNameRadioGroup = customRoutesView.findViewById(R.id.climberNameRadioGroup);
RadioGroup climbingStyleRadioGroup = customRoutesView.findViewById(R.id.styleNameRadioGroup);
RelativeLayout routeWhoClimbed = customRoutesView.findViewById(R.id.routeWhoClimbedRelativeLayout);
imageViewDiffImage.setImageResource(R.mipmap.muscle);
textViewRouteName.setText(mRouteItemToAdd.name);
textViewRouteDiff.setText("Difficulty: " + (int) mRouteItemToAdd.difficulty);
climberNameOne.setText(climberName1);
climberNameTwo.setText(climberName2);
routeWhoClimbed.setVisibility(GONE);
//Here comes the button with the animated image
customButton.setOnClickListener(new View.OnClickListener() {
boolean isCustomButtonClicked = true;
#Override
public void onClick(View v) {
if (isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue_back);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(View.VISIBLE);
isCustomButtonClicked = false;
} else if (!isCustomButtonClicked) {
customButton.setImageResource(R.drawable.avd_anim_arrow_blue);
Drawable d = customButton.getDrawable();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
if (d instanceof AnimatedVectorDrawable) {
animArrowAnim = (AnimatedVectorDrawable) d;
animArrowAnim.start();
}
}
routeWhoClimbed.setVisibility(GONE);
isCustomButtonClicked = true;
}
}
});
//Button, works like an 'OK' or something, and I have no
//problem with this
climbedItButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int checkedNameButton = climberNameRadioGroup.getCheckedRadioButtonId();
int checkedStyleButton = climbingStyleRadioGroup.getCheckedRadioButtonId();
RadioButton checkedNameRadioButton = (RadioButton) findViewById(checkedNameButton);
RadioButton checkedStyleRadioButton = (RadioButton) findViewById(checkedStyleButton);
String checkedName = (String) checkedNameRadioButton.getText();
String checkedStyle = (String) checkedStyleRadioButton.getText();
addClimbToDatabase(user.getUid(), checkedName, mRouteItemToAdd, placeName, checkedStyle);
}
});
//And finally, I add this new "ticket" with the custom view to the layout i want to show it. Again, this also works like a charm, no problem here.
routeLayout.addView(customRoutesView);
}
Ultimately, I did not manage to understand the problem throughly, but I was able to eliminate it.
So during my fixing tries I narrowed down the problem to the animated drawable state - credit to #avalerio for his pro tip, but the answer wasn't addig an id to the button. I think somehow and sometime, the state of the first animation (turning the arrow 180 degrees) stuck in the end position - causing the other views using this animatedDrawable showing it in end position on start.
.reset() did not help, since it resets the animatedVectorDrawable object, not the animation xml drawable state. My solution is a kind of workaround, but it is working: when the custom-view 'ticket' is created with the animated-drawable-imagebutton, I set the imageResource of the button to a not-animated xml drawable - this drawable is basically the start position of my animated-drawable. This way, when the 'tickets' are generated, the imagebutton is 'hardcoded' in the start position.
Not elegant, but works. BUT(!) I would really appreciate if someone could explain to me how this weird behavior is possible - just sometimes, randomly, with no pattern I can reproduce intentionally.

Is there a way to change textView when a particular image(drawable) appears?

I am testing this code that generates a random image, and I am trying to make each generated image have a description
Button buttong;
Random r;
Integer[] images = {
R.drawable.img250, R.drawable.img484, R.drawable.img485,
};
imageView = (ImageView) findViewById(R.id.imageView);
message = (TextView) findViewById(R.id.text_view);
buttong = (Button) findViewById(R.id.buttong);
r = new Random()
buttong.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
imageView.setImageResource(images[r.nextInt(images.length)]);
}
});
I dont know how to explain this very well, but for example: when the image "img250" appears put something like "message.setText("Miami Beach is a south Florida island city");"
i tried if/else statement but no luck
Based on the if statement you posted in the comments, it looks like you were choosing one random image when you set the image and another when you were setting the text. Choose the image first, and then use that to both set the image and the text.
For example:
Integer randomResource = images[r.nextInt(images.length)];
imageView.setImageResource(randomResource );
if (randomResource == R.drawable.img250) {
message.setText("Miami Beach is a south Florida island city");
} else {
// ...
}

how to override the position of an onItemClick in Android

So I have a button, and this button switches the cell of a listview with the cell above, and vise versa for ANOTHER button which is for down (this one is for up... It doesn't matter which, I just decided to talk about this one). The whole button and list view thing is working, but my problem is when I press the up button, and then decide to press it again, it just acts as a down button. The reason for this is because it's still stuck on the same item/position of the list view, and I need to figure out a way to Override the position of the onItemClick in the code??
```
upButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//upButton onClick
Integer myTeam = position; //7 -159
Integer otherTeam = position - 1; //6 - 1678
Map<Integer, String> onClickMap = sortByValue(Constants.picklistMap);
String extraValue;
Log.e("myposition", myTeam.toString());
Log.e("otherposition", otherTeam.toString());
extraValue = onClickMap.get(myTeam); //159
String team = onClickMap.get(otherTeam);
Constants.picklistMap.put(myTeam, onClickMap.get(otherTeam));
Constants.picklistMap.put(otherTeam, extraValue); //6
Log.e("Position: ",Constants.picklistMap.get(position));
Log.e("Position - 1: ",Constants.picklistMap.get(position - 1));
if(myTeam != 0) {
dref.child("picklist").child(myTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(myTeam)));
dref.child("picklist").child(otherTeam.toString()).setValue(Integer.parseInt(Constants.picklistMap.get(otherTeam)));
} else {
Toast.makeText(getActivity(), "Nice try.
If you try it again, the app is going to crash as punishment ... (:",
Toast.LENGTH_LONG).show();
}
}
});
```
By overriding the position, I just mean how
position =+ 1
would make position = position + 1 in python, and I want to do the same thing in Java. The problem is I know that can't be done using the snippet of code I just used to increment the value of position!
Please help!
The reason I can't use position = position + 1 is because on the onItemClick, int position is defined, and then the onClick is created for the buttons, so I need position to be final for me to use it in the onClick, and if I got rid of final, i wouldn't be able to use it in the onClick as it can't be accessed from within an inner class when it's not final
Define which position you want to change, and use this method to update position. You can use this method in onClickListener. This should work.
private int position = 0;
private void up(ArrayList<Integer> arr){
if (position < 1 || position >= arr.size()) return;
int temp = arr.get(position - 1);
arr.set(position - 1, arr.get(position));
arr.set(position, temp);
position --;
}

How to make a Random Layout when button clicked

Actually i want to make it Random class but then i think to much activity can make the app slow so i just want to make Relative layout Random
so i have 5 layout in one activity class
layout1 = (RelativeLayout)findViewById(R.id.layout1);
layout2 = (RelativeLayout)findViewById(R.id.layout2);
layout3 = (RelativeLayout)findViewById(R.id.layout3);
layout4 = (RelativeLayout)findViewById(R.id.layout4);
layout5 = (RelativeLayout)findViewById(R.id.layout5);
and in each layout there is the button in there to make layout random again
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
//The code to how make layout random
}
});
}
and then how to make layout that already opened not open again if the button random was pressed? then if all layout was already opened it will open new activity class
can anyone help me explain with give some example code of that?
Initially set visibility gone to all relative layouts and put all of them into View's ArrayList.
Get random number from 0 to List size.
Get View at random position and set its visibility to Visible and remove from ArrayList.
Do same thing until ArrayList is empty.
Create new activity when ArrayList is empty.
Code:
ArrayList<View> viewList=new ArrayList<>();
initLayouts(){
layout1 = (RelativeLayout)findViewById(R.id.layout1);
layout2 = (RelativeLayout)findViewById(R.id.layout2);
layout3 = (RelativeLayout)findViewById(R.id.layout3);
layout4 = (RelativeLayout)findViewById(R.id.layout4);
layout5 = (RelativeLayout)findViewById(R.id.layout5);
viewList.add(layout1);
viewList.add(layout2);
viewList.add(layout3);
viewList.add(layout4);
viewList.add(layout5);
for(int i=0;i<viewList.size();i++){
viewList.get(i).setVisibility(View.GONE);
}
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v){
loadRandomLayout();
}
});
}
public loadRandomLayout(){
if(viewList.size()>0) {
Random r = new Random();
int number = r.nextInt(viewList.size());
viewList.get(number).setVisibility(View.VISIBLE);
viewList.remove(number);
}else{
startActivity(new Intent(this,NewActivity.class));
}
}
You could create random int as follows:
//To get a Random number 1-5 (I saw your RelativeLayouts and you've 5
Random rand = new Random();
int randomNum = rand.nextInt((5 - 1) + 1) + 1;
And then you could create a method to choose what to show :
public void ShowRelativeLayout(int rand){
switch(rand){
case 1:
if (layout1.getVisibility() == View.VISIBLE) {
//Do nothing cause it's visible
break;
} else {
layout1.setVisibility(View.VISIBLE);
break;
}
case 2:
..........
}
Make an array to store the layout indexes.
RelativeLayout[] layout = new RelativeLayout[5];
layout[0] = (RelativeLayout)findViewById(R.id.layout[0]); // 0
layout[1] = (RelativeLayout)findViewById(R.id.layout[1]); // 1
layout[2] = (RelativeLayout)findViewById(R.id.layout[2]); // 2
layout[3] = (RelativeLayout)findViewById(R.id.layout[3]); // 3
layout[4] = (RelativeLayout)findViewById(R.id.layout[4]); // 4
Make a simple random number generator.
public void FindNewLayout ()
{
Random r_generator = new Random();
int randomNum;
//now the only way to know which layouts have been shown before, you
//need to store the indexes that have been used before, somewhere.
//I recommend using an array.
// count, and the array below should be initialized somewhere else
//rather than inside the method so that only one instance of each is
//created, but for simplicity I'll just put their initialization here
int static count = 0;
//I'll explain below what count does.
// the log array that remembers each layout change
boolean[] log = new boolean[5];
do
{
//select new random number
randomNum = r_generator.nextInt((max - min) + 1) + min;
//in this case max = 4, min = 0, so replace these values in the
//equation above
// check the log to see if the number has appeared again
if ( log[randomNum] == false )
{
//Great! it hasn't appeared before, so change layout
log[randomNum] = true;
layout[randomNum].setVisibility = true;
count++; // increases step
break; //stops while because an unused layout has been found
}
}while (count<5)
//if the value of count is equal to 5 then every layout has been used
//before so the do-while code should not be run again
}// end method
And the above method should be called whenever you want to try to change layout.
Finally, you can use something like the Debugger.log("message"); statement
to be printed on the console for debugging purposes if you want, in order to find out when the layout has changed.

onClickListener issue with Android Studio [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I've been attempting to build a simple puzzle app, more just to prove to myself that I could than anything else. It's a simple 9 tile puzzle with one tile missing. Tiles adjacent to the missing tile can be moved into that slot.
What I've attempted to do was use a grid layout of 9 imageviews for the tiles. Whenever a tile is to be moved I instantiate a tenth imageview passing that tile's image source and location to it. The original tile is then set to invisible and the mover tile moves to the new location, at which point it passes this data to the recieving tile and goes invisible.
First I find the offset between two adjacent imageViews:
int startPosition1[] = new int[2];
topLeft.getLocationOnScreen(startPosition1);
int startPosition2[] = new int[2];
topCenter.getLocationOnScreen(startPosition2);
final int separation = startPosition2[1] - startPosition1[1];
Then, in the OnClickListener, I check to see if the move is valid and call a method I created to do the move (moveme):
topLeft.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int thisLocation[] = new int[2];
v.getLocationOnScreen(thisLocation);
int invisibleLocation[] = new int[2];
findViewById(theInvisible).getLocationOnScreen(invisibleLocation);
if ((thisLocation[0] - invisibleLocation[0]) == 0)
{
if ((thisLocation[1] - invisibleLocation[1]) == separation)
{
Toast.makeText(getApplicationContext(), R.string.boldly ,Toast.LENGTH_LONG).show();
moveMe(thisLocation, "translationY", (0-separation), v);
}
else if((invisibleLocation[1] - thisLocation[1]) == separation)
{
Toast.makeText(getApplicationContext(), R.string.boldly, Toast.LENGTH_LONG).show();
moveMe(thisLocation, "translationY", separation, v);
}
}
else if ((thisLocation[1] - invisibleLocation[1]) == 0) {
if ((thisLocation[0] - invisibleLocation[0]) == separation) {
Toast.makeText(getApplicationContext(), R.string.boldly, Toast.LENGTH_LONG).show();
moveMe(thisLocation, "translationX", (0 - separation), v);
} else if ((invisibleLocation[0] - thisLocation[0]) == separation) {
Toast.makeText(getApplicationContext(), R.string.boldly, Toast.LENGTH_LONG).show();
moveMe(thisLocation, "translationX", separation, v);
}
}
else
{
Toast.makeText(getApplicationContext(), R.string.illogical, Toast.LENGTH_LONG).show();
}
}
});
Here's the moveMe method:
void moveMe( int[] thisLocation, String direction, int separation, View v)
{
Log.i(TAG, "Entere mover");
ImageView mover = (ImageView) findViewById(R.id.mover);
ImageView destination = (ImageView) findViewById(getTheInvisible());
mover.setContentDescription(v.getContentDescription());
setView(mover);
mover.setX(thisLocation[0]);
mover.setY(thisLocation[1]);
Log.i(TAG, "relocated mover");
mover.setVisibility(View.VISIBLE);
v.setVisibility(View.INVISIBLE);
v.setClickable(false);
setTheInvisible(v);
Log.i(TAG, "Swapped visibilities");
ObjectAnimator test = ObjectAnimator.ofFloat(mover, direction, separation);
test.setDuration(1000);
test.setRepeatCount(0);
test.start();
Log.i(TAG, "animation complete");
destination.setContentDescription(mover.getContentDescription());
setView(destination);
destination.setVisibility(View.VISIBLE);
destination.setClickable(true);
mover.setVisibility(View.INVISIBLE);
Log.i(TAG, "Swapped views with destination");
}
As near as I can tell, this method is not even being called. Also any tile that fits the criteria to call this method does not issue it's toast message either. Lastly I've noticed that any tile set two spaces away directly along the x or y axis from the blank tile also doesn't display its text. Thanks in advance.
Okay, after nearly a week of looking I found the problem. As it turns out GridLayouts supply their own animations. In order to enable them all you have to do is put this in your GridLayout item in xml:
android:animateLayoutChanges="true"
Then simply make the change and call the layoutAnimator like so:
mover.setLayoutParams(destination.getLayoutParams());
theGrid.startLayoutAnimation();
In this example mover is an ImageView that temporarily takes on the image of other views and moves them to other grid coordinates. theGrid is the resource id name I gave the grid layout.
The issue with it not doing anything for certain tiles was a fault in my if then statements.

Categories

Resources