Just got into Android development.. Please bear with me.
I created an overridden onTouchEvent function. Every time I touch somewhere inside my app, I expect it to run the function twice. Instead, the function runs random number of times. Some times 7, other times 12. I am just wondering if this is normal?
This is my code if anyone is curious..
package com.jojocoder.subhunter;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.view.Display;
import android.util.Log;
import android.widget.ImageView;
import java.util.Random;
public class MainActivity extends AppCompatActivity {
int numberHorizontalPixels;
int numberVerticalPixels;
int blockSize;
int gridWidth = 40;
int gridHeight;
float horizantalTouched = -100;
float verticalTouched = -100;
int subHorizaltalPosition;
int subVerticalPosition;
boolean hit = false;
int shotsTaken;
int distanceFromSub;
boolean debugging = true;
int testcount;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
numberHorizontalPixels = size.x;
numberVerticalPixels = size.y;
blockSize = numberHorizontalPixels / gridWidth;
gridHeight = numberVerticalPixels / blockSize;
Log.d("Debugging","Running OnCreate func");
newGame();
draw();
}
public void newGame() {
Log.d("Debugging", "Running newGame func");
}
void draw() {
Log.d("Debugging", "Running draw func");
printDebuggingText();
}
#Override
public boolean onTouchEvent(MotionEvent motionEvent) {
testcount ++;
Log.d("Debugging", "Running OnTouchEvent func");
takeShot();
return true;
}
void takeShot() {
Log.d("Debugging", "Running takeShot func");
draw();
}
void boom() {
}
void printDebuggingText() {
Log.d("numberHorizantalPixels", "" + numberHorizontalPixels);
Log.d("numberVerticalPixels", "" + numberVerticalPixels);
Log.d("blockSize", "" + blockSize);
Log.d("gridWidth", "" + gridWidth);
Log.d("gridHeight", "" + gridHeight);
Log.d("horizantalTouched", "" + horizantalTouched);
Log.d("verticalTouhced", "" + verticalTouched);
Log.d("subHorizantalPosition", "" + subHorizaltalPosition);
Log.d("subVerticalPosition", "" + subVerticalPosition);
Log.d("hit", "" + hit);
Log.d("shotsTaken", "" + shotsTaken);
Log.d("debugging", "" + debugging);
Log.d("distanceFronSub", "" + distanceFromSub);
Log.d("testcount", "" + testcount);
}
}
Thanks in advance.
If you are using onTouchEvent() method to intercept the touch events in an Activity or a View. This method is called several times as the pressure, size, position, etc. of the touch event changes or even when a new finger is put on the touch screen.
Related
I have coordinates of screen and I want to tell operating system to perform that operation which OS is supposed to perform on touch of screen on that coordinates.
Just like cicret somehow tells mobile phone that what to do. While user is not directly interacting with mobile phone.
Plz tell me anything if you know about it.
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
public class MainActivity extends Activity
{
StringBuilder stringBuilder = new StringBuilder();
TextView textView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
this.textView = (TextView) findViewById( R.id.strXY );
this.textView.setText("X: ,Y: ");//texto inicial
this.textView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
stringBuilder.setLength(0);
if (arg1.getAction() == MotionEvent.ACTION_MOVE) {
stringBuilder.append("Moving, X:" + arg1.getX() + ", Y:" + arg1.getY());
}
else {
stringBuilder.append("Stoped, X:" + arg1.getX() + ", Y:" + arg1.getY());
}
textView.setText(stringBuilder.toString());
return true;
}
});
}
}
I have a working frame-by-frame animation inside an Android application.
That's fine - but how would I add a scrolling background to this application, so that the animation run over the background?
I can find plenty of examples for implementing the 2 processes separately - but NOT together.
Any help would be appreciated!
Here's my code for the animation Activity..
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceView;
import android.widget.ImageView;
/**
*
*
*/
public class MyAnimationView extends ImageView
{
private static final String TAG = "AnimationTest:AnimationView";
private Context mContext = null;
private static final int DELAY = 100; //delay between frames in milliseconds
private boolean mIsPlaying = false;
private boolean mStartPlaying = false;
private ArrayList<Bitmap> mBitmapList = new ArrayList<Bitmap>();
private int play_frame = 0;
private long last_tick = 0;
public MyAnimationView(Context context, AttributeSet attrs)
{
super(context, attrs);
mContext = context;
}
#Override
protected void onDraw(Canvas c)
{
Log.d(TAG, "onDraw called");
if (mStartPlaying)
{
Log.d(TAG, "starting animation...");
play_frame = 0;
mStartPlaying = false;
mIsPlaying = true;
postInvalidate();
}
else if (mIsPlaying)
{
if (play_frame >= mBitmapList.size())
{
mIsPlaying = false;
}
else
{
long time = (System.currentTimeMillis() - last_tick);
int draw_x = 0;
int draw_y = 0;
if (time >= DELAY) //the delay time has passed. set next frame
{
last_tick = System.currentTimeMillis();
c.drawBitmap(mBitmapList.get(play_frame), draw_x, draw_y, null);
play_frame++;
postInvalidate();
}
else //still within delay. redraw current frame
{
c.drawBitmap(mBitmapList.get(play_frame), draw_x, draw_y, null);
postInvalidate();
}
}
}
}
/*ideally this should be in a background thread*/
public void loadAnimation(String prefix, int nframes)
{
mBitmapList.clear();
for (int x = 0; x < nframes; x++)
{
String name = prefix + "_" + x;
Log.d(TAG, "loading animation frame: " + name);
int res_id = mContext.getResources().getIdentifier(name, "drawable", mContext.getPackageName());
BitmapDrawable d = (BitmapDrawable) mContext.getResources().getDrawable(res_id);
mBitmapList.add(d.getBitmap());
}
}
public void playAnimation()
{
mStartPlaying = true;
postInvalidate();
}
}
"draw_x" and "draw_y" are the variables for your bitmap position. If you change this two variables (or just one of them), you can move (scroll) your picture over the screen.
I have two classes - MainActivity.java and MainView.java.
I'm trying to render a custom view (defined in MainView.java) when screen is touched from the main activity.
My code is doing a funky thing. From the main page, when you touch the screen, it does NOT render the custom view I've specified in MainView.java - but still prints out a message I put in the onDraw() method, which should mean that onDraw() is being run. Why is my onDraw() method being run but its view doesn't render?
Also, both my onTouchEvent in MainActivity.java and MainView.java seems to respond at the same time, although the view I see is the only the activity_main.xml.
Please help :(
MainActivity.java
package com.example.owner.thesisapp;
import com.example.owner.thesisapp.MainView;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.media.AudioManager;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.media.SoundPool;
import android.view.View;
import android.graphics.Canvas;
import android.widget.ImageView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class MainActivity extends Activity {
private static SoundPool soundPool;
private static HashMap soundPoolMap;
private static int S1 = R.raw.a3v1;
private static int S2 = R.raw.c3v1;
private static int S3 = R.raw.dsharp3v1;
private static int S4 = R.raw.fsharp3v1;
private int soundID;
private boolean isSoundLoaded = false;
public MainView mainView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mainView = (MainView) findViewById(R.id.main_view);
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
#Override
public void onLoadComplete(SoundPool soundPool, int sampleId,
int status) {
isSoundLoaded = true;
}
});
soundID = soundPool.load(this, R.raw.fsharp3v1, 1);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
if (isSoundLoaded) {
soundPool.play(soundID, 1f, 1f, 1, 0, 1f);
Log.d("Test", "Played sound");
}
mainView.postInvalidate();
return false;
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
// Keep landscape orientation
public void onConfigurationChanged(Configuration newConfig) {
// ignore orientation/keyboard change
super.onConfigurationChanged(newConfig);
}
}
MainView.java
package com.example.owner.thesisapp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
/**
* Created by Owner on 6/1/2015.
*/
public class MainView extends View {
Bitmap stillWave;
int iy = 0;
public MainView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
stillWave = BitmapFactory.decodeResource(getResources(), R.drawable.wave);
setWillNotDraw(false);
Log.d("MAINVIEW: Is this ran?", " ");
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int)event.getX();
int y = (int)event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.d("Action DOWN!", " ");
iy = 0;
this.invalidate();
case MotionEvent.ACTION_MOVE:
Log.d("Action MOVE!", " ");
case MotionEvent.ACTION_UP:
Log.d("Action UP!", " ");
}
return false;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d("MAINVIEW ONDRAW: Is this ran?", " ");
int width = canvas.getWidth();
int height = canvas.getHeight();
//set background
Rect wBackground = new Rect();
wBackground.set(0, 0, width, height);
Paint pBackground = new Paint();
pBackground.setStyle(Paint.Style.FILL);
pBackground.setColor(Color.BLACK);
canvas.drawRect(wBackground, pBackground);
//Log.d("garo, sero", width + " " + height);
//set Wave
Paint pWave = new Paint();
pWave.setStyle(Paint.Style.FILL_AND_STROKE);
pWave.setColor(Color.WHITE);
pWave.setStrokeWidth(10);
pWave.setStrokeCap(Paint.Cap.ROUND);
int waveFlucMin = -100;
int waveFlucMax = 100;
float[] coords = new float[width * 2];
for (int ix = 0; ix < width; ix++) {
int yoffset = waveFlucMin + (int) (Math.random() * ((waveFlucMax - waveFlucMin) + 1));
coords[2 * ix] = (float) ix;
coords[2 * ix + 1] = (float) iy + yoffset;
}
//Log.d("Coordinates x?", coords[1] + " " + coords[3] + " " + coords[5] + " " + coords[7] + " " + coords[301] + " " + coords[303] + " ");
//Log.d("Coordinates y?", coords[0] + " " + coords[2] + " " + coords[4] + " " + coords[6] + " " + coords[300] + " " + coords[302] + " ");
//Log.d("Generating?", "YES, generating forloop : " + iy);
//wait a second between each wave generation
/*
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
*/
drawWave(coords, width, pWave, canvas);
if (iy < height) {
iy += 10;
invalidate();
} else {
//do nothing - finish onDraw() call.
}
}
private void drawWave(float[] coords, int width, Paint pWave, Canvas canvas) {
canvas.drawPoints(coords, 0, width*2, pWave);
}
}
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" tools:context=".MainActivity">
<com.example.owner.thesisapp.MainView
android:id="#+id/main_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<ImageView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#111C64"/>
The problem is in your layout. Both your custom View and the ImagView are, since your are using a RelativeLayout, aligned to the Top left. The z order in this case put the ImageView on top on your custom View and, since it is taking the whole screen, you can't see your custom view.
I'm learning Android programming.
So I managed to implement a simple app that rolls a ball over the screen if you tilt yout phone. But right now it is as simple as:
if roll > 0 then xpos++ else xpos-- end and the same for ypos.
So I want to calculate a more exact direction and also I would like the ball to roll faster the more the phone is tilting.
So if I know the tilt in the roll direction and the pitch direction, how do I calculate the direction and speed of the ball?
Here is how:
package benyamephrem.tiltball;
import android.graphics.Point;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.os.Handler;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager.LayoutParams;
import android.widget.FrameLayout;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorManager;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.SensorEventListener;
import android.widget.Toast;
public class TiltBall extends ActionBarActivity {
BallView mBallView = null;
Handler RedrawHandler = new Handler(); //so redraw occurs in main thread
Timer mTmr = null;
TimerTask mTsk = null;
int mScrWidth, mScrHeight;
android.graphics.PointF mBallPos, mBallSpd;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE); //hide title bar
//set app to full screen and keep screen on
getWindow().setFlags(0xFFFFFFFF, LayoutParams.FLAG_FULLSCREEN | LayoutParams.FLAG_KEEP_SCREEN_ON);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tilt_ball);
//create pointer to main screen
final FrameLayout mainView = (android.widget.FrameLayout) findViewById(R.id.main_view);
//get screen dimensions
Display display = getWindowManager().getDefaultDisplay();
mScrWidth = display.getWidth();
mScrHeight = display.getHeight();
mBallPos = new android.graphics.PointF();
mBallSpd = new android.graphics.PointF();
//create variables for ball position and speed
mBallPos.x = mScrWidth / 2;
mBallPos.y = mScrHeight / 5;
mBallSpd.x = 0;
mBallSpd.y = 0;
//create initial ball
mBallView = new BallView(this, mBallPos.x, mBallPos.y, 75);
mainView.addView(mBallView); //add ball to main screen
mBallView.invalidate(); //call onDraw in BallView
//listener for accelerometer, use anonymous class for simplicity
((SensorManager) getSystemService(Context.SENSOR_SERVICE)).registerListener(
new SensorEventListener() {
#Override
public void onSensorChanged(SensorEvent event) {
//set ball speed based on phone tilt (ignore Z axis)
//***Change speed here by multiplying event values by bigger numbers***
mBallSpd.x = -event.values[0] * (30/10);
mBallSpd.y = event.values[1] * (30/10);
//timer event will redraw ball
}
#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
} //ignore
},
((SensorManager) getSystemService(Context.SENSOR_SERVICE))
.getSensorList(Sensor.TYPE_ACCELEROMETER).get(0),
SensorManager.SENSOR_DELAY_NORMAL);
//listener for touch event
mainView.setOnTouchListener(new android.view.View.OnTouchListener() {
public boolean onTouch(android.view.View v, android.view.MotionEvent e) {
//set ball position based on screen touch
mBallPos.x = e.getX();
mBallPos.y = e.getY();
//timer event will redraw ball
return true;
}
});
} //OnCreate
//listener for menu button on phone
#Override
public boolean onCreateOptionsMenu(Menu menu) {
menu.add("Exit"); //only one menu item
return super.onCreateOptionsMenu(menu);
}
//listener for menu item clicked
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
if (item.getTitle() == "Exit") //user clicked Exit
finish(); //will call onPause
return super.onOptionsItemSelected(item);
}
//For state flow see http://developer.android.com/reference/android/app/Activity.html
#Override
public void onPause() //app moved to background, stop background threads
{
mTmr.cancel(); //kill\release timer (our only background thread)
mTmr = null;
mTsk = null;
super.onPause();
}
#Override
public void onResume() //app moved to foreground (also occurs at app startup)
{
//create timer to move ball to new position
mTmr = new Timer();
mTsk = new TimerTask() {
public void run() {
//if debugging with external device,
// a log cat viewer will be needed on the device
Log.d("TiltBall", "Timer Hit - " + mBallPos.x + ":" + mBallPos.y);
//move ball based on current speed
mBallPos.x += mBallSpd.x;
mBallPos.y += mBallSpd.y;
//if ball goes off screen, reposition to opposite side of screen
if (mBallPos.x > mScrWidth) mBallPos.x = 0;
if (mBallPos.y > mScrHeight) mBallPos.y = 0;
if (mBallPos.x < 0) mBallPos.x = mScrWidth;
if (mBallPos.y < 0) mBallPos.y = mScrHeight;
//update ball class instance
mBallView.x = mBallPos.x;
mBallView.y = mBallPos.y;
//redraw ball. Must run in background thread to prevent thread lock.
RedrawHandler.post(new Runnable() {
public void run() {
mBallView.invalidate();
}
});
}
}; // TimerTask
mTmr.schedule(mTsk, 10, 10); //start timer
super.onResume();
} // onResume
#Override
public void onDestroy() //main thread stopped
{
super.onDestroy();
//wait for threads to exit before clearing app
System.runFinalizersOnExit(true);
//remove app from memory
android.os.Process.killProcess(android.os.Process.myPid());
}
//listener for config change.
//This is called when user tilts phone enough to trigger landscape view
// we want our app to stay in portrait view, so bypass event
#Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
}
} //TiltBallActivity
Here is the BallView class;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
public class BallView extends View {
public float x;
public float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//construct new ball object
public BallView(Context context, float x, float y, int r) {
super(context);
//color hex is [transparncy][red][green][blue]
mPaint.setColor(0xFF1325E0); //not transparent. color is blue
this.x = x;
this.y = y;
this.r = r; //radius
}
//qcalled by invalidate()
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawCircle(x, y, r, mPaint);
}
public int getRadius(){
return r;
}
}
This is not my code but I forgot its source so credits to whoever made it. I am using it for a current project I'm working on.
I'm developing an application,in this when user touch on a image he will see an animated image for a while and come back to original image .
I'm able to animate gif file ,but the animation is running repeatedly , how to restrict animation, once the animation completes and comes back to image view
please anybody help me regarding this,
thanks in advance
here is my code
package purpletalk.gifanimation;
import java.io.InputStream;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Movie;
import android.graphics.Point;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.view.View.OnTouchListener;
import android.view.animation.OvershootInterpolator;
public class GifAnimationDemo extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
ImageView image;
static int i=0;
AnimationDrawable rocketAnimation;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
System.out.println("\tmoviestart121321="+i);
image=(ImageView)findViewById(R.id.imageView1);
image.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
/*image.setBackgroundResource(R.drawable.babyanim);
rocketAnimation = (AnimationDrawable)image.getBackground();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
rocketAnimation.start();
rocketAnimation.isOneShot();
return true;
}
*/
if (event.getAction() == MotionEvent.ACTION_DOWN) {
setContentView(new GIFView(this));
}
else
{setContentView(R.layout.main);
}
return false;
}
class GIFView extends View {
Movie movie;
InputStream is=null;
long moviestart;
private long startTime;
private long endTime;
private long duration=100000;
public GIFView(Context context) {
super(context);
is=context.getResources().openRawResource(R.drawable.baby1);
movie=Movie.decodeStream(is);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xFFCCCCCC);
super.onDraw(canvas);
//long now=android.os.SystemClock.uptimeMillis();
long curTime = System.currentTimeMillis();
// float percentTime = (float) (curTime - startTime)
// (float) (endTime - startTime);
//System.out.println("now="+now);
// first time
moviestart = 0;
System.out.println("\tmoviestart="+i);
int relTime = (int)((curTime - moviestart) % movie.duration()) ;
// System.out.println("time="+relTime+"\treltime="+movie.duration());
// movie.setTime((int) (now+movie.duration()));
// movie.duration();
movie.setTime(relTime);
movie.draw(canvas,20,20);
this.invalidate();
}
#Override
protected void onAnimationEnd() {
// TODO Auto-generated method stub
Log.e("Animation end","time");
super.onAnimationEnd();
}
public void onAnimateMove(float dx, float dy, long duration) {
startTime = System.currentTimeMillis();
endTime = startTime + duration;
}
}
}