My program is animating an imageView. This image should be in the very center of the screen. The problem is, that the image isn't in the center at all. I tried to do it with
if (x<0) {
x = this.getWidth()/2;
y = this.getHeight()/2;
}
but the program doesn't give the favored result. is it the wrong way to center it, or what's wrong?
public class AnimatedView extends ImageView{
private Context mContext;
int x = -1;
int y = -1;
private int xVelocity = 10;
private int yVelocity = 5;
private Handler h;
private final int FRAME_RATE = 30;
boolean continueAnimation = true;
private ImageView imageView;
private BitmapDrawable ball;
public AnimatedView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
h = new Handler();
imageView = (ImageView) findViewById(R.id.imageview1);
}
private Runnable r = new Runnable() {
#Override
public void run() {
if(continueAnimation) {
invalidate();
}
}
};
protected void onDraw(Canvas c) {
ball = (BitmapDrawable) mContext.getResources().getDrawable(R.drawable.ballrot);
if (x<0) {
x = this.getWidth()/2;
y = this.getHeight()/2;
}
else {
x += xVelocity;
if ((x > this.getWidth() - ball.getBitmap().getWidth()) || (x < 0)) {
boolean continueAnimation = false;
}
}
c.drawBitmap(ball.getBitmap(), x, y, null);
if(continueAnimation)
{
h.postDelayed(r, FRAME_RATE);
}
else {
x = this.getWidth()-ball.getBitmap().getWidth();
}
}
}
To calculate center position programmatically you need to know the size of the object to be centered and container where the object reside.
centerx = container.getWidth()/2 - obj.getWidth()/2;
centery = container.getHeight()/2 - obj.getHeight()/2;
With assumption that you use top left position of object
Related
I have been working at it for some time and looking it up online however can't find anything.
I'm trying to work out why the Log I created under
Player.Update() is always returning 0 whereas the Log in my Setter is reporting the right values.
The relevant code should be below.
MainActivity
package com.Frenchie.AnimatedSprite;
import ...
public class MainActivity extends Activity implements SensorEventListener {
//Accelerometer
private SensorManager senSensorManager;
private Sensor senAccelerometer;
private static int DIRECTION_STATIONARY = 0;
private static int DIRECTION_DOWN = 1;
private static int DIRECTION_LEFT = 2;
private static int DIRECTION_RIGHT = 3;
private static int DIRECTION_UP = 4;
Player player;
GameView gameView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameView = new GameView(this);
player = new Player();
setContentView(gameView);
//Accelerometer
senSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
senAccelerometer = senSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
senSensorManager.registerListener(this, senAccelerometer , SensorManager.SENSOR_DELAY_FASTEST);
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
Sensor mySensor = sensorEvent.sensor;
if (mySensor.getType() == Sensor.TYPE_ACCELEROMETER) {
if (sensorEvent.values[0] < -1){
player.setDirection(DIRECTION_UP);
//Log.d("onSensorChanged", ""+ player.getDirection());
}
else if (sensorEvent.values[0] > 1){
player.setDirection(DIRECTION_DOWN);
}
else if (sensorEvent.values[1] < -1){
player.setDirection(DIRECTION_LEFT);
}
else if (sensorEvent.values[1] > 1){
player.setDirection(DIRECTION_RIGHT);
}
else{
player.setDirection(DIRECTION_STATIONARY);
}
//Log.d("Player Update", "X:" +sensorEvent.values[0]+ " Y:" +sensorEvent.values[1]+ " Z:" +sensorEvent.values[2] + " Direction: " + direction);
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
}
Player.java
package com.Frenchie.AnimatedSprite;
import ...
public class Player {
private Bitmap sprite;
private int x, y, speed;
//Animation Variables
private static final int SPRITE_ROWS = 4;
private static final int SPRITE_COLUMNS = 4;
private int currentFrame, width, height, srcY, srcX, direction;
Rect src, dst;
//Static Directions
private static int DIRECTION_STATIONARY = 0;
private static int DIRECTION_DOWN = 1;
private static int DIRECTION_LEFT = 2;
private static int DIRECTION_RIGHT = 3;
private static int DIRECTION_UP = 4;
GameView gameView;
public Player (Context context, GameView gameView){
this.gameView = gameView;
x = 100;
y = 500;
speed = 30;
sprite = BitmapFactory.decodeResource(context.getResources(), R.drawable.player);
width = sprite.getWidth() / SPRITE_COLUMNS;
height = sprite.getHeight() / SPRITE_ROWS;
}
public Player() {
}
public void Update() {
Log.d("Player | Update", "" + direction);
if (direction == DIRECTION_UP){
y -= speed;
}
else if (direction == DIRECTION_DOWN){
y += speed;
}
else if (direction == DIRECTION_RIGHT){
x += speed;
}
else if (direction == DIRECTION_LEFT){
x -= speed;
}
else if (direction == 0){
}
}
public void UpdateAnim(){
currentFrame = ++currentFrame % SPRITE_COLUMNS;
srcX = currentFrame * width;
if (direction == DIRECTION_RIGHT){
srcY = 2 * height;
}
else if (direction == DIRECTION_LEFT){
srcY = 1 * height;
}
if (direction == DIRECTION_DOWN){
srcY = 0 * height;
}
else if (direction == DIRECTION_UP){
srcY = 3 * height;
}
src = new Rect(srcX, srcY, srcX + width, srcY + height);
dst = new Rect(x, y, x + width, y + height);
}
public Rect getSrc(){
return src;
}
public Rect getDst(){
return dst;
}
public Bitmap getSprite() {
return sprite;
}
public void setDirection(int mainDirection) {
this.direction = mainDirection;
Log.d("Setter", "" + direction);
}
}
GameView
package com.Frenchie.AnimatedSprite;
import ...
public class GameView extends SurfaceView implements Runnable {
private Canvas canvas;
private SurfaceHolder surfaceHolder;
private Thread thread;
Player player;
public GameView(Context context) {
super(context);
player = new Player(context, this);
surfaceHolder = getHolder();
thread = new Thread(this);
thread.start();
}
#Override
public void run() {
while (true) {
Update();
DrawCanvas();
}
}
private void Update() {
player.Update();
player.UpdateAnim();
Control();
}
private void DrawCanvas() {
canvas = surfaceHolder.lockCanvas();
if (surfaceHolder.getSurface().isValid()) {
canvas.drawColor(Color.MAGENTA);
canvas.drawBitmap(player.getSprite(), player.getSrc(), player.getDst(), null);
surfaceHolder.unlockCanvasAndPost(canvas);
} else {
Log.d("Run", "Surface Invalid");
}
}
private void Control() {
try {
thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
If you need any more information let me know.
Please I need the help regarding Undo method , I tried to implement it like the code below but it is not remove the last color,
Kindly help me to resolve it.
awaiting your kind response.
Thanks in Advance.
MainActivity
public class MainActivity extends AppCompatActivity implements
View.OnTouchListener {
Button red, blue, yellow, undo;
Paint paint;
private RelativeLayout drawingLayout;
private MyView myView;
private ArrayList<Path> paths = new ArrayList<Path>();
private ArrayList<Path> undonePaths = new ArrayList<Path>();
/**
* Called when the activity is first created.
*/
/*
*
* private ImageView imageView; private Canvas cv; private Bitmap mask,
* original, colored; private int r,g,b; private int sG, sR, sB;
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myView = new MyView(this);
drawingLayout = (RelativeLayout) findViewById(R.id.relative_layout);
drawingLayout.addView(myView);
red = (Button) findViewById(R.id.btn_red);
blue = (Button) findViewById(R.id.btn_blue);
yellow = (Button) findViewById(R.id.btn_yellow);
undo = (Button) findViewById(R.id.undo);
red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.RED);
}
});
yellow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.YELLOW);
}
});
blue.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
paint.setColor(Color.BLUE);
}
});
undo.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
myView.onClickUndo();
}
});
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
// flood fill
public class MyView extends View {
final Point p1 = new Point();
Bitmap mBitmap;
ProgressDialog pd;
Canvas canvas;
private Path path;
// Bitmap mutableBitmap ;
public MyView(Context context) {
super(context);
paint = new Paint();
paint.setAntiAlias(true);
pd = new ProgressDialog(context);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(5f);
mBitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.gp1_1).copy(Bitmap.Config.ARGB_8888, true);
this.path = new Path();
}
public void onClickUndo() {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
Toast.makeText(getContext(), getString(R.string.nomore), Toast.LENGTH_SHORT).show();
}
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas = canvas;
paint.setColor(Color.GREEN);
// int width = drawingLayout.getWidth();
// int height = drawingLayout.getHeight();
// float centerX = (width - mBitmap.getWidth()) * 0.5f;
//float centerY = (height - mBitmap.getHeight()) * 0.5f;
canvas.drawBitmap(mBitmap, 0, 0, paint);
///////////////////////////////
for (Path p : paths) {
canvas.drawPath(p, paint);
//////////////////////////
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
p1.x = (int) x;
p1.y = (int) y;
final int sourceColor = mBitmap.getPixel((int) x, (int) y);
final int targetColor = paint.getColor();
new TheTask(mBitmap, p1, sourceColor, targetColor).execute();
paths.add(path);
invalidate();
}
return true;
}
public void clear() {
path.reset();
invalidate();
}
public int getCurrentPaintColor() {
return paint.getColor();
}
class TheTask extends AsyncTask<Void, Integer, Void> {
Bitmap bmp;
Point pt;
int replacementColor, targetColor;
public TheTask(Bitmap bm, Point p, int sc, int tc) {
this.bmp = bm;
this.pt = p;
this.replacementColor = tc;
this.targetColor = sc;
pd.setMessage(getString(R.string.wait));
pd.show();
}
#Override
protected void onPreExecute() {
pd.show();
}
#Override
protected void onProgressUpdate(Integer... values) {
}
#Override
protected Void doInBackground(Void... params) {
FloodFill f = new FloodFill();
f.floodFill(bmp, pt, targetColor, replacementColor);
return null;
}
#Override
protected void onPostExecute(Void result) {
pd.dismiss();
invalidate();
}
}
}
public class FloodFill {
public void floodFill(Bitmap image, Point node, int targetColor,
int replacementColor) {
int width = image.getWidth();
int height = image.getHeight();
int target = targetColor;
int replacement = replacementColor;
if (target != replacement) {
Queue<Point> queue = new LinkedList<Point>();
do {
int x = node.x;
int y = node.y;
while (x > 0 && image.getPixel(x - 1, y) == target) {
x--;
}
boolean spanUp = false;
boolean spanDown = false;
while (x < width && image.getPixel(x, y) == target) {
image.setPixel(x, y, replacement);
if (!spanUp && y > 0
&& image.getPixel(x, y - 1) == target) {
queue.add(new Point(x, y - 1));
spanUp = true;
} else if (spanUp && y > 0
&& image.getPixel(x, y - 1) != target) {
spanUp = false;
}
if (!spanDown && y < height - 1
&& image.getPixel(x, y + 1) == target) {
queue.add(new Point(x, y + 1));
spanDown = true;
} else if (spanDown && y < height - 1
&& image.getPixel(x, y + 1) != target) {
spanDown = false;
}
x++;
}
} while ((node = queue.poll()) != null);
}
}
}
}
I guess you mean the undo method doesn't work. The possible reason is the previous drawing on the canvas is not removed. Try clearing the canvas before drawing in the onDraw() method.
#Override protected void onDraw(Canvas canvas) {
this.canvas = canvas;
canvas. drawColor(0,PorterDuff.Mode.CLEAR); //This clears the canvas.
paint.setColor(Color.GREEN);
//rest of the code
}
Seems it is impossible to return previous color it is required an array for each point to store the used color in every point.
I have a custom view, that is sometimes being drawn and sometimes not .. this is reproduce-able across multiple phone.
Don't know why this is happening .. setDimensions() is being called during the onMeasure call of a GalleryGridElement (relative layout) which I use as gallery elements in my recyclerview.
One example would be .. going into the recycler view gallery activity, the circular progress view is there .. when you leave the activity and come back .. onResume creates a new adapter and gives it to the recycler view .. however the circular progress views don't show this time:
public class CircularProgressView extends View {
private Paint mIndicatorColour;
private RectF mIndicatorRect;
private Paint mBackCircleColour;
private static final float START_ANGLE = -90;
private volatile float mStopAngle = 0;
private float mOutterCircleStrokeWidth = 20;
private float mInnerCircleStrokeWidth = 16;
private float mViewWidth = 0, mViewHeight = 0;
private volatile int mCurrentProgress = 0;
private ExecutorService mExecutorService;
public CircularProgressView(Context context) {
super(context);
setUp();
}
public CircularProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
setUp();
}
public CircularProgressView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setUp();
}
private void setUp(){
mIndicatorRect = new RectF(0,0,300,300);
mIndicatorColour = new Paint();
mIndicatorColour.setColor(Color.parseColor("#D62F85"));
mIndicatorColour.setStyle(Paint.Style.STROKE);
mIndicatorColour.setStrokeWidth(mInnerCircleStrokeWidth);
mIndicatorColour.setAntiAlias(true);
mIndicatorColour.setDither(true);
mIndicatorColour.setStrokeJoin(Paint.Join.ROUND);
mIndicatorColour.setStrokeCap(Paint.Cap.ROUND);
mBackCircleColour = new Paint();
mBackCircleColour.setColor(Color.WHITE);
mBackCircleColour.setStyle(Paint.Style.STROKE);
mBackCircleColour.setStrokeWidth(mOutterCircleStrokeWidth);
mBackCircleColour.setAntiAlias(true);
mBackCircleColour.setDither(true);
mBackCircleColour.setStrokeJoin(Paint.Join.ROUND);
mBackCircleColour.setStrokeCap(Paint.Cap.ROUND);
mExecutorService = Executors.newSingleThreadExecutor();
}
public void setDimensions(float width, int scaleCircleThicknessValue){
mViewHeight = width;
mViewWidth = width;
mIndicatorRect.left = mIndicatorRect.top = mOutterCircleStrokeWidth;
mIndicatorRect.right = mIndicatorRect.bottom = width - mOutterCircleStrokeWidth;
mIndicatorColour.setStrokeWidth(mInnerCircleStrokeWidth);
mBackCircleColour.setStrokeWidth(mOutterCircleStrokeWidth);
mInnerCircleStrokeWidth = (0.1f * scaleCircleThicknessValue) * width;
mOutterCircleStrokeWidth = mInnerCircleStrokeWidth + 5;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int desiredWidth = Math.round(mViewWidth);
int desiredHeight = Math.round(mViewHeight);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//Set values
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(mIndicatorRect, 0, 360, false, mBackCircleColour);
canvas.drawArc(mIndicatorRect, START_ANGLE, mStopAngle, false, mIndicatorColour);
}
public synchronized void setProgress(final int progress) {
if ((mCurrentProgress != progress) && (progress > 0)) {
mCurrentProgress = progress;
mExecutorService.submit(new Runnable() {
#Override
public void run() {
final float currentAngle = mStopAngle;
float newAngle = (360f * ((float) progress / 100f));
float step = (Math.round(newAngle) - Math.round(currentAngle)) <= 1 ? 1 : (newAngle - currentAngle)/5f;
if (step < 0.01) {
newAngle = 359;
}
for (float i = currentAngle; i < newAngle; i += step) {
try {
mStopAngle = i;
postInvalidate();
Thread.sleep(1000 / 60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
}
}
public float getProgress(){
return (360f-mStopAngle) < 1f ? 1 : mStopAngle / 360f;
}
}
Just following up on this incase someone runs into this issue:
Since I am using a custom view inside a custom view with the recycler view.
When I bind the view-holder to model, I make sure to completely re-render the view ... ie :
mCircularProgressView.setVisibility(VISIBLE);
mCircularProgressView.setDimensions(getWidth() * 0.82f, 1);
mCircularProgressView.requestLayout();
mCircularProgressView.postInvalidate();
This makes sure the view is drawn no matter what.
i have an issue with inserting custom views into my relative layout that takes only a part of the screen. When the activity loads it should populate views with specific width and height at x,y position that i get from my server, then when i click insert mode and click on the relative layout it should draw the view where i clicked as well...The problem is, sometimes it draws rectangle(should be square), sometimes just a line, sometimes nothing. It behaves differently if i change my width and height.
Custom view :
public class TableView extends View {
private static final String TAG = "TableView";
private int numberOfSeats;
private int tableId;
private int positionX;
private int positionY;
private int objectWidth;
private int objectHeight;
private boolean isTaken;
private String tableKind;
private Rect rectangle;
private Paint paint;
/* public TableView(Context context, AttributeSet attrs) {
super(context, attrs);
}*/
public TableView(Context context,int numberOfSeats,int tableId,int positionX,int positionY,int width,int height
,boolean isTaken, String tableKind) {
super(context);
this.numberOfSeats = numberOfSeats;
this.tableId = tableId;
this.positionX = positionX;
this.positionY = positionY;
this.objectWidth = width;
this.objectHeight = height;
this.isTaken = isTaken;
this.tableId = tableId;
this.tableKind = tableKind;
//defining shape
rectangle = new Rect(positionX,positionY,width,height);
//defining shape color
paint = new Paint();
paint.setColor(Color.GRAY);
Log.i(TAG, "TableView: tableId: "+tableId+" isTaken: "+isTaken);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = objectWidth;
int desiredHeight = objectHeight;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can't be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//canvas.drawColor(Color.BLUE);
canvas.drawRect(rectangle, paint);
}
public int getNumberOfSeats() {
return numberOfSeats;
}
public int getTableId() {
return tableId;
}
public int getPositionX() {
return positionX;
}
public int getPositionY() {
return positionY;
}
public int getObjectWidth() {
return objectWidth;
}
public int getObjectHeight() {
return objectHeight;
}
public boolean isTaken() {
return isTaken;
}
public String getTableKind() {
return tableKind;
}
}
Main activity:
public class MainActivity extends AppCompatActivity {
int numberOfSeats = 1;
int tableId = 0;
int positionX = 100;
int positionY = 208;
boolean isTaken = true;
String tableKind = "table";
int objectWidth =200;
int objectHeight=200;
TextView topTable;
RelativeLayout floorPlan ;
Button saveBtn ;
private boolean insertTableCheck = false;
private static final String TAG = "MainActivity";
private int idTest = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
topTable =(TextView) findViewById(R.id.tableView);
floorPlan = (RelativeLayout) findViewById(R.id.floor_plan);
saveBtn = (Button) findViewById(R.id.saveBtn);
for (int i = 0;i<15;i++) {
TableView tv = new TableView(MainActivity.this, numberOfSeats, tableId, positionX, positionY, objectWidth, objectHeight
, isTaken, tableKind);
tv.setTag(i);
positionX +=25;
positionY +=34;
//tv.setY(positionY);
//tv.setX(positionX);
floorPlan.addView(tv);
}
floorPlan.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (insertTableCheck) {
saveBtn.setVisibility(View.VISIBLE);
int x = (int)motionEvent.getX()-objectWidth/2;
int y =(int) motionEvent.getY()-objectHeight/2;
Log.i(TAG, "insertTable: insertingTable on: " + x + " " + y);
TableView tav = new TableView(MainActivity.this,numberOfSeats,tableId,x,
y,objectWidth,objectHeight,isTaken,tableKind);
tav.setX(x);
tav.setY(y);
floorPlan.addView(tav);
/*TextView tableForInsert = new TextView(MainActivity.this);
tableForInsert.setBackgroundColor(Color.BLACK);
tableForInsert.setWidth(objectWidth);
tableForInsert.setHeight(objectHeight);
tableForInsert.setX(x);
tableForInsert.setY(y);
floorPlan.addView(tableForInsert);*/
insertTableCheck = false;
} else {
Log.i(TAG, "onTouch: just clicked on layout");
}
return true;
}
});
}
Note that for loop and the data above is just for testing! Any help would be much appreciated. Thanks
I'm trying to make this game app.
I basically have this BitMap bMapEgg moving down every time UpdateCourt() gets called in a Surfaceview ChickenView. The problem I'm facing is that it looks really chunky. The movement of the bitmap doesn't look smooth.
ballPosition.y += 18; is the code that makes it move.
Any ideas how to make it look smooth?
public class MainActivity extends Activity implements View.OnTouchListener{
static Canvas canvas;
static ChickenView chickenView;
//Used for getting display details like the number of pixels
static Display display;
static Point size;
static int screenWidth;
static int screenHeight;
static Point ballPosition;
static int ballWidth;
static boolean ballIsMovingDown;
//stats
static long lastFrameTime;
static int fps;
static int score;
static int lives;
static float bitmapPositionX ;
static float bitmapPositionY ;
static float bitmapWidth ;
static float bitmapHeight;
static Bitmap bMapEgg;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
chickenView = (ChickenView) findViewById(R.id.chickenView);
//Get the screen size in pixels
display = getWindowManager().getDefaultDisplay();
size = new Point();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
display.getSize(size);
}
screenWidth = size.x;
screenHeight = size.y;
ballWidth = screenWidth / 35;
ballPosition = new Point();
ballPosition.x = screenWidth / 2;
ballPosition.y = 1 + ballWidth;
final ImageView imageEggs = (ImageView)findViewById(R.id.imageEggs);
final ImageView imageUpgrade = (ImageView)findViewById(R.id.imageUpgrade);
TextView test = (TextView)findViewById(R.id.textEggs);
imageUpgrade.setOnTouchListener(this);
chickenView.setOnTouchListener(this);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.imageUpgrade:
if (event.getAction() == MotionEvent.ACTION_DOWN) {
final int x = (int) event.getX();
final int y = (int) event.getY();
//now map the coords we got to the
//bitmap (because of scaling)
ImageView imageView = ((ImageView)v);
Bitmap bitmap =((BitmapDrawable)imageView.getDrawable()).getBitmap();
int pixel = bitmap.getPixel(x,y);
//now check alpha for transparency
int alpha = Color.alpha(pixel);
if (alpha != 0) {
//do whatever you would have done for your click event here
Intent i;
i = new Intent(this, StructureActivity.class);
startActivity(i);
}
}
break;
case R.id.chickenView:
float x = event.getX();
float y = event.getY();
// Replace these with the correct values (bitmap x, y, width & height)
float x1 = bitmapPositionX;
float x2 = x1 + bitmapWidth;
float y1 = bitmapPositionY;
float y2 = y1 + bitmapHeight;
// Test to see if touch is inside the bitmap
if (x > x1 && x < x2 && y > y1 && y < y2) {
// Bitmap was touched
Log.v("test", "test");
} else {
Log.v("werkt ghil ni", "test");
}
break;
}
return true;
}
static class ChickenView extends SurfaceView implements Runnable {
Thread ourThread = null;
SurfaceHolder ourHolder;
volatile boolean playingSquash;
Paint paint;
public ChickenView(Context context) {
super(context);
init(context);
}
public ChickenView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public ChickenView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
ourHolder = getHolder();
paint = new Paint();
ballIsMovingDown = true;
}
#Override
public void run() {
while (playingSquash) {
updateCourt();
drawCourt();
controlFPS();
}
}
public void updateCourt() {
//depending upon the two directions we should be
//moving in adjust our x any positions
if (ballIsMovingDown) {
ballPosition.y += 18;
}
//if hits bottom
if (ballPosition.y > screenHeight - 7*ballWidth) {
ballIsMovingDown = false;
}
}
public void drawCourt() {
if (ourHolder.getSurface().isValid()) {
canvas = ourHolder.lockCanvas();
//Paint paint = new Paint();
canvas.drawColor(Color.BLACK);//the background
paint.setColor(Color.argb(255, 255, 255, 255));
paint.setTextSize(45);
canvas.drawText("Score:" + score + " Lives:" + lives + " fps:" + fps, 20, 40, paint);
Bitmap bMapEgg = BitmapFactory.decodeResource(getResources(), R.drawable.egg);
bMapEgg = scaleDown(bMapEgg,180, true);
Bitmap bMapBackground = BitmapFactory.decodeResource(getResources(), R.drawable.backgrounddd);
canvas.drawBitmap(bMapBackground, 0, 0, paint);
canvas.drawBitmap(bMapEgg, ballPosition.x, ballPosition.y, paint);
bitmapPositionX = ballPosition.x;
bitmapPositionY = ballPosition.y;
bitmapWidth = bMapEgg.getWidth();
bitmapHeight = bMapEgg.getHeight();
ourHolder.unlockCanvasAndPost(canvas);
}
}
public void controlFPS() {
long timeThisFrame = (System.currentTimeMillis() - lastFrameTime);
long timeToSleep = 15 - timeThisFrame;
if (timeThisFrame > 0) {
fps = (int) (1000 / timeThisFrame);
}
if (timeToSleep > 0) {
try {
ourThread.sleep(timeToSleep);
} catch (InterruptedException e) {
}
}
lastFrameTime = System.currentTimeMillis();
}
public void pause() {
playingSquash = false;
try {
ourThread.join();
} catch (InterruptedException e) {
}
}
public void resume() {
playingSquash = true;
ourThread = new Thread(this);
ourThread.start();
}
}
#Override
protected void onStop() {
super.onStop();
while (true) {
chickenView.pause();
break;
}
finish();
}
#Override
protected void onResume() {
super.onResume();
chickenView.resume();
}
#Override
protected void onPause() {
super.onPause();
chickenView.pause();
}
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
chickenView.pause();
finish();
return true;
}
return false;
}
public static Bitmap scaleDown(Bitmap realImage, float maxImageSize,
boolean filter) {
float ratio = Math.min(
(float) maxImageSize / realImage.getWidth(),
(float) maxImageSize / realImage.getHeight());
int width = Math.round((float) ratio * realImage.getWidth());
int height = Math.round((float) ratio * realImage.getHeight());
Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width,
height, filter);
return newBitmap;
}
}
The problem is that in each frame you decode and scale all bitmaps all over again.
Move your bitmaps decoding and scaling out of the draw method, put it in an initialization method and store decoded and scaled bitmaps in member variables (maybe even static ones) so you can just reuse them for drawing in each frame.