Change Images or Bitmap when ever touched on screen - android

I want to change the bitmap that contains an image whenever user tap on the screen. i.e. the default image is shadow1, now what i want is that when user touched on screen then this image changed to shadow2, then again if user touched then shadow3, then on next touch the image again comes as shadow1 and it goes on and on and on. so basically there are three images and i want that when ever user touched on screen then image changes with each tap.
Following is the code that i tried but it is still not working as expected i.e. the image changes from shadow1 to shadow2 but then not changes to shadow3 or shadow1 even if i touched many times.
public void Touched(float x, float y)
{
boom = false;
try{
switch (bird.GetState()) {
case 0:
distance = 0;
bird.SetState(1);
flapped = true;
Bitmap workingBitmap = BitmapFactory.decodeResource(gameLogic.Resources(), R.drawable.shadow1);
bitmapBird = workingBitmap.copy(Bitmap.Config.ARGB_8888, false);
if (bitmapBird==workingBitmap)
{
}
riseCounter = 0;
pipeValues.clear();
//SoundManager.playSound(2, 1);
break;
case 1:
{
riseCounter = 0;
flapped = true;
t = 3;
Bitmap workingBitmappp = BitmapFactory.decodeResource(gameLogic.Resources(), R.drawable.shadow2);
bitmapBird = workingBitmappp.copy(Bitmap.Config.ARGB_8888, false);
//SoundManager.playSound(2, 1);
}
break;
case 2:
{
riseCounter = 0;
flapped = true;
t = 0;
}
break;
default:
Bitmap workingBitma = BitmapFactory.decodeResource(gameLogic.Resources(), R.drawable.shadow3);
bitmapBird = workingBitma.copy(Bitmap.Config.ARGB_8888, false);
break;
}
} catch(Exception e){}
}
I think there should be a for loop or while loop in 'case 1' and whenever user tap then image changes. Please help me with this.

You can simply use an int value to keep track of the image displayed as;
First Initialize a int at class level;
int num = 0;
then you can use it as;
if(num == 0){
loadFirstImage();
num++;
}
else if(num == 1)
{
loadSecondImage();
num++;
}
else if(num == 2){
loadThirdImage();
num = 0 ;
}

I think that you need to change the state of the bird in your second case statement.
First iteration will set the state to 1, from there, the only case statement you can hit is case 1: because you never change it.
So you need something like
case 1:
bird.SetState(2);
//....
Hope that helps

Related

Directional buttons do not work in the "negative" direction

I am trying to make an image view move Up/Down/Left/Right using image buttons. I am able to get the image to move right and down, however up and left do not work.
I have tried changing the +/- sign, the length of the increments to move the image, and also the if/else statements to determine whether or not to move the image.
// Move ImageView Up
case R.id.upBtn: {
if (img.getY() > 0) {
img.setY(img.getY() - 25);
}
}
// Move ImageView Down
case R.id.downBtn: {
if (img.getY() < 950) {
img.setY(img.getY() + 25);
}
}
// Move ImageView Left
case R.id.leftBtn: {
if (img.getX() > 0) {
img.setX(img.getX() - 25);
}
}
// Move ImageView Right
case R.id.rightBtn: {
if (img.getX() < 2000) {
img.setX(img.getX() + 25);
}
}
The image view is supposed to move in all directions but it won't go in the up or left directions. I removed the if/else statements to see if they were the issue and they had no effect in regards to moving the image. They just keep it from going off the screen. It appears that I can not subtract from the getY() function but that does not make sense.
You are missing break statements, so once a case is matched, the code of all following case statements will also execute.
Try :
// Move ImageView Up
case R.id.upBtn: {
if (img.getY() > 0) {
img.setY(img.getY() - 25);
}
}
break;
// Move ImageView Down
case R.id.downBtn: {
if (img.getY() < 950) {
img.setY(img.getY() + 25);
}
}
break;
// Move ImageView Left
case R.id.leftBtn: {
if (img.getX() > 0) {
img.setX(img.getX() - 25);
}
}
break;
// Move ImageView Right
case R.id.rightBtn: {
if (img.getX() < 2000) {
img.setX(img.getX() + 25);
}
}
break;
default :

How to rotate an image in Glide to be right side up

I am a little bit of a novice Android developer but I am working on a project to improve memory efficiency in our app's handling of images.
Right now, we have some code for rotating an image based on the Exif data to ensure that it's right side up. I'd like to do the same thing but in Glide, but I can't find any documentation on that... or even documentation on reading Exif data.
I have to imagine this is a fairly common use case! I'd like to take the following code and reduce it to a straightforward Glide method.
Here's what we have now:
final Matrix bitmapMatrix = new Matrix();
int widthMultiplier = 1;
int heightMultiplier = 1;
try {
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(bo.toByteArray()));
final Collection<ExifIFD0Directory> exifIFD0Directories = metadata.getDirectoriesOfType(ExifIFD0Directory.class);
if (exifIFD0Directories != null) {
for (ExifIFD0Directory d : exifIFD0Directories) {
if (d.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
try {
final int exifOrientation = d.getInt(ExifIFD0Directory.TAG_ORIENTATION);
switch (exifOrientation) {
case 1:
break; // top left
case 2:
heightMultiplier = -1;
break; // top right
case 3:
bitmapMatrix.postRotate(180);
break; // bottom right
case 4:
bitmapMatrix.postRotate(180);
heightMultiplier = -1;
break; // bottom left
case 5:
bitmapMatrix.postRotate(90);
heightMultiplier = -1;
break; // left top
case 6:
bitmapMatrix.postRotate(90);
break; // right top
case 7:
bitmapMatrix.postRotate(270);
heightMultiplier = -1;
break; // right bottom
case 8:
bitmapMatrix.postRotate(270);
break; // left bottom
default:
break; // Unknown
}
break;
} catch (MetadataException e) {
handleException(e, subscriber, uri, inputStream, mFinalPath, fromGallery);
return;
}
}
}
}
} catch (ImageProcessingException | IOException e) {
handleException(e, subscriber, uri, inputStream, mFinalPath, fromGallery);
return;
}
Any ideas are appreciated.
From some additional resource, it sounds as if Glide actually handles this automatically.

Android Multitouch Strange Behavior

After a lot of tinkering, I think I've finally come up with a good multitouch handling system for my android game. It makes use of Robert Greene's Input Pipeline, modified for use with multitouch. Right now, the code has a simple system that records which pointer ID is currently doing which action (right now just shooting and moving). Each pointer's state is kept in a Pointer class, which is just a simple encapsulation of whether it is down, and it's coordinates. The ID acts as the pointer array index.
This seems like it should work well in practice, but in game it behaves very erratic. When recording the pointer actions in LogCat, oftentimes Android will send an "UP" action when the pointer remains down, or just before a number of "MOVE" actions by the pointer. Because my code believes the pointer is up, the game doesn't respond to it.
This also happens with button presses like the shooting button. When the pointer comes down on the area (which right now is just simply the lower left region), Android will send multiple "UP" and "DOWN" actions even though the pointer remains down the whole time. I had a single touch movement system before and none of these problems happened.
Is this just an issue with how I am reacting to the events? Should I handle POINTER_DOWN and DOWN separately? Or should I detect which pointers are moving after the "UP" action to see which ones really are down despite what Android says?
Here's my current code in my thread which receives the input events from Android. Because it is a pipeline system, I have the events encapsulated in the InputObject which is somewhat similar to Robert Greene's. Maybe a new set of eyes can help me tell what's wrong? Thanks for any help!
private int inx, iny;
private int shootID;
public boolean shooting = false;
private int moveID;
public boolean moveDown = false;
private static final int MAX_POINTERS = 10;
private Pointer[] pointers = new Pointer[MAX_POINTERS];
public void inputTouch(InputObject in) {
switch(in.action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
pointers[in.pID].press(in.pX[in.actionIndex], in.pY[in.actionIndex]);
//Log.i("D", "DOWN");
break;
case MotionEvent.ACTION_MOVE:
for(int p = 0; p < in.pointCount; p++) {
int id = in.pointerIDs[p];
pointers[id].setCoord(in.pX[id], in.pY[id]);
}
//Log.i("D", "MOVE");
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
pointers[in.pID].release();
if(shootID == in.pID) {
shooting = false;
}
if(moveID == in.pID) {
moveDown = false;
}
//Log.i("D", "UP");
break;
case MotionEvent.ACTION_CANCEL:
default:
break;
}
for(int ap = 0; ap < MAX_POINTERS; ap++) {
if(pointers[ap].down) {
if(pointers[ap].x < world.cam.pixelWidth / 4 &&
pointers[ap].y > world.cam.pixelHeight - (world.cam.pixelHeight / 4)) {
shootID = ap;
shooting = true;
} else {
inx = pointers[ap].x;
iny = pointers[ap].y;
moveID = ap;
moveDown = true;
}
}
}
StringBuilder sb = new StringBuilder();
for(int j = 0; j < 3; j++) {
sb.append("ID " + (j+1) + ": " + pointers[j].down + "[" + pointers[j].x + ", " + pointers[j].y + "]" + " | ");
}
//Log.i("D", sb.toString());
}
Hope you got the answer by now, but here''s my solution:
First of all, there's a couple of things to add in the InputHolder class:
-internal public fields for mPointerIndex = event.getPointerIndex and mPointerID = event.getPointerID(mPointerIndex) (these get assigned in the useEvent/useHistory)
-if you only need to track 2 touchpoints, you need to add mPointerIndex2, x2 and y2 aswell. Add more as you need to track more points.
-add definitions for the case where MotionEvent.ACTION_POINTER_2_UP/DOWN gets passed. Turns out, POINTER_1 is the same as POINTER_UP/DOWN! This really tripped me up because I was falling through the switch case to the default. I only caught this because I changed my default to -1 and saw it logged.
Depending on how you process the actions in your processInput(obj), you map these to different ints. In my case I used the obj.y to see if they where left/right touches and I only needed two points, so I mapped these to ACTION_TOUCH_POINTER_UP/DOWN instead of giving each touch it's own action int identifier.
-now, if you want to track multiple touch points, you would have to do the above and the below in a for loop over all entries in event.getPointerCount(). In my case I was only interested in the x/y of one other touchpoint, so I could get away with only doing a check after I had filled the first point and the other pointerindex was easy to deduce:
public void useEvent(MotionEvent event) {
eventType = EVENT_TYPE_TOUCH;
int a = event.getAction();
switch (a) {
case MotionEvent.ACTION_DOWN:
action = ACTION_TOUCH_DOWN;
break;
case MotionEvent.ACTION_POINTER_DOWN:
action = ACTION_TOUCH_POINTER_DOWN;
break;
case MotionEvent.ACTION_POINTER_2_DOWN:
action = ACTION_TOUCH_POINTER_DOWN;
break;
case MotionEvent.ACTION_MOVE:
action = ACTION_TOUCH_MOVE;
break;
case MotionEvent.ACTION_UP:
action = ACTION_TOUCH_UP;
break;
case MotionEvent.ACTION_POINTER_UP:
action = ACTION_TOUCH_POINTER_UP;
break;
case MotionEvent.ACTION_POINTER_2_UP:
action = ACTION_TOUCH_POINTER_UP;
break;
default:
action = -1;
}
time = event.getEventTime();
pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT;
pointerID = event.getPointerId(pointerIndex);
x = (int) event.getX(pointerIndex);
y = (int) event.getY(pointerIndex);
if (event.getPointerCount() > 1)
{
pointerIndex2 = pointerIndex== 0 ? 1 : 0;
x2 = (int)event.getX(pointerIndex2);
y2 = (int)event.getY(pointerIndex2);
}
}
If you''re tracking more points, or need more information about each touchevent, you have to extend the for loop up over the action switch case.
Anyway, now you need two variables in your thread so you can keep track of your two touches: call 'em touchOneID and touchTwoID (or index). On an ACTION_POINTER_2_UP, the obj.mPointerID refers to the obj which is going UP! This means that the other touch will change it's ID! Keep track of this change, and you're sorted. The internal obj's mPointerID/Index will always be correct, you just have to track them correctly in your surfaceview's thread so you can act accordingly to when you get a POINTER_DOWN. In my case, I did a simple x position check to determine what to do in my ACTION_MOVE event which told me enough to correctly determine which x/y or x2/y2 I should use and how to use it. This meant less code to run and limits to the things I had to keep in memory, but it all depends on what and how much information you need.
Finally:
To be honest, if you handled the definitions correctly and assigned every MotionEvent and held them in the InputObject, you'd probably be fine. Hell, I think you can ignore and lose the whole switch case and just say obj.mAction = event.getAction() and handle these in your processInput(obj)!
Meaning, all those static ints he's remapping to in the InputHolder seem unnecessary, unless you really only need one or two touch definitions (which explains his mysterious standalone comment of "this app is only interested in down touches"). Getting rid of those statically defined ints also means you can just test against MotionEvent.ACTION_CODE instead of doing a lookup against InputHolder.TOUCH_ACTION_CODE.

updating Textview based on sensordata

I'm trying to update a textview based on sensorinput - more precise pitch. I have no problem getting the sensor data, converting it to degrees and displaying it in a textview.
The problem is, that I wan't different numbers displayed, based on the pitch in degrees. I have written a if-else if statement and placed it in the onsensorchanged, but apart from the initial number it does not update.
#Override
public void onSensorChanged(SensorEvent event) {
switch(event.sensor.getType()){
case Sensor.TYPE_ACCELEROMETER:
for(int i =0; i < 3; i++){
valuesAccelerometer[i] = event.values[i];
}
break;
case Sensor.TYPE_MAGNETIC_FIELD:
for(int i =0; i < 3; i++){
valuesMagneticField[i] = event.values[i];
}
break;
}
boolean success = SensorManager.getRotationMatrix(
matrixR,
matrixI,
valuesAccelerometer,
valuesMagneticField);
if(success){
SensorManager.getOrientation(matrixR, matrixValues);
// Float to double
double pitch = Math.toDegrees(matrixValues[1]);
// 1 decimal
pitch = Math.abs(round(pitch, 0));
//set textview vinkel to degrees
vinkel.setText(String.valueOf(pitch));
// find tubesize from edittext
String tubesizestring = tubesize.getText().toString();
if(tubesizestring=="1000"){
if(pitch>=0.6){
kwh.setText("2,69");
}else if(pitch>=1.0){
kwh.setText("3,47");
}else if(pitch>=2.0){
kwh.setText("4,90");
}else if(pitch>=5.0){
kwh.setText("7,75");
}else if(pitch>=10.0){
kwh.setText("10,96");
}else if(pitch>=20.0){
kwh.setText("15,50");
}else if(pitch>=30.0){
kwh.setText("18,99");
}else{
kwh.setText("more than 30 degrees");
}
}
}
I hope it is clear what I'm trying to do. Othervise please ask
Hope somebody can point me in the right direction
It doesn't work because your logic is fundamentally flawed. Let's assume the pitch is around 25. It's greater than 0.6 and 1.0 and so on. So obviously only the first if statement will be seen, since the others are else if statements. To get it to work, change the order of the statements.
if(pitch>=30.0){
kwh.setText("18,99");
}else if(pitch>=20.0){
kwh.setText("15,50");
}else if(pitch>=10.0){
kwh.setText("10,96");
}else if(pitch>=5.0){
kwh.setText("7,75");
}else if(pitch>=2.0){
kwh.setText("4,90");
}
else if(pitch>=1.0){
kwh.setText("3,47");
}
else if(pitch>=0.6){
kwh.setText("2,69");
}eelse{
kwh.setText("more than 30 degrees");

Android - Moving a single image

Can anyone help please.
Im writing a small Android game where the player is able to select a "barrier" and drag it accross the screen with their finger. I have the barriers drawn on the screen and I am able to drag it accross the screen.
My problem however is when I add more than 1 barrier, eg 3 barriers, and drag a barrier accross the screen, they all drag and they all drag to the same position. That is to say they all lie on top of each other, making it look as though there is only 1 barrier.
Here is my code, can anyone please tell me where I am going wrong/explain where I am going wrong.
public class MainGamePanel extends SurfaceView implements SurfaceHolder.Callback, SensorEventListener {
// Initialising the Barrier
private Barrier barrier[] = new Barrier[3];
// The Main Game Panel
public MainGamePanel(Context context) {
super(context);
// Adding a call-back (this) to the surfaceHolder to intercept events
getHolder().addCallback(this);
// Creating the Game items
// The starting coordinates of the Barrier
int x = 30;
int y = 270;
barrier[0] = new Barrier(BitmapFactory.decodeResource(getResources(), R.drawable.blue_barrier), x, y);
barrier[1] = new Barrier(BitmapFactory.decodeResource(getResources(), R.drawable.green_barrier), x + 15, y);
barrier[2] = new Barrier(BitmapFactory.decodeResource(getResources(), R.drawable.pink_barrier), x + 30, y);
// Create the Game Loop Thread
thread = new MainThread(getHolder(), this);
// Make the GamePanel focusable so it can handle events
setFocusable(true);
}
// Handles the touch events
public boolean onTouchEvent(MotionEvent event)
{
int eventAction = event.getAction();
int x = (int)event.getX();
int y = (int)event.getY();
switch (eventAction)
{
// Touch down so check if finger is on Barrier
case MotionEvent.ACTION_DOWN:
if (x > barrier[0].getX() && x < barrier[0].getX() + 8
&& y > barrier[0].getX() && y < barrier[0].getY() + 8)
{
barrier[0].isTouched();
}
else if (x > barrier[1].getX() && x < barrier[1].getX() + 8
&& y > barrier[1].getX() && y < barrier[1].getY() + 8)
{
barrier[1].isTouched();
}
else if (x > barrier[2].getX() && x < barrier[2].getX() + 8
&& y > barrier[2].getX() && y < barrier[2].getY() + 8)
{
barrier[2].isTouched();
}
break;
// Touch-drag with the Barrier
case MotionEvent.ACTION_MOVE:
// Move the Barrier the same as the finger
for (int i = 0; i < barrier.length; i++)
{
if (barrier[i] == barrier[0])
{
barrier[0].setX(x);
barrier[0].setY(y);
} // end if
else if (barrier[i] == barrier[1])
{
barrier[1].setX(x);
barrier[1].setY(y);
}
else if (barrier[i] == barrier[2])
{
barrier[2].setX(x);
barrier[2].setY(y);
} // end else if
} // end for
break;
case MotionEvent.ACTION_UP:
// Finger no longer on Barrier - Do Nothing
break;
}
return true;
}
// Render - Draws the Game Item Bitmaps to the screen
public void render(Canvas canvas)
{
// Set the background to white
canvas.drawColor(Color.WHITE);
barrier[0].draw(canvas);
barrier[1].draw(canvas);
barrier[2].draw(canvas);
}
// Update
// This is the Game's update method
// It iterates through all the Objects and calls their update() methods (if they have one)
public void update()
{
} // end update
In your barrier move code, you aren't checking a particular barrier is touched, so you're moving all of them to the same coordinates. The following loop does exactly the same thing as your current code:
// Move the Barrier the same as the finger
for (int i = 0; i < barrier.length; i++)
{
barrier[i].setX(x);
barrier[i].setY(y);
} //end for
To fix this, you need to check if the current barrier in the loop is the one that was touched, and can change that whole loop to something like:
// Move the Barrier the same as the finger
for (int i = 0; i < barrier.length; i++)
{
if (barrier[i].isTouched())
{
barrier[i].setX(x);
barrier[i].setY(y);
} // end if
} // end for
You would then need to make sure that you un-set the touched property in the ACTION_UP section. If you post your Barrier class definition I can probably help more.
I'm pretty sure your problem could be solved by making the barriers three separate objects instead of in an array.
As already pointed out, your code in handling the move is wrong because it moves all the Barriers to the same X,Y when it should only move the one that is touched.
Also, you are never resetting the isTouched on the objects in the Action up. When the user lifts their finger you should set them all to isTouched == false. If you don't do that then once you touch one it will always move to the X,Y.

Categories

Resources