How to center align center a Bitmap? - android

I am trying to align center a Bitmap, but I keep failing to do so. I am making a live wallpaper for Android that keeps looping the image. I have simple background and an animation image that overlaps the background.
Here is my code:
import java.io.IOException;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Handler;
import android.os.SystemClock;
import android.service.wallpaper.WallpaperService;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
/*
* This animated wallpaper draws a rotating wireframe cube.
*/
public class CubeWallpaper1 extends WallpaperService {
public static final String SHARED_PREFS_NAME="cube1_settings";
private final Handler mHandler = new Handler();
private static boolean Reverse= false;
private static boolean screenfit = false;
private static String slow;
private static String fast;
private static String medium;
private static String framerate;
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onDestroy() {
super.onDestroy();
}
#Override
public Engine onCreateEngine() {
return new CubeEngine();
}
class CubeEngine extends Engine implements SharedPreferences.OnSharedPreferenceChangeListener {
private final Paint mPaint = new Paint();
private float mOffset;
private float mTouchX = -1;
private float mTouchY = -1;
private long mStartTime;
private float mCenterX;
private float mCenterY;
private float bottom;
private int i=1;
private float screenwidth;
private float halfscreenwidth;
private float screenheight;
private float screenhalfheight;
private boolean plus = false;
private final Runnable mDrawCube = new Runnable() {
public void run() {
drawFrame();
}
};
private boolean mVisible;
private SharedPreferences mPrefs;
CubeEngine() {
final Paint paint = mPaint;
paint.setColor(0xffffffff);
paint.setAntiAlias(true);
paint.setStrokeWidth(2);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.STROKE);
mPrefs = CubeWallpaper1.this.getSharedPreferences(SHARED_PREFS_NAME, 0);
mPrefs.registerOnSharedPreferenceChangeListener(this);
onSharedPreferenceChanged(mPrefs, null);
mStartTime = SystemClock.elapsedRealtime();
}
#Override
public void onCreate(SurfaceHolder surfaceHolder) {
super.onCreate(surfaceHolder);
setTouchEventsEnabled(true);
}
#Override
public void onDestroy() {
super.onDestroy();
mHandler.removeCallbacks(mDrawCube);
}
#Override
public void onVisibilityChanged(boolean visible) {
mVisible = visible;
if (visible) {
drawFrame();
} else {
mHandler.removeCallbacks(mDrawCube);
}
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
super.onSurfaceChanged(holder, format, width, height);
screenwidth = width;
halfscreenwidth = width/2.0f;
screenheight = height;
screenhalfheight = height/2.0f;
drawFrame();
}
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
#Override
public void onSurfaceDestroyed(SurfaceHolder holder) {
super.onSurfaceDestroyed(holder);
mVisible = false;
mHandler.removeCallbacks(mDrawCube);
}
#Override
public void onOffsetsChanged(float xOffset, float yOffset,
float xStep, float yStep, int xPixels, int yPixels) {
mOffset = xOffset;
drawFrame();
}
#Override
public void onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_MOVE) {
mTouchX = event.getX();
mTouchY = event.getY();
} else {
mTouchX = -1;
mTouchY = -1;
}
super.onTouchEvent(event);
}
void drawFrame() {
final SurfaceHolder holder = getSurfaceHolder();
Canvas c = null;
try {
c = holder.lockCanvas();
if (c != null) {
drawCube(c);
drawTouchPoint(c);
}
} finally {
if (c != null) holder.unlockCanvasAndPost(c);
}
mHandler.removeCallbacks(mDrawCube);
if (mVisible) {
mHandler.postDelayed(mDrawCube, 1000 / 600);
if(framerate==slow){
Log.v("slow call ","screen height");
mHandler.postDelayed(mDrawCube, 1000 / 100);
}
else if(framerate==medium){
Log.v("medium call ","screen height");
mHandler.postDelayed(mDrawCube, 1000 / 400);
}
else if(framerate==fast){
Log.v("fast call ","screen height");
mHandler.postDelayed(mDrawCube, 1000 / 1000);
}
}
}
void drawCube(Canvas c) {
c.save();
c.drawColor(0xff000000);
if(Reverse)
{
if (i>73 || i<1)
{
plus = !plus;
if(plus )
i+=2;
else
i-=2;
}
}
else
{
if(i>73)
i=1;
plus =true;
}
try {
if(i<=0 || i>73)
i=1;
THIS IS MY BACKROUND
Bitmap holdmap = BitmapFactory.decodeStream(getAssets().open( "hold.png"));
THIS IS MY IMAGE ANIMATION
Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open((i/10)+""+(i%10)+".png"));
int imgh = bitmap.getHeight();
int himgh = bitmap.getHeight()/2;
int imgw = bitmap.getWidth();
int himgw = bitmap.getWidth()/2;
if(screenfit==false){
if(imgw>screenwidth){
float w1 = imgw - screenwidth;
float omg = imgw-w1;
float nw1 = w1/imgw*100;
float h1 = imgh - screenheight;
float hmg =imgh-h1;
float nh1 = h1/imgh*100;
RectF rf = new RectF(0,0,omg,hmg);
RectF rf2 = new RectF(0,0,300,300);
c.drawBitmap(holdmap, null, rf, mPaint);
c.drawBitmap(bitmap, null, rf2, mPaint);
}else if (imgw<screenwidth){
float w1 = imgw - screenwidth;
float omg=imgw-w1;
float nw1 = w1/imgw*100;
float h1 = imgh - screenheight;
float hmg =imgh-h1;
float nh1 = h1/imgh*100;
RectF rf = new RectF(0,0,omg,hmg);
RectF rf2 = new RectF(0,0,300,300);
c.drawBitmap(holdmap, null, rf, mPaint);
c.drawBitmap(bitmap, null, rf2, mPaint);
}
}else if (screenfit==true){
if(imgw>screenwidth){
float w1 = imgw - screenwidth;
float omg=imgw-w1;
float nw1 = w1/imgw*100;
float h1 = imgh - screenheight;
float hmg =imgh-h1;
float nh1 = h1/imgh*100;
RectF rf = new RectF(0,0,omg,hmg);
RectF rf2 = new RectF(0,0,300,300);
c.drawBitmap(holdmap, null, rf, mPaint);
c.drawBitmap(bitmap, null, rf2, mPaint);
}else if (imgw<screenwidth){
float w1 = imgw - screenwidth;
float omg=imgw-w1;
float nw1 = w1/imgw*100;
float h1 = imgh - screenheight;
float hmg =imgh-h1;
float nh1 = h1/imgh*100;
RectF rf = new RectF(0,0,omg,hmg);
RectF rf2 = new RectF(0,0,300,300);
c.drawBitmap(holdmap, null, rf, mPaint);
c.drawBitmap(bitmap, null, rf2, mPaint);
}
}
if(plus )
i++;
else
i--;
} catch (IOException e) {
e.printStackTrace();
}
c.restore();
}
void drawTouchPoint(Canvas c) {
if (mTouchX >=0 && mTouchY >= 0) {
c.drawCircle(mTouchX, mTouchY, 0, mPaint);
}
}
public void onSharedPreferenceChanged(
SharedPreferences sharedPreferences, String key) {
Reverse = sharedPreferences.getBoolean("reverse", false);
screenfit = sharedPreferences.getBoolean("screenfit", false);
framerate = sharedPreferences.getString("framerate","fast");
}
}
}

Related

I live wallpaper just shows up as black, its supposed to draw a background image and then layover glitter effects with touch glitter trail effects

This is my code below but its not working. I am trying to draw a background image, and then have random sparkles and glitter effects randomly show on the screen. All I get is a black screen.
package com.griffslabs.glitterlwptest;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.service.wallpaper.WallpaperService;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import java.util.ArrayList;
import java.util.Random;
public class RainbowSparkleWallpaperService extends WallpaperService {
#Override
public Engine onCreateEngine() {
return new RainbowSparkleEngine();
}
class RainbowSparkleEngine extends Engine {
private ArrayList<Sparkle> sparkles = new ArrayList<>();
private ArrayList<GlitterTrail> glitterTrails = new ArrayList<>();
private Paint paint = new Paint();
private int sparkleSize = 5;
private int glitterTrailSize = 10;
private int sparkleSpeed = 5;
private int glitterTrailSpeed = 2;
private int width;
private int height;
private Random random = new Random();
#Override
public void onSurfaceCreated(SurfaceHolder holder) {
super.onSurfaceCreated(holder);
}
#Override
public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) {
this.width = width;
this.height = height;
super.onSurfaceChanged(holder, format, width, height);
}
#Override
public void onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
int x = (int) event.getX();
int y = (int) event.getY();
sparkles.add(new Sparkle(x, y, sparkleSize, sparkleSpeed));
glitterTrails.add(new GlitterTrail(x, y, glitterTrailSize, glitterTrailSpeed));
}
private class DrawThread extends Thread {
private boolean running = false;
private SurfaceHolder surfaceHolder;
DrawThread(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
}
void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
Canvas canvas;
while (running) {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
Rect frame = surfaceHolder.getSurfaceFrame();
onDraw(canvas, frame);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
}
public void onDraw(Canvas canvas, Rect frame) {
canvas.drawBitmap(getBackgroundImage(), null, frame, null);
for (int i = 0; i < sparkles.size(); i++) {
Sparkle sparkle = sparkles.get(i);
paint.setColor(sparkle.color);
canvas.drawCircle(sparkle.x, sparkle.y, sparkle.size, paint);
sparkle.update();
if (sparkle.y + sparkle.size < 0 || sparkle.y - sparkle.size > height) {
sparkles.remove(sparkle);
}
}
for (int i = 0; i < glitterTrails.size(); i++) {
GlitterTrail glitterTrail = glitterTrails.get(i);
paint.setColor(glitterTrail.color);
canvas.drawRect(glitterTrail.x, glitterTrail.y, glitterTrail.x + glitterTrail.size, glitterTrail.y + glitterTrail.size, paint);
glitterTrail.update();
if (glitterTrail.y + glitterTrail.size < 0 || glitterTrail.y - glitterTrail.size > height) {
glitterTrails.remove(glitterTrail);
}
}
}
private Bitmap getBackgroundImage() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
Bitmap background = BitmapFactory.decodeResource(getResources(), R.drawable.background, options);
background = Bitmap.createScaledBitmap(background, width, height, true);
return background;
}
private class Sparkle {
int x;
int y;
int size;
int speed;
int color;
Sparkle(int x, int y, int size, int speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.color = getRandomColor();
}
void update() {
y -= speed;
}
int getRandomColor() {
int[] rainbowColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
return rainbowColors[random.nextInt(rainbowColors.length)];
}
}
private class GlitterTrail {
int x;
int y;
int size;
int speed;
int color;
GlitterTrail(int x, int y, int size, int speed) {
this.x = x;
this.y = y;
this.size = size;
this.speed = speed;
this.color = getRandomColor();
}
void update() {
y -= speed;
}
int getRandomColor() {
int[] rainbowColors = {Color.RED, Color.YELLOW, Color.GREEN, Color.BLUE, Color.MAGENTA};
return rainbowColors[random.nextInt(rainbowColors.length)];
}
}
}
}
expecting it to work. I have tried almost everything and it just does not work. any input will be aprecciated.

How can I make the background of my custom brush transparent?

I wanted to draw on the canvas with the code below with my custom brush, but as you can see in the picture, the background of my brush is black, albeit without color.
Although I specified the brush color as Color.TRANSPARENT or Color.parseColor ("# 00000000"), the brush background still turns black.
How can I make the background color of my brush transparent?
click to see the picture
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PathMeasure;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import androidx.annotation.ColorInt;
import androidx.annotation.IntRange;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.MotionEvent;
import android.view.View;
import java.util.Stack;
public class BrushDrawingView extends View {
static final float DEFAULT_BRUSH_SIZE = 50.0f;
static final float DEFAULT_ERASER_SIZE = 50.0f;
static final int DEFAULT_OPACITY = 255;
private float mBrushSize = DEFAULT_BRUSH_SIZE;
private float mBrushEraserSize = DEFAULT_ERASER_SIZE;
private int mOpacity = DEFAULT_OPACITY;
private final Stack<BrushLinePath> mDrawnPaths = new Stack<>();
private final Stack<BrushLinePath> mRedoPaths = new Stack<>();
private final Paint mDrawPaint = new Paint();
private Canvas mDrawCanvas;
private boolean mBrushDrawMode;
private Bitmap brushBitmap;
private Path mPath;
private float mTouchX, mTouchY;
private static final float TOUCH_TOLERANCE = 4;
private BrushViewChangeListener mBrushViewChangeListener;
public BrushDrawingView(Context context) {
this(context, null);
}
public BrushDrawingView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public BrushDrawingView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupBrushDrawing();
}
private void setupBrushDrawing() {
//Caution: This line is to disable hardware acceleration to make eraser feature work properly
setupPathAndPaint();
setVisibility(View.GONE);
}
private void setupPathAndPaint() {
mPath = new Path();
mDrawPaint.setAntiAlias(true);
mDrawPaint.setStyle(Paint.Style.STROKE);
mDrawPaint.setStrokeJoin(Paint.Join.ROUND);
mDrawPaint.setStrokeCap(Paint.Cap.ROUND);
mDrawPaint.setStrokeWidth(mBrushSize);
mDrawPaint.setAlpha(mOpacity);
}
private void refreshBrushDrawing() {
mBrushDrawMode = true;
setupPathAndPaint();
}
void brushEraser() {
mBrushDrawMode = true;
mDrawPaint.setStrokeWidth(mBrushEraserSize);
mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
}
public void setBrushDrawingMode(boolean brushDrawMode) {
this.mBrushDrawMode = brushDrawMode;
if (brushDrawMode) {
this.setVisibility(View.VISIBLE);
refreshBrushDrawing();
}
}
public Bitmap getBrushBitmap() {
return brushBitmap;
}
public void setBrushBitmap(Bitmap brushBitmap) {
this.brushBitmap = brushBitmap;
}
public void setOpacity(#IntRange(from = 0, to = 255) int opacity) {
this.mOpacity = (int) (opacity * 2.55f);
setBrushDrawingMode(true);
}
public int getOpacity() {
return mOpacity;
}
boolean getBrushDrawingMode() {
return mBrushDrawMode;
}
public void setBrushSize(float size) {
mBrushSize = 5 + (int) (size);
setBrushDrawingMode(true);
}
void setBrushColor(#ColorInt int color) {
mDrawPaint.setColor(color);
setBrushDrawingMode(true);
}
void setBrushEraserSize(float brushEraserSize) {
this.mBrushEraserSize = brushEraserSize;
setBrushDrawingMode(true);
}
void setBrushEraserColor(#ColorInt int color) {
mDrawPaint.setColor(color);
setBrushDrawingMode(true);
}
float getEraserSize() {
return mBrushEraserSize;
}
public float getBrushSize() {
return mBrushSize;
}
int getBrushColor() {
return mDrawPaint.getColor();
}
public void clearAll() {
mDrawnPaths.clear();
mRedoPaths.clear();
if (mDrawCanvas != null) {
mDrawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
}
invalidate();
}
void setBrushViewChangeListener(BrushViewChangeListener brushViewChangeListener) {
mBrushViewChangeListener = brushViewChangeListener;
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Bitmap canvasBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
mDrawCanvas = new Canvas(canvasBitmap);
}
#Override
protected void onDraw(Canvas canvas) {
for (BrushLinePath linePath : mDrawnPaths) {
canvas.drawPath(linePath.getDrawPath(), linePath.getDrawPaint());
}
canvas.drawPath(mPath, mDrawPaint);
/////
final Bitmap scaledBitmap = getScaledBitmap();
final float centerX = scaledBitmap.getWidth() / 2;
final float centerY = scaledBitmap.getHeight() / 2;
final PathMeasure pathMeasure = new PathMeasure(mPath, false);
float distance = scaledBitmap.getWidth() / 2;
float[] position = new float[2];
float[] slope = new float[2];
float slopeDegree;
while (distance < pathMeasure.getLength())
{
pathMeasure.getPosTan(distance, position, slope);
slopeDegree = (float)((Math.atan2(slope[1], slope[0]) * 180f) / Math.PI);
canvas.save();
canvas.translate(position[0] - centerX, position[1] - centerY);
canvas.rotate(slopeDegree, centerX, centerY);
canvas.drawBitmap(scaledBitmap, 0, 0, mDrawPaint);
canvas.restore();
distance += scaledBitmap.getWidth() + 10;
}
}
/////
private Bitmap getScaledBitmap()
{
// width / height of the bitmap[
float width = brushBitmap.getWidth();
float height = brushBitmap.getHeight();
// ratio of the bitmap
float ratio = width / height;
// set the height of the bitmap to the width of the path (from the paint object).
float scaledHeight = mDrawPaint.getStrokeWidth();
// to maintain aspect ratio of the bitmap, use the height * ratio for the width.
float scaledWidth = scaledHeight * ratio;
// return the generated bitmap, scaled to the correct size.
return Bitmap.createScaledBitmap(brushBitmap, (int)scaledWidth, (int)scaledHeight, true);
}
/**
* Handle touch event to draw paint on canvas i.e brush drawing
*
* #param event points having touch info
* #return true if handling touch events
*/
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
if (mBrushDrawMode) {
float touchX = event.getX();
float touchY = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchStart(touchX, touchY);
break;
case MotionEvent.ACTION_MOVE:
touchMove(touchX, touchY);
break;
case MotionEvent.ACTION_UP:
touchUp();
break;
}
invalidate();
return true;
} else {
return false;
}
}
boolean undo() {
if (!mDrawnPaths.empty()) {
mRedoPaths.push(mDrawnPaths.pop());
invalidate();
}
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onViewRemoved(this);
}
return !mDrawnPaths.empty();
}
boolean redo() {
if (!mRedoPaths.empty()) {
mDrawnPaths.push(mRedoPaths.pop());
invalidate();
}
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onViewAdd(this);
}
return !mRedoPaths.empty();
}
private void touchStart(float x, float y) {
mRedoPaths.clear();
mPath.reset();
mPath.moveTo(x, y);
mTouchX = x;
mTouchY = y;
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onStartDrawing();
}
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - mTouchX);
float dy = Math.abs(y - mTouchY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mTouchX, mTouchY, (x + mTouchX) / 2, (y + mTouchY) / 2);
mTouchX = x;
mTouchY = y;
}
}
private void touchUp() {
mPath.lineTo(mTouchX, mTouchY);
// Commit the path to our offscreen
mDrawCanvas.drawPath(mPath, mDrawPaint);
// kill this so we don't double draw
mDrawnPaths.push(new BrushLinePath(mPath, mDrawPaint));
/////
final Bitmap scaledBitmap = getScaledBitmap();
final float centerX = scaledBitmap.getWidth() / 2;
final float centerY = scaledBitmap.getHeight() / 2;
final PathMeasure pathMeasure = new PathMeasure(mPath, false);
float distance = scaledBitmap.getWidth() / 2;
float[] position = new float[2];
float[] slope = new float[2];
float slopeDegree;
while (distance < pathMeasure.getLength())
{
pathMeasure.getPosTan(distance, position, slope);
slopeDegree = (float)((Math.atan2(slope[1], slope[0]) * 180f) / Math.PI);
mDrawCanvas.save();
mDrawCanvas.translate(position[0] - centerX, position[1] - centerY);
mDrawCanvas.rotate(slopeDegree, centerX, centerY);
mDrawCanvas.drawBitmap(scaledBitmap, 0, 0, mDrawPaint);
mDrawCanvas.restore();
distance += scaledBitmap.getWidth() + 10;
}
/////
mPath = new Path();
if (mBrushViewChangeListener != null) {
mBrushViewChangeListener.onStopDrawing();
mBrushViewChangeListener.onViewAdd(this);
}
}
#VisibleForTesting
Paint getDrawingPaint() {
return mDrawPaint;
}
#VisibleForTesting
Pair<Stack<BrushLinePath>, Stack<BrushLinePath>> getDrawingPath() {
return new Pair<>(mDrawnPaths, mRedoPaths);
}
}
public interface BrushViewChangeListener {
void onViewAdd(BrushDrawingView brushDrawingView);
void onViewRemoved(BrushDrawingView brushDrawingView);
void onStartDrawing();
void onStopDrawing();
}
class BrushLinePath {
private final Paint mDrawPaint;
private final Path mDrawPath;
BrushLinePath(final Path drawPath, final Paint drawPaints) {
mDrawPaint = new Paint(drawPaints);
mDrawPath = new Path(drawPath);
}
Paint getDrawPaint() {
return mDrawPaint;
}
Path getDrawPath() {
return mDrawPath;
}
}
The reason it happens is because Paint doesn't have an alpha composing mode set by default. Thus, when you're trying to paint a bitmap over your canvas it will replace the destination pixels with your brush pixels, which in your case is #00000000. And that will result in pixel being displayed as black. Have a look into this documentation: https://developer.android.com/reference/android/graphics/PorterDuff.Mode
By the first glance it seems you're looking for PorterDuff.Mode.SRC_OVER or PorterDuff.Mode.SRC_ATOP - this way transparent pixels from your source image (your brush) will not over-draw the pixels from your destination (canvas). In case your background is always non-transparent, you will see no difference between SRC_OVER and SRC_ATOP, but if it isn't - choose the one which fits your needs. Then you can modify setupPathAndPaint method by adding this line to its end:
mDrawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));

Changing background color of SignatureView

I found this code on stack and it works well. However, there is an issue. While I'm able to set its background color, the color changes to black as soon as the clearSignature() function is called.
Why is that happening?
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* A simple view to capture a path traced onto the screen. Initially intended to
* be used to captures signatures.
*
* #author Andrew Crichton
* #version 0.1
*/
public class SignatureView extends View
{
private Path mPath;
private Paint mPaint;
private Paint bgPaint = new Paint(Color.TRANSPARENT);
private Bitmap mBitmap;
private Canvas mCanvas;
private float curX, curY;
private static final int TOUCH_TOLERANCE = 4;
private static final int STROKE_WIDTH = 4;
boolean modified = false;
public SignatureView(Context context)
{
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public SignatureView(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
init();
}
private void init()
{
setFocusable(true);
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(STROKE_WIDTH);
}
public void setSigColor(int color)
{
mPaint.setColor(color);
}
public void setSigColor(int a, int red, int green, int blue)
{
mPaint.setARGB(a, red, green, blue);
}
public boolean clearSignature()
{
if (mBitmap != null)
createFakeMotionEvents();
if (mCanvas != null)
{
mCanvas.drawColor(Color.BLACK);
mCanvas.drawPaint(bgPaint);
mPath.reset();
invalidate();
}
else
{
return false;
}
return true;
}
public Bitmap getImage()
{
return this.mBitmap;
}
public void setImage(Bitmap bitmap)
{
this.mBitmap = bitmap;
this.invalidate();
}
public boolean hasChanged()
{
return modified;
}
#Override protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
{
int bitmapWidth = mBitmap != null ? mBitmap.getWidth() : 0;
int bitmapHeight = mBitmap != null ? mBitmap.getWidth() : 0;
if (bitmapWidth >= width && bitmapHeight >= height)
return;
if (bitmapWidth < width)
bitmapWidth = width;
if (bitmapHeight < height)
bitmapHeight = height;
Bitmap newBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas newCanvas = new Canvas();
newCanvas.setBitmap(newBitmap);
if (mBitmap != null)
newCanvas.drawBitmap(mBitmap, 0, 0, null);
mBitmap = newBitmap;
mCanvas = newCanvas;
}
private void createFakeMotionEvents()
{
MotionEvent downEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis() + 100, MotionEvent.ACTION_DOWN,
1f, 1f, 0);
MotionEvent upEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis() + 100, MotionEvent.ACTION_UP, 1f,
1f, 0);
onTouchEvent(downEvent);
onTouchEvent(upEvent);
}
#Override protected void onDraw(Canvas canvas)
{
modified = true;
canvas.drawColor(Color.RED);
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
canvas.drawPath(mPath, mPaint);
}
#Override public boolean onTouchEvent(MotionEvent event)
{
float x = event.getX();
float y = event.getY();
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
touchDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
break;
case MotionEvent.ACTION_UP:
touchUp();
break;
}
invalidate();
return true;
}
/**
* ---------------------------------------------------------- Private
* methods ---------------------------------------------------------
*/
private void touchDown(float x, float y)
{
mPath.reset();
mPath.moveTo(x, y);
curX = x;
curY = y;
}
private void touchMove(float x, float y)
{
float dx = Math.abs(x - curX);
float dy = Math.abs(y - curY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE)
{
mPath.quadTo(curX, curY, (x + curX) / 2, (y + curY) / 2);
curX = x;
curY = y;
}
}
private void touchUp()
{
mPath.lineTo(curX, curY);
if (mCanvas == null)
{
mCanvas = new Canvas();
mCanvas.setBitmap(mBitmap);
}
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
}
Well I have updated the original SignatureView code, now it supports a custom signature background color. This color is different from the view's background color!
setSigBackgroundColor()
I also made some other optimizations, use on your own risk as this is minimal tested!
Small list of optimizations:
Better bitmap recycling etc.
Recycling of MotionEvents
Added signature background color set method
Optimizations
Changed setImage method, although still not very safe to use!
New code:
import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.os.SystemClock;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
/**
* A simple view to capture a path traced onto the screen. Initially intended to
* be used to captures signatures.
*
* #author Andrew Crichton
* #version 0.1.1
*
* Modified by Rolf Smit
* -Recycle bitmaps
* -Recycle MotionEvents
* -Signature Background color changes
* -Optimizations
* -Changed setImage method, although still unsafe to use!
*/
public class SignatureView extends View {
private Path mPath;
private Paint mPaint;
private Bitmap mBitmap;
private Canvas mCanvas;
private int sigBackgroundColor = Color.TRANSPARENT;
private float curX, curY;
private static final int TOUCH_TOLERANCE = 4;
private static final int STROKE_WIDTH = 4;
boolean modified = false;
public SignatureView(Context context) {
super(context);
init();
}
public SignatureView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SignatureView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init() {
setFocusable(true);
mPath = new Path();
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mPaint.setColor(Color.WHITE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(STROKE_WIDTH);
}
public void setSigColor(int color) {
mPaint.setColor(color);
}
public void setSigColor(int alpha, int red, int green, int blue) {
mPaint.setARGB(alpha, red, green, blue);
}
public void setSigBackgroundColor(int color){
sigBackgroundColor = color;
}
public void setSigBackgroundColor(int alpha, int red, int green, int blue){
sigBackgroundColor = Color.argb(alpha, red, green, blue);
}
public boolean clearSignature() {
if (mBitmap != null) {
createFakeMotionEvents();
}
if (mCanvas != null) {
mCanvas.drawColor(sigBackgroundColor);
mPath.reset();
invalidate();
} else {
return false;
}
return true;
}
public Bitmap getImage() {
return Bitmap.createBitmap(mBitmap);
}
public void setImage(Bitmap bitmap){
this.mBitmap = bitmap;
if(mCanvas != null){
mCanvas.setBitmap(mBitmap);
}
}
public boolean hasChanged() {
return modified;
}
#Override
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
int bitmapWidth = mBitmap != null ? mBitmap.getWidth() : 0;
int bitmapHeight = mBitmap != null ? mBitmap.getWidth() : 0;
if (bitmapWidth >= width && bitmapHeight >= height) {
return;
}
if (bitmapWidth < width) {
bitmapWidth = width;
}
if (bitmapHeight < height) {
bitmapHeight = height;
}
Bitmap newBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
Canvas newCanvas = new Canvas();
newCanvas.setBitmap(newBitmap);
mCanvas = newCanvas;
if (mBitmap != null) {
newCanvas.drawBitmap(mBitmap, 0, 0, null);
mBitmap.recycle();
} else {
newCanvas.drawColor(sigBackgroundColor);
}
mBitmap = newBitmap;
}
private void createFakeMotionEvents() {
MotionEvent downEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis() + 100, MotionEvent.ACTION_DOWN, 1f, 1f, 0);
MotionEvent upEvent = MotionEvent.obtain(SystemClock.uptimeMillis(), SystemClock.uptimeMillis() + 100, MotionEvent.ACTION_UP, 1f, 1f, 0);
onTouchEvent(downEvent);
onTouchEvent(upEvent);
downEvent.recycle();
upEvent.recycle();
}
#Override
protected void onDraw(Canvas canvas) {
modified = true;
canvas.drawBitmap(mBitmap, 0, 0, mPaint);
canvas.drawPath(mPath, mPaint);
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
touchDown(x, y);
break;
case MotionEvent.ACTION_MOVE:
touchMove(x, y);
break;
case MotionEvent.ACTION_UP:
touchUp();
break;
}
invalidate();
return true;
}
private void touchDown(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
curX = x;
curY = y;
}
private void touchMove(float x, float y) {
float dx = Math.abs(x - curX);
float dy = Math.abs(y - curY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(curX, curY, (x + curX) / 2, (y + curY) / 2);
curX = x;
curY = y;
}
}
private void touchUp() {
mPath.lineTo(curX, curY);
if (mCanvas == null) {
mCanvas = new Canvas();
mCanvas.setBitmap(mBitmap);
}
mCanvas.drawPath(mPath, mPaint);
mPath.reset();
}
}

android-update line between two rotating rectangles

after i draw line between 2 fixed points on two different rectangles i need to rotate them.The problem is that my line is not updated, it stays on the same x1,y1 x2,y2. How to make line to follow this rectangle?
If any of you have any example code or something that can help, it would be great!
Thanks!
I dont think that i will need OnValidateUpdate tho solve this.
This is my example code to demonstrate this problem:
Object that i want to draw:
public class Object {
private int xPos;
private int yPos;
private int width;
private int height;
float xDistance = 0f;
float yDistance = 0f;
double angleToTurn = 0.0;
Matrix matrix = new Matrix();
private Rect rect;
private Paint paint;
private Point point;
Paint p = null;
public Object(int xPos, int yPos){
this.xPos = xPos;
this.yPos = yPos;
this.width = 300;
this.height = 100;
matrix = new Matrix();
rect = new Rect(xPos,yPos,xPos + width,yPos + height);
paint = new Paint();
paint.setStyle(Style.FILL);
paint.setColor(Color.BLUE);
p = new Paint();
p.setStyle(Style.FILL);
p.setStrokeWidth(15);
p.setColor(Color.BLACK);
point = new Point(this.getxPos(), this.getyPos()+this.getHeight());
}
public void rotate(float xEvent, float yEvent){
xDistance = xEvent - this.xPos;
yDistance = yEvent - this.yPos;
int angleToTurn = ((int)Math.toDegrees(Math.atan2(yDistance, xDistance)));
matrix.setRotate((int)(angleToTurn),xPos,yPos + height/2);
}
public void draw(Canvas c){
c.save();
c.setMatrix(matrix);
c.drawRect(rect, paint);
c.drawPoint(point.x,point.y,p);
c.restore();
}
public Point getPoint() {
return point;
}
public void setPoint(Point point) {
this.point = point;
}
public Matrix getMatrix() {
return matrix;
}
public void setMatrix(Matrix matrix) {
this.matrix = matrix;
}
public int getxPos() {
return xPos;
}
public void setxPos(int xPos) {
this.xPos = xPos;
}
public int getyPos() {
return yPos;
}
public void setyPos(int yPos) {
this.yPos = yPos;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
GameView class where i draw 2 rects:
public class GameView extends SurfaceView implements SurfaceHolder.Callback{
private SurfaceHolder surfaceHolder;
private GameloopThread gameloopThread;
float downx,downy,upx,upy;
private Object object,object1;
Line line;
public GameView(Context context) {
super(context);
gameloopThread = new GameloopThread(this);
surfaceHolder = getHolder();
surfaceHolder.addCallback(this);
object = new Object(500,500);
object1 = new Object(800,700);
line = new Line(object.getPoint(),object1.getPoint());
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas canvas = surfaceHolder.lockCanvas();
onDraw(canvas);
surfaceHolder.unlockCanvasAndPost(canvas);
gameloopThread.setRunning(true);
gameloopThread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
gameloopThread.setRunning(false);
while(retry){
try {
gameloopThread.join();
retry=false;
}catch(InterruptedException e){
}
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {
}
#SuppressLint("ClickableViewAccessibility")
#Override
public boolean onTouchEvent( MotionEvent event) {
float x = 0f,y=0f;
if(event.getAction() == MotionEvent.ACTION_DOWN){
downx = event.getX();
downy = event.getY();
}
if (event.getAction() == MotionEvent.ACTION_MOVE) {
x = event.getX();
y = event.getY();
object.rotate(x, y);
object1.rotate(x, y);
}
if (event.getAction() == MotionEvent.ACTION_UP) {
}
return true;
}
#Override
public void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawColor(Color.LTGRAY);
if(object != null)
object.draw(canvas);
if(object1 != null)
object1.draw(canvas);
if(line != null){
line._drawLine(canvas);
}
}
}
Line class that should connect two rectangles (i made class for it but it is not needed)
public class Line {
private Point point1,point2;
private Paint p;
Matrix m;
public Line(Point p1,Point p2){
this.point1 = p1;
this.point2 = p2;
p = new Paint();
p.setStyle(Style.FILL);
p.setColor(Color.RED);
m = new Matrix();
}
public void _drawLine(Canvas c){
c.setMatrix(m);
c.save();
c.drawLine(point1.x, point1.y, point2.x, point2.y, p);
c.restore();
}
public Matrix getMatrix(){
return m;
}
}
I would like to use Matrix object if possible to achieve that.There is also MainActivity and Thread class but I dont post them because thay are not relevant to this problem.
You can use ValueAnimator to animate the rectangles. On each
onAnimationUpdate(ValueAnimator animation)
you can invalidate or re-draw the line with the new position.
I found the solution I can just use Matrix.mapPoints, save them and just redraw line !

How to draw a bitmap from sdcard to custom ondraw method

I have a image on sdcard can anyone tell me how to draw the image from sdcard onto the custom ondraw method
I got the answer actually to draw a image from sdcard we have to intialize the image again in the function below
public void surfaceCreated(SurfaceHolder holder)
{
ball=BitmapFactory.createScaledBitmap(src,width,height,true);
bgr=BitmapFactory.decodeFile("/sdcard/1364275090569.jpg");
}
Actually this is my code and in this i am able to draw and customly move the image over background through the images placed in the resource folder but when i load a image instead from the sdcard and then implement it the application gives error
public class Preview extends Activity{
BallBounces ball;
public static int wd;
public static int ht;
public static String txt;
public static String path;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
Intent i=getIntent();
ball = new BallBounces(this);
setContentView(ball);
txt=i.getStringExtra("bpath");
path=i.getStringExtra("path");
wd= getWindowManager().getDefaultDisplay().getWidth();
ht=getWindowManager().getDefaultDisplay().getHeight();
}
}
class BallBounces extends SurfaceView implements SurfaceHolder.Callback {
private int mActivePointerId = INVALID_POINTER_ID;
private static final int INVALID_POINTER_ID = -1;
private ScaleGestureDetector mScaleDetector;
private float mScaleFactor = 1.f;
public float mPosX=0;
public float mPosY=0;
public float mLastTouchX;
public float mLastTouchY;
//For Fetching image
private Bitmap bmp;
private Drawable image;
private byte[] byteArray;
private ByteArrayBuffer baf = null;
int wid =Preview.wd, hght = Preview.ht;
//For Rotation
int direction = 0;
int degree = 0;
String twxt=Preview.txt;
String pth=Preview.path;
float wdth,hgt;
private float newX ;
public float newY ;
private float rotateX;
private float rotateY;
private float imgX;
private float imgY;
GameThread thread;
public int screenW; //Device's screen width.
public int screenH; //Devices's screen height.
public int ballX; //Ball x position.
public int ballY; //Ball y position.
int initialY ;
float dY; //Ball vertical speed.
int ballW;
int ballH;
int bgrW;
int bgrH;
int angle;
int bgrScroll;
int dBgrY; //Background scroll speed.
float acc;
Bitmap ball, bgr, bgrReverse;
boolean reverseBackroundFirst;
boolean ballFingerMove;
Bitmap d;
//Measure frames per second.
long now;
int framesCount=0;
int framesCountAvg=0;
long framesTimer=0;
Paint fpsPaint=new Paint();
//Frame speed
long timeNow;
long timePrev = 0;
long timePrevFrame = 0;
long timeDelta;
public BallBounces(Context context) {
super(context);
ball = BitmapFactory.decodeResource(getResources(), R.drawable.bubble);//load image
bgr = BitmapFactory.decodeResource(getResources(), R.drawable.grd); //Load a background.
bgrW = bgr.getWidth();
bgrH = bgr.getHeight();
ballW = ball.getWidth();
ballH = ball.getHeight();
image =new BitmapDrawable(context.getResources() , ball);
imgX=image.getIntrinsicWidth();
imgY=image.getIntrinsicHeight();
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
//Set thread
getHolder().addCallback(this);
setFocusable(true);
}
#Override
public void onSizeChanged (int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
//This event-method provides the real dimensions of this custom view.
screenW = w;
screenH = h;
System.out.println(w+" X "+h);
bgr = Bitmap.createScaledBitmap(bgr, w, h, true); //Scale background to fit the screen.
bgrW = bgr.getWidth();
bgrH = bgr.getHeight();
}
//***************************************
//************* TOUCH *****************
//***************************************
#Override
public synchronized boolean onTouchEvent(MotionEvent ev) {
mScaleDetector.onTouchEvent(ev);
final int action = ev.getActionMasked();
if (action == MotionEvent.ACTION_DOWN) {
System.out.println("DOWN");
final float x = ev.getX();
final float y = ev.getY();
mLastTouchX = x;
mLastTouchY = y;
System.out.println("DOWN-POSITION--"+x+" X "+y);
mActivePointerId = ev.getPointerId(0);
}
if (action == MotionEvent.ACTION_MOVE) {
System.out.println("MOVE");
final int pointerIndex = ev.findPointerIndex(mActivePointerId);
final float x = ev.getX(pointerIndex);
final float y = ev.getY(pointerIndex);
System.out.println("Moving points" +x+" X "+y);
if (!mScaleDetector.isInProgress()) {
final float dx = x - mLastTouchX;
final float dy=y-mLastTouchY;
mPosX += dx;
mPosY += dy;
newX=ev.getRawX();
newY=ev.getRawY();
System.out.println("Image Config" +newX+" X "+newY);
invalidate();
}
mLastTouchX = x;
mLastTouchY = y;
}
if (action == MotionEvent.ACTION_UP) {
System.out.println("UP");
mActivePointerId = INVALID_POINTER_ID;
}
if (action == MotionEvent.ACTION_CANCEL) {
System.out.println("CANCEL");
mActivePointerId = INVALID_POINTER_ID;
}
if (action == MotionEvent.ACTION_POINTER_UP) {
System.out.println("ACTN_POINTER_UP");
final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)
>> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
}
return true;
}
public BitmapDrawable writeOnDrawable(int drawableId, String text){
Rect bounds = new Rect();
Paint textPaint = new Paint();
textPaint.getTextBounds(twxt,0,twxt.length(),bounds);
float height = bounds.height();
float width = bounds.width();
wdth=width/2;
hgt=height/2;
Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId).copy(Bitmap.Config.ARGB_8888, true);
Paint paint = new Paint();
paint.setStyle(Style.FILL_AND_STROKE);
paint.setColor(Color.WHITE);
paint.setTextSize(15);
Canvas canvas = new Canvas(bm);
int xPos =(int) ((bm.getWidth()/2)-wdth);
int yPos = (int) ((bm.getHeight()/2)-hgt) ;
canvas.drawText(text, xPos-(wdth/8),yPos+hgt, paint);
return new BitmapDrawable(bm);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect fromRect1 = new Rect(0, 0, bgrW - bgrScroll, bgrH);
Rect toRect1 = new Rect(bgrScroll, 0, bgrW, bgrH);
Rect fromRect2 = new Rect(bgrW - bgrScroll, 0, bgrW, bgrH);
Rect toRect2 = new Rect(0, 0, bgrScroll, bgrH);
if (!reverseBackroundFirst) {
canvas.drawBitmap(bgr, fromRect1, toRect1, null);
}
else{
canvas.drawBitmap(bgr, fromRect2, toRect2, null);
}
if(mPosX<0)
{
mPosX=0;
}
if(mPosX>screenW-ballW)
{
mPosX=screenW-ballW;
}
if(mPosY>screenH-ballH)
{
mPosY=screenH-ballH;
}
if(mPosY<0)
{
mPosY=0;
}
canvas.drawBitmap(ball, mPosX, mPosY, null);
canvas.drawText(mPosX+ " X "+mPosY, 40, 70, fpsPaint);
canvas.drawText(ballW+ " X "+ballH, 40, 100, fpsPaint);
canvas.drawText(screenW+ " X "+screenH, 40, 150, fpsPaint);
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
public void surfaceCreated(SurfaceHolder holder) {
thread = new GameThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
thread.setRunning(false);
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
class GameThread extends Thread {
private SurfaceHolder surfaceHolder;
private BallBounces gameView;
private boolean run = false;
public GameThread(SurfaceHolder surfaceHolder, BallBounces gameView) {
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
public void setRunning(boolean run) {
this.run = run;
}
public SurfaceHolder getSurfaceHolder() {
return surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (run) {
c = null;
//limit frame rate to max 60fps
timeNow = System.currentTimeMillis();
timeDelta = timeNow - timePrevFrame;
if ( timeDelta < 16) {
try {
Thread.sleep(16 - timeDelta);
}
catch(InterruptedException e) {
}
}
timePrevFrame = System.currentTimeMillis();
try {
c = surfaceHolder.lockCanvas(null);
synchronized (surfaceHolder) {
//call methods to draw and process next fame
gameView.onDraw(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
#Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f));
invalidate();
return true;
}
}
}

Categories

Resources