How to draw a bitmap from sdcard to custom ondraw method - android

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;
}
}
}

Related

for loop in run() SurfaceView Runnable Android

Hi I am trying to make an application that draws lines based on points a user enters. A user may input as many points possible and the object will draw these lines based on their x and y values. I have looked into many drawing tutorials and found that using a SurfaceView Runnable is the best way to do any kind of drawing or animation in Android. I have run into a problem where the run() function does not draw with for loops. Is there a way to get loops working in run() or somewhere else? My code is below.
public class draw extends SurfaceView implements Runnable {
Thread thread = null;
updateDraw draw = null;
boolean canDraw = false;
Path path;
Bitmap bitmap;
SurfaceHolder surfaceHolder;
Context mContext;
Paint paint;
int bitmapX;
int bitmapY;
int viewWidth;
int viewHeight;
ArrayList<ArrayList<Double>> XY;
Paint blue_paintbrush_stroke
public draw(Context context, ArrayList<ArrayList<Double>> XY) {
super(context);
mContext = context;
surfaceHolder = getHolder();
paint = new Paint();
path = new Path();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
viewWidth = w;
viewHeight = h;
draw = new updateDraw(viewWidth, viewHeight);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inScaled = true;
options.inMutable = true;
bitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.bitmap, options);
setUpBitmap();
}
#Override
public void run() {
Canvas canvas;
prepPaintBrushes();
while (canDraw) {
//draw stuff
if (surfaceHolder.getSurface().isValid()) {
int x = draw.getX();
int y = draw.getY();
canvas = surfaceHolder.lockCanvas();
canvas.save();
canvas.drawBitmap(bitmap, bitmapX, bitmapY, paint);
canvas.drawPath(path, blue_paintbrush_stroke);
for(int i = 0; i < XY.size()-1; i++){
float aX = (XY.get(i).get(0), XY.get(i).get(1)).get(0) + bitmapX;
float aY = (XY.get(i).get(0), XY.get(i).get(1)).get(1) + bitmapY;
float bX = (XY.get(i+1).get(0), XY.get(i+1).get(0)).get(0) + bitmapX;
float bY = (XY.get(i+1).get(0), XY.get(i+1).get(1)).get(1) + bitmapY;
canvas.drawLine(aX, aY, bX, bY, blue_paintbrush_stroke);
}
path.rewind();
canvas.restore();
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
private void updateFrame(int newX, int newY) {
draw.update(newX, newY);
}
private void setUpBitmap() {
bitmapX = (int) Math.floor(
Math.random() * (viewWidth - backGround.getWidth()));
bitmapY = (int) Math.floor(
Math.random() * (viewHeight - backGround.getHeight()));
}
public void pause() {
canDraw = false;
while (true) {
try {
thread.join();
break;
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void resume() {
canDraw = true;
thread = new Thread(this);
thread.start();
}
private void prepPaintBrushes() {
blue_paintbrush_stroke = new Paint();
blue_paintbrush_stroke.setColor(Color.BLUE);
blue_paintbrush_stroke.setStyle(Paint.Style.STROKE);
blue_paintbrush_stroke.setStrokeWidth(10);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
setUpBitmap();
// Set coordinates of map.
updateFrame((int) x, (int) y);
invalidate();
break;
case MotionEvent.ACTION_MOVE:
// Updated coordinates for map.
updateFrame((int) x, (int) y);
invalidate();
break;
default:
// Do nothing.
}
return true;
}
}
Is better to override onDraw method and draw directly from it.
Create your custom class and extend from SurfaceView but is not
necessary to implement Runnable
Override onDraw(Canvas canvas)
remove run() method (use onDraw instead)
please make sure that you are calling the resume() method from the parent activity.
something like
#Override
protected void onResume(){
super.onResume();
customDraw.resume();
}

Draw paint over image not blank space using canvas

I am trying to draw line over image, it works fine but i faced some problem. The problem is I want to draw line over image only, not blank space. This the code here the sizechanged method i declare like this.
class DrawingPaint extends View implements View.OnTouchListener {
private Canvas mCanvas;
private Path mPath;
private Paint mPaint, mBitmapPaint;
public ArrayList<PathPoints> paths = new ArrayList<PathPoints>();
private ArrayList<PathPoints> undonePaths = new ArrayList<PathPoints>();
private Bitmap mBitmap;
private int color;
private int x, y;
private String textToDraw = null;
private boolean isTextModeOn = false;
int lastColor = 0xFFFF0000;
static final float STROKE_WIDTH = 15f;
Matrix m;
int imageHeight,imageWidth;
public DrawingPaint(Context context/*, int color*/) {
super(context);
//this.color = color;
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
/*mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(STROKE_WIDTH);
mPaint.setTextSize(30);
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
mCanvas = new Canvas();*/
}
public void colorChanged(int color) {
this.color = color;
mPaint.setColor(color);
}
public void setColor(int color) {
mPaint = new Paint();
this.color = color;
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(color);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(STROKE_WIDTH);
mPaint.setTextSize(30);
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
mCanvas = new Canvas();
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// mBitmap = AddReportItemActivity.mPhoto;
mBitmap = CustomGalleryHandler.getmInstance().getBitmapSend();
float xscale = (float) w / (float) mBitmap.getWidth();
float yscale = (float) h / (float) mBitmap.getHeight();
if (xscale > yscale) // make sure both dimensions fit (use the
// smaller scale)
xscale = yscale;
float newx = (float) w * xscale;
float newy = (float) h * xscale; // use the same scale for both
// dimensions
// if you want it centered on the display (black borders)
/*mBitmap = Bitmap.createScaledBitmap(mBitmap, this.getWidth(),
this.getHeight(), true);*/
// mCanvas = new Canvas(mBitmap);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(new File(PreferenceForCustomCamera.getInstance().getImagePathForGalleryFullScreen()).getAbsolutePath(), options);
imageHeight = options.outHeight;
imageWidth = options.outWidth;
m = new Matrix();
RectF drawableRect = new RectF(0, 0, imageWidth, imageHeight);
//onMeasure(imageWidth,imageHeight);
RectF viewRect = new RectF(0, 0, w, h);
m.setRectToRect(drawableRect, viewRect, Matrix.ScaleToFit.CENTER);
mBitmap = Bitmap.createBitmap(mBitmap,0,0,imageWidth,
imageHeight, m,true);
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
//setMeasuredDimension(this.getWidth(), this.getHeight());
//setMeasuredDimension(560, 100);even though give a ensured size, it can't //anyway.
}
#Override
protected void onDraw(Canvas canvas) {
float[] pts = {0, 0};
m.mapPoints(pts);
canvas.drawBitmap(mBitmap, pts[0], pts[1], mBitmapPaint);
// canvas.drawBitmap(mBitmap, 0, 0, mBitmapPaint);
for (PathPoints p : paths) {
mPaint.setColor(p.getColor());
Log.v("", "Color code : " + p.getColor());
if (p.isTextToDraw()) {
canvas.drawText(p.textToDraw, p.x, p.y, mPaint);
} else {
canvas.drawPath(p.getPath(), mPaint);
}
}
}
private float mX, mY;
private static final float TOUCH_TOLERANCE = 0;
private void touch_start(float x, float y) {
mPath.reset();
mPath.moveTo(x, y);
mX = x;
mY = y;
}
private void touch_move(float x, float y) {
float dx = Math.abs(x - mX);
float dy = Math.abs(y - mY);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
mPath.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2);
mX = x;
mY = y;
}
}
private void touch_up() {
mPath.lineTo(mX, mY);
// commit the path to our offscreen
mCanvas.drawPath(mPath, mPaint);
// kill this so we don't double draw
mPath = new Path();
paths.add(new PathPoints(mPath, color, false));
}
private void drawText(int x, int y) {
this.x = x;
this.y = y;
paths.add(new PathPoints(color, textToDraw, true, x, y));
// mCanvas.drawText(textToDraw, x, y, mPaint);
}
#Override
public boolean onTouch(View arg0, MotionEvent event) {
float x = event.getX();
float y = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isTextModeOn) {
touch_start(x, y);
invalidate();
}
break;
case MotionEvent.ACTION_MOVE:
if (!isTextModeOn) {
touch_move(x, y);
invalidate();
}
break;
case MotionEvent.ACTION_UP:
if (isTextModeOn) {
drawText((int) x, (int) y);
invalidate();
} else {
touch_up();
invalidate();
}
break;
}
return true;
}
public void onClickUndo() {
try {
if (paths.size() > 0) {
undonePaths.add(paths.remove(paths.size() - 1));
invalidate();
} else {
}
} catch (Exception e) {
e.toString();
}
}
public void onClickRedo() {
try {
if (undonePaths.size() > 0) {
paths.add(undonePaths.remove(undonePaths.size() - 1));
invalidate();
} else {
}
} catch (Exception e) {
e.toString();
}
}
/*class PathPoints {
private Path path;
// private Paint mPaint;
private int color;
private String textToDraw;
private boolean isTextToDraw;
private int x, y;
public PathPoints(Path path, int color, boolean isTextToDraw) {
this.path = path;
this.color = color;
this.isTextToDraw = isTextToDraw;
}
public PathPoints(int color, String textToDraw, boolean isTextToDraw,
int x, int y) {
this.color = color;
this.textToDraw = textToDraw;
this.isTextToDraw = isTextToDraw;
this.x = x;
this.y = y;
}
public Path getPath() {
return path;
}
public void setPath(Path path) {
this.path = path;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public String getTextToDraw() {
return textToDraw;
}
public void setTextToDraw(String textToDraw) {
this.textToDraw = textToDraw;
}
public boolean isTextToDraw() {
return isTextToDraw;
}
public void setTextToDraw(boolean isTextToDraw) {
this.isTextToDraw = isTextToDraw;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
}*/
}
Perhaps you'd want to extend your customized view from ImageView it self.
public class Line extends ImageView {
private static final String TAG = "Line";
private Paint lineDraw = null;
private int mStartX = 0;
private int mStartY = 0;
private int mEndX = 0;
private int mEndY = 0;
private float mStrokeWidth = 0;
public Line(Context context) {
super(context);
init_Paint();
}
public Line(Context context, AttributeSet attrs) {
super(context, attrs);
init_Attributes(context, attrs);
init_Paint();
}
public Line(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init_Attributes(context, attrs);
init_Paint();
}
private void init_Paint()
{
lineDraw = new Paint(Paint.ANTI_ALIAS_FLAG);
lineDraw.setStyle(Paint.Style.FILL);
lineDraw.setColor(Color.BLACK);
lineDraw.setStrokeWidth(mStrokeWidth);
}
private void init_Attributes(Context context, AttributeSet attrs)
{
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Line);
mStartX = a.getInteger(R.styleable.Line_startX, 0);
mStartY = a.getInteger(R.styleable.Line_startY, 0);
mEndX = a.getInteger(R.styleable.Line_endX, 0);
mEndY = a.getInteger(R.styleable.Line_endY, 0);
mStrokeWidth = a.getDimension(R.styleable.Line_strokeWidth, 0);
a.recycle();
}
public void setStartX(int startX)
{
this.mStartX = startX;
}
public void setStartY(int startY)
{
this.mStartY = startY;
}
public void setEndX(int endX)
{
this.mEndX = endX;
}
public void setEndY(int endY)
{
this.mEndY = endY;
}
public void setStrokeWidth(float strokeWidth)
{
this.mStrokeWidth = strokeWidth;
}
#Override
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
int width = MeasureSpec.getSize(widthMeasureSpec);
int height = MeasureSpec.getSize(heightMeasureSpec);
setMeasuredDimension(width, height);
}
#Override
public void onDraw(Canvas canvas)
{
//Call ImageView's default onDraw() method.
super.onDraw(canvas);
// You can instead use canvas.drawPath();
canvas.drawLine(mStartX, mStartY, mEndX, mEndY, lineDraw);
}
}
In your attr.xml add the following.
<resources>
<declare-styleable name="Line">
<attr name="startX" format="integer" />
<attr name="endX" format="integer" />
<attr name="startY" format="integer" />
<attr name="endY" format="integer" />
<attr name="strokeWidth" format="dimension" />
</declare-styleable>
</resources>
and you can use this like so.
<views.customview.Line
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:startX="5"
app:startY="5"
app:endX="500"
app:endY="500"
app:strokeWidth="15dp"
android:src="#drawable/add_bookmark"
/>

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 set ontouch listener for something drawn using canvas: Android

I have a custom view in which i am drawing one big circle and a small circle on the edge of this big circle.
I would like to move the small circle and so would like to have a ontouch listener only for the small circle.
Could some please tell me how to set the ontouch listener for only the small circle.
public class ThermoView extends View{
private ImageView mThermostatBgrd;
private ImageView mCurTempArrow;
private ImageView mSetPointIndicator;
public static final int THEMROSTAT_BACKGROUND = 0;
public static final int THEMROSTAT_CURR_TEMP = 1;
public static final int THEMROSTAT_SET_POINT = 2;
private float mViewCentreX;
private float mViewCentreY;
private float mThermostatRadius;
private Canvas mCanvas;
private Paint mPaint;
private Paint mPaintCurTemp;
private Paint mPaintSetTemp;
private Paint mPaintOverrideTemp;
private Paint mPaintCurTempIndicator;
private Boolean mManualOverride = false;
private double mManualOverrideAngle;
private int mMaxTemp = 420;
private int mMinTemp = 120;
private RectF mCurrTempBox;
private float mCurTempCircleX;
private float mCurTempCircleY;
private Matrix mMatrix;
public double getManualOverrideAngle() {
return mManualOverrideAngle;
}
public void setManualOverrideAngle(double mManualOverrideAngle) {
this.mManualOverrideAngle = mManualOverrideAngle;
}
public RectF getCurrTempBox() {
if (mCurrTempBox == null){
mCurrTempBox = new RectF();
}
return mCurrTempBox;
}
public void setCurrTempBox(RectF mCurrTempBox) {
this.mCurrTempBox = mCurrTempBox;
}
public Boolean getManualOverride() {
return mManualOverride;
}
public void setManualOverride(Boolean mManualOverride) {
this.mManualOverride = mManualOverride;
}
public ThermoView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Path smallCirle = new Path();
int viewWidth = getMeasuredWidth();
int viewHeight = getMeasuredHeight();
mViewCentreX = viewWidth/2;
mViewCentreY = viewHeight/2;
float paddingPercent = 0.2f;
int thermostatThickness = 20;
mThermostatRadius = (int) ((Math.min(mViewCentreX, mViewCentreY)*(1- paddingPercent)));
if (mPaint == null){
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
}
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(thermostatThickness);
mPaint.setColor(0xffff0000);
Path arcPath = new Path();
RectF container = new RectF();
container.set(mViewCentreX - mThermostatRadius, mViewCentreY - mThermostatRadius,
mViewCentreX + mThermostatRadius, mViewCentreY + mThermostatRadius);
arcPath.addArc(container, 120, 300);
canvas.drawPath(arcPath, mPaint);
int dummyCurTemp = 200;
if (mPaintCurTemp == null){
mPaintCurTemp = new Paint(Paint.ANTI_ALIAS_FLAG);
}
mPaintCurTemp.setTextAlign(Align.CENTER);
mPaintCurTemp.setTextSize(100);
canvas.drawText(String.valueOf(dummyCurTemp), mViewCentreX, mViewCentreY, mPaintCurTemp);
if (this.mManualOverride == false){
double angle = (360-120-(300/(mMaxTemp - mMinTemp))*(dummyCurTemp-mMinTemp))*(Math.PI/180);
this.mCurTempCircleX = (float) (mViewCentreX + mThermostatRadius*(Math.cos(angle)));
this.mCurTempCircleY = (float) (mViewCentreY - mThermostatRadius*(Math.sin(angle)));
if (mCurrTempBox == null){
mCurrTempBox = new RectF();
}
if (mPaintCurTempIndicator == null){
mPaintCurTempIndicator = new Paint(Paint.ANTI_ALIAS_FLAG);
}
mPaintCurTempIndicator.setStyle(Paint.Style.STROKE);
mPaintCurTempIndicator.setStrokeWidth(thermostatThickness/2);
mPaintCurTempIndicator.setColor(Color.GREEN);
mCurrTempBox.set(mCurTempCircleX-50, mCurTempCircleY-50, mCurTempCircleX+50, mCurTempCircleY+50);
smallCirle.addCircle(mCurTempCircleX, mCurTempCircleY, 50, Direction.CW);
canvas.drawPath(smallCirle, mPaintCurTempIndicator);
}else{
if (mCurrTempBox == null){
mCurrTempBox = new RectF();
}
if (mPaintCurTempIndicator == null){
mPaintCurTempIndicator = new Paint(Paint.ANTI_ALIAS_FLAG);
}
if (mMatrix == null){
mMatrix = new Matrix();
}
//mMatrix.reset();
mMatrix.postRotate((float) (mManualOverrideAngle), mViewCentreX,mViewCentreY);
//mMatrix.postTranslate(mViewCentreX, mViewCentreY);
mPaintCurTempIndicator.setStyle(Paint.Style.STROKE);
mPaintCurTempIndicator.setStrokeWidth(thermostatThickness/2);
mPaintCurTempIndicator.setColor(Color.GREEN);
canvas.concat(mMatrix);
smallCirle.addCircle(mCurTempCircleX, mCurTempCircleY, 50, Direction.CW);
canvas.drawPath(smallCirle, mPaintCurTempIndicator);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mInitialX = event.getX();
mInitialY = event.getY();
RectF touchedAt = new RectF(mInitialX-10, mInitialY-10, mInitialX+10, mInitialY+10);
RectF indicatorAt = mThermoStatView.getCurrTempBox();
if (RectF.intersects(indicatorAt, touchedAt)){
this.isIndicatorSelected = true;
mThermoStatView.setManualOverride(true);
}
break;
case MotionEvent.ACTION_MOVE:
if (this.isIndicatorSelected == true){
float angle = (float) (180*Math.atan2(event.getY() - mThermostatHeight/2, event.getX() - mThermostatWidth/2) / Math.PI);
mThermoStatView.setManualOverrideAngle(angle);
mThermoStatView.invalidate();
//mThermoStatView.requestLayout();
}
break;
case MotionEvent.ACTION_UP:
if (this.isIndicatorSelected == true){
this.isIndicatorSelected = false;
}
break;
}
return true;
}
}
try this (this is a little modified version of MyView i already posted as an answer for your previous question):
public class MyView extends View {
private final static String TAG = "Main.MyView";
private static final float CX = 0;
private static final float CY = 0;
private static final float RADIUS = 20;
private static final float BIGRADIUS = 50;
private static final int NORMAL_COLOR = 0xffffffff;
private static final int PRESSED_COLOR = 0xffff0000;
private Paint mPaint;
private Path mSmallCircle;
private Path mCircle;
private Matrix mMatrix;
private float mAngle;
private int mSmallCircleColor;
public MyView(Context context) {
super(context);
mPaint = new Paint();
mSmallCircle = new Path();
mSmallCircle.addCircle(BIGRADIUS + RADIUS + CX, CY, RADIUS, Direction.CW);
mSmallCircleColor = NORMAL_COLOR;
mCircle = new Path();
mCircle.addCircle(0, 0, BIGRADIUS, Direction.CW);
mMatrix = new Matrix();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction();
if (action == MotionEvent.ACTION_UP) {
mSmallCircleColor = NORMAL_COLOR;
invalidate();
return false;
}
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
float r = 0;
if (action == MotionEvent.ACTION_DOWN) {
float[] pts = {
BIGRADIUS + RADIUS + CX, CY
};
mMatrix.mapPoints(pts);
r = (float) Math.hypot(event.getX() - pts[0], event.getY() - pts[1]);
}
if (r < RADIUS) {
mSmallCircleColor = PRESSED_COLOR;
mAngle = (float) (180 * Math.atan2(event.getY() - h2, event.getX() - w2) / Math.PI);
invalidate();
return true;
}
return false;
}
#Override
protected void onDraw(Canvas canvas) {
float w2 = getWidth() / 2f;
float h2 = getHeight() / 2f;
mMatrix.reset();
mMatrix.postRotate(mAngle);
mMatrix.postTranslate(w2, h2);
canvas.concat(mMatrix);
mPaint.setColor(0x88ffffff);
canvas.drawPath(mCircle, mPaint);
mPaint.setColor(mSmallCircleColor);
canvas.drawPath(mSmallCircle, mPaint);
}
}
You can get the rectangle of your touch point and the rectangle(position) of your inner circle and check if they cross over with the Intersects method.
http://docs.oracle.com/javase/7/docs/api/java/awt/Rectangle.html#intersects(java.awt.Rectangle)
Your canvas onTouchListener can do whatever it needs to do if the touchpoint intersect your circle.
e.g:
// Create a rectangle from the point of touch
Rect touchpoint = new Rect(x,y,10,10);
// Create a rectangle from the postion of the circle.
Rect myCircle=new Rect(10,10,20,20);
if (Rect.intersects(myCircle,touchpoint)){
Log.d("The circle was touched");
}

How to center align center a Bitmap?

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");
}
}
}

Categories

Resources