Related
I have the current code which draw a bounding box around a user's face on a live camera preview.
I am also trying to draw the position of facial landmarks on the live camera preview. It draws them but not at the right location due to not having the scale value
I found this code online but am struggling to compute this scale value as it is a live camera preview and not a bitmap image
Example code found online
double scale = Math.min( viewWidth / imageWidth, viewHeight / imageHeight );
for (Landmark landmark : face.getLandmarks()) {
int cx = (int) (landmark.getPosition().x * scale);
int cy = (int) (landmark.getPosition().y * scale);
canvas.drawCircle(cx, cy, 10, paint);
}
My Function
#Override
public void draw(Canvas canvas) {
Face face = mFace;
if (face == null) {
return;
}
// Draws a circle at the position of the detected face, with the face's track id below.
float x = translateX(face.getPosition().x + face.getWidth() / 2);
float y = translateY(face.getPosition().y + face.getHeight() / 2);
canvas.drawCircle(x, y, FACE_POSITION_RADIUS, mFacePositionPaint);
// Draws a bounding box around the face.
float xOffset = scaleX(face.getWidth() / 2.0f);
float yOffset = scaleY(face.getHeight() / 2.0f);
float left = x - xOffset;
float top = y - yOffset;
float right = x + xOffset;
float bottom = y + yOffset;
canvas.drawRect(left, top, right, bottom, mBoxPaint);
Paint paint = new Paint();
paint.setColor( Color.GREEN );
paint.setStyle( Paint.Style.STROKE );
paint.setStrokeWidth( 5 );
for ( Landmark landmark : face.getLandmarks() ) {
int cx = (int) ( landmark.getPosition().x);
int cy = (int) ( landmark.getPosition().y);
canvas.drawCircle( cx, cy, 10, paint );
}
}
Solved via the following, but not wholly accurate
if ((contains(face.getLandmarks(), 11) != 99)
&& (contains(face.getLandmarks(), 5) != 99)
&& (contains(face.getLandmarks(), 6) != 99)
) {
Log.i(TAG, "draw: Mouth Open >> found all the points");
/**
* for bottom mouth
*/
int cBottomMouthX;
int cBottomMouthY;
cBottomMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 0)).getPosition().x);
cBottomMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 0)).getPosition().y);
Log.i(TAG, "draw: Condition Bottom mouth >> cBottomMouthX >> " + cBottomMouthX + " cBottomMouthY >> " + cBottomMouthY);
canvas.drawCircle(cBottomMouthX, cBottomMouthY, 10, paint);
/**
* for left mouth
*/
int cLeftMouthX;
int cLeftMouthY;
cLeftMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().x);
cLeftMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().y);
Log.i(TAG, "draw: Condition LEft mouth >> cLeftMouthX >> " + cLeftMouthX + " cLeftMouthY >> " + cLeftMouthY);
cLeftMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().x);
cLeftMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 5)).getPosition().y);
canvas.drawCircle(cLeftMouthX, cLeftMouthY, 10, paint);
/**
* for Right mouth
*/
int cRightMouthX;
int cRightMouthY;
cRightMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().x);
cRightMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().y);
Log.i(TAG, "draw: Condition Right mouth >> cRightMouthX >> " + cRightMouthX + " cRightMouthY >> " + cRightMouthY);
cRightMouthX = (int) translateX(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().x);
cRightMouthY = (int) translateY(face.getLandmarks().get(contains(face.getLandmarks(), 11)).getPosition().y);
canvas.drawCircle(cRightMouthX, cRightMouthY, 10, paint);
float centerPointX = (cLeftMouthX + cRightMouthX) / 2;
float centerPointY = ((cLeftMouthY + cRightMouthY) / 2) - 20;
canvas.drawCircle(centerPointX, centerPointY, 10, paint);
float differenceX = centerPointX - cBottomMouthX;
float differenceY = centerPointY - cBottomMouthY;
Log.i(TAG, "draw: difference X >> " + differenceX + " Y >> " + differenceY);
if (differenceY < (-60)) {
Log.i(TAG, "draw: difference - Mouth is OPENED ");
} else {
Log.i(TAG, "draw: difference - Mouth is CLOSED ");
}
}
}
private int contains (List < Landmark > list,int name){
for (int i = 0; i < list.size(); i++) {
if (list.get(i).getType() == name) {
return i;
}
}
return 99;
}
I am trying to make real time application based on canvas writing here multiple device will be connected with this application if i write something on canvas it should reflect on other devices which are connected with this app here my issue is i am able to write on canvas and its also writes smooth but when it comes to receiving end its getting disjoint segment not clear path visible on canvas.
I am using thread using moveTo() and quadTo()to and receiving points from server
here images for reference
Source writing
Receiving end
Here is my code which i am trying
onDraw method
#Override
protected void onDraw(final Canvas canvas) {
normal_canvas_draw=true;
bckimage = getBackground();
String col = "#333333".substring(1);
col = col.toLowerCase();
col = "#ff" + col;
mc.setcanvas(canvas);
paint1.setAntiAlias(true);
paint1.setDither(true);
paint1.setStyle(Paint.Style.STROKE);
paint1.setStrokeJoin(Paint.Join.ROUND);
paint1.setStrokeCap(Paint.Cap.ROUND);
paint1.setPathEffect(new CornerPathEffect(30) ); // set the path effect when they join.
paint.setDither(true); // set the dither to true
paint.setStyle(Paint.Style.STROKE); // set to STOKE
paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want
paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too
paint.setPathEffect(new CornerPathEffect(30) ); // set the path effect when they join.
paint.setAntiAlias(true);
mCanvas.drawPath(path, paint);
mCanvas.drawPath(path1, paint1);
/*
for(Path p :paths)
{
mCanvas.drawPath(p, paint1);
}*/
//mCanvas.drawPath(path1, paint1);
//s = paths.size();
s = type.size();
Log.d("BLOCK", s + " , " + leftval.size());
int j = 0, k = 0;
canvas.drawBitmap(img, 0, 0, null);
canvas.drawText(mc.getDisplaymsg(), mCanvas.getWidth()-200, 25, painttext);
r = new Rect(10, 600, 100, 650);
}
onTouchEvent
#Override
public boolean onTouchEvent(MotionEvent event) {
if (mIsScrolling)
sv.requestDisallowInterceptTouchEvent(false);
else
sv.requestDisallowInterceptTouchEvent(true);
float eventX = event.getX();
float eventY = event.getY();
boolean touchcaptured = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.reset();
// path.moveTo(eventX, eventY);
boolean l = r.contains((int) event.getX(), (int) event.getY());
if (markerMode)
{
isEraserDown="false";
isPenDown="false";
isMarkerDown="true";
path.moveTo(eventX,eventY);
startX=eventX/scalefactor;
startY=eventY/scalefactor;
mX=eventX;
mY=eventY;
MainActivity.super.loadUrl("javascript:eraserfunction(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}
else if (eraseMode)
{
isEraserDown="true";
isPenDown="false";
isMarkerDown="false";
System.out.println("--Eraserfromtouch");
path.moveTo(eventX,eventY);
startX=eventX/scalefactor;
startY=eventY/scalefactor;
mX=eventX;
mY=eventY;
MainActivity.super.loadUrl("javascript:eraserfunction(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}
else if (blockerase) {
// left=(int) event.getX();
// right=left+1;
// top=(int) event.getY();
// bottom=top+1;
rx = (int) event.getX();
ry = (int) event.getY();
}
/*------------------- Pendown when we touch on mobile screen------*/
else if (penmode) {
isPenDown="true";
isEraserDown="false";
isMarkerDown="false";
System.out.println("---pen-down---"+eventX+","+eventY);
int historySize = event.getHistorySize();
if(isPenDown=="true")
{
path.moveTo(eventX,eventY);
mX = eventX;
mY = eventY;
startX=eventX/scalefactor;
startY=eventY/scalefactor;
mc.setXY(eventX / scalefactor, eventY / scalefactor);
MainActivity.super.loadUrl("javascript:penDown(0,0,'pen')");
}
else
{
}
// System.out.println(" Lcal x"+eventX+" y"+eventY+" x2"+eventX+" y2"+eventY);
} else if (rectanglemode) {
rx = (int) event.getX();
ry = (int) event.getY();
} else if (linemode) {
rx = (int) event.getX();
ry = (int) event.getY();
} else if (circlemode) {
cx = (int) event.getX();
cy = (int) event.getY();
MainActivity.super.loadUrl("javascript:circleDown(" + cx / scalefactor + "," + cy / scalefactor + ")");
} else if (textmode) {
cx = (int) event.getX();
cy = (int) event.getY();
//MainActivity.super.loadUrl("javascript:drawtext(" +cx + "," + cy+","+"Hello World"+")");
}
//invalidate();
break;
case MotionEvent.ACTION_MOVE:
if (markerMode) {
if (isMarkerDown.equals("true")) {
System.out.println("Marker Move");
Log.d("MARKER", "Hi im marker");
String col = mc.getdrawAttributes().substring(1);
col = col.toLowerCase();
col = "#ff" + col;
int coll = Color.parseColor(col);
paint.setColor(coll);
paint.setAlpha(10);
paint.setStrokeWidth(20);
if (bckimage == null) {
} else {
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
}
MainActivity.super.loadUrl("javascript:marker1(" + eventX / scalefactor + "," + eventY / scalefactor + ")");
}
else{
}
path.quadTo(mX,mY,(mX+event.getX())/2,(mY+event.getY())/2);
mX=event.getX();
mY=event.getY();
}
else if (eraseMode)
{
if(isEraserDown=="true")
{
System.out.println("--Eraserfromtouch--MOVE");
System.out.println("Marker Move");
Log.d("Eraser", "Im eraser");
String thh = mc.getdrawAttributes1();
float f = Float.parseFloat(thh);
paint.setStrokeWidth(f);
if (bckimage == null) {
paint.setColor(Color.WHITE); //Toast.makeText(getContext(),"ERASE",Toast.LENGTH_LONG).show();
} else {
// setLayerType(View.LAYER_TYPE_SOFTWARE, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
MainActivity.super.loadUrl("javascript:eraserfunction1(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}
path.quadTo(mX,mY,(mX+event.getX())/2,(mY+event.getY())/2);
mX=event.getX();
mY=event.getY();
}
else
{
}
}
else if (blockerase) {
qx = (int) event.getX();
qy = (int) event.getY();
}
/*------------------Pen move on the screen following by finger-------------*/
else if (penmode) {
if(isPenDown=="true")
{
String thh1 = mc.getdrawAttributes1();
float width = Float.parseFloat(thh1);
paint.setStrokeWidth(width);
paint.setColor(color);
paint.setDither(true); // set the dither to true
paint.setStyle(Paint.Style.STROKE); // set to STOKE
paint.setStrokeJoin(Paint.Join.ROUND); // set the join to round you want
paint.setStrokeCap(Paint.Cap.ROUND); // set the paint cap to round too
paint.setPathEffect(new CornerPathEffect(30) ); // set the path effect when they join.
paint.setAntiAlias(true);
// Line current = lines.get(lines.size() - 1);
System.out.println("---penmove---");
float dx = Math.abs((int) event.getX() - mX);
float dy = Math.abs((int) event.getY() - mY);
System.out.println("--Value of dx-dy-"+dx+"-"+dy);
if (dx >= 4 || dy >= 4) {
// setXY function set X and Y values to be used in JS File
mc.setXY((int) event.getX() / scalefactor, (int) event.getY() / scalefactor);
MainActivity.super.loadUrl("javascript:penMove(0,0,'pen')");
path.quadTo(mX,mY,(mX+event.getX())/2,(mY+event.getY())/2);
mX=event.getX();
mY=event.getY();
}
else
{
}
}
} else if (rectanglemode) {
qx = (int) event.getX();
qy = (int) event.getY();
} else if (linemode) {
qx = (int) event.getX();
qy = (int) event.getY();
} else if (circlemode) {
//MainActivity.super.loadUrl("javascript:circleDown(" + eventX + "," + eventY + ")");
}
break;
case MotionEvent.ACTION_UP:
boolean ll = r.contains((int) event.getX(), (int) event.getY());
if (markerMode)
MainActivity.super.loadUrl("javascript:marker12()");
else if (eraseMode) {
MainActivity.super.loadUrl("javascript:penUp()");
isEraserDown="false";
isMarkerDown="false";
System.out.println("--Eraserfromtouch---actionup");
path.lineTo(mX,mY);
mCanvas.drawPath(path,paint);
path= new Path();
// path1= new Path();
paths.add(path);
// MainActivity.super.loadUrl("javascript:eraserfunction1(" + eventX / scalefactor + "," + eventY / scalefactor + "," + mc.getdrawAttributes1() + ")");
}else if (blockerase) {
qx = (int) event.getX();
qy = (int) event.getY();
MainActivity.super.loadUrl("javascript:bigeraserfunction1(" + rx / scalefactor + "," + ry / scalefactor + "," + qx / scalefactor + "," + qy / scalefactor + ")");
}
/*---------------------Pen up for writing on canvas------------------*/
else if (penmode) {
MainActivity.super.loadUrl("javascript:penUp()");
isPenDown="false";
System.out.println("---pen--up---");
path.lineTo(mX,mY);
mCanvas.drawPath(path,paint);
path= new Path();
// path1= new Path();
paths.add(path);
} else if (rectanglemode) {
qx = (int) event.getX();
qy = (int) event.getY();
MainActivity.super.loadUrl("javascript:rectangle(" + rx / scalefactor + "," + ry / scalefactor + "," + qx / scalefactor + "," + qy / scalefactor + ",'" + Prefs.getString(Elucido_APP_CONSTANTS.shared_user_name, "") + "')");
} else if (linemode) {
qx = (int) event.getX();
qy = (int) event.getY();
MainActivity.super.loadUrl("javascript:line(" + rx / scalefactor + "," + ry / scalefactor + "," + qx / scalefactor + "," + qy / scalefactor + ",'" + Prefs.getString(Elucido_APP_CONSTANTS.shared_user_name, "") + "')");
} else if (circlemode) {
c1x = (int) event.getX();
c1y = (int) event.getY();
MainActivity.super.loadUrl("javascript:circleup(" + c1x / scalefactor + "," + c1y / scalefactor + ")");
} else if (textmode) {
cx = (int) event.getX();
cy = (int) event.getY();
opentextDialog((int) (cx / scalefactor), (int) (cy / scalefactor));
}
break;
default:
return false;
}
invalidate();
return true;
}
draw() Method is in thread for continuously receiving points path
public boolean draw() {
//------------------------ Starting Reciving points--------------------------
String s1 = mc.getdrawlinesdual();
words1 = s1.split(",");
float xx11 = Float.parseFloat(words1[0].replaceAll("[\\(\\)\\[\\]\\{\\}]", "")) * scalefactor;
float yy11 = Float.parseFloat(words1[1]) * scalefactor;
float xx21 = Float.parseFloat(words1[2]) * scalefactor;
float yy21 = Float.parseFloat(words1[3].replaceAll("[\\(\\)\\[\\]\\{\\}]", "")) * scalefactor;
System.out.println("---------x" + xx11 + " y" + yy11 + " x2" + xx21 + " y2" + yy21);
if (a1 == 0)
{
System.out.println("----paint from pen--a1 == 0");
Log.d("TAGG", "INTEGER value " + mc.getdrawAttributes());
if (mc.getdrawTypeAttributes().toString().compareTo("eraser") == 0) {
System.out.println("Eraser--a1==0---ifllop");
Log.d("Eraser", "Im eraser");
String thh = mc.getdrawThAttributes();
float f = Float.parseFloat(thh);
paint1.setStrokeWidth(f);
if (bckimage == null) {
paint1.setColor(Color.WHITE); //Toast.makeText(getContext(),"ERASE",Toast.LENGTH_LONG).show();
} else {
paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
}
} else {
System.out.println("Eraser--a1==0---elsellop");
String th = mc.getdrawThAttributes();
float f = Float.parseFloat(th);
paint1.setColor(color);
}
String t = mc.getdrawTypeAttributes().trim();
if ((t.compareTo("marker") == 0)) {
Log.d("MARKER", "Hi im marker");
String col = mc.getdrawColorAttributes().substring(1);
col = col.toLowerCase();
col = "#ff" + col.trim();
int coll = Color.parseColor(col);
paint1.setColor(coll);
paint1.setAlpha(10);
paint1.setStrokeWidth(20);
if (bckimage == null) {
} else {
paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
}
}
path1.moveTo(xx11, yy11);
// path1.lineTo(xx21, yy21);
path1.quadTo(xx11, yy11, (xx11 + xx21) / 2, (yy11 + yy21) / 2);
// invalidate();
// type.add("Line");
path1 = new Path();
a1 = xx11;
b1 = yy11;
c1 = xx21;
d1 = yy21;
}
else if (a1 == xx11)
{
//il.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
System.out.println("----paint from pen--a1 == xx11");
MainActivity.this.blankwhiteboard = 1;
path1.moveTo(c1, d1);
// float x = c+(xx2-c)/2;
// float y= d+(yy2-d)/2;
path1.quadTo(c1, d1, (c1 + xx21) / 2, (d1 + yy21) / 2);
// path1.lineTo(xx21, yy21);
invalidate();
c1 = xx21;
d1 = yy21;
}
else
{
type.add("Line");
System.out.println("----paint from pen");
path1 = new Path();
paint1 = new Paint();
paint1.setAntiAlias(true);
String th = mc.getdrawThAttributes();
paint1.setStyle(Paint.Style.STROKE);
paint1.setStrokeJoin(Paint.Join.ROUND);
paint1.setStrokeCap(Paint.Cap.ROUND);
paint1.setPathEffect(new CornerPathEffect(30));
paint1.setDither(true);
String t = mc.getdrawTypeAttributes();
if (mc.getdrawTypeAttributes().toString().compareTo("eraser") == 0)
{
System.out.println("Eraser--a1!=0---ifllop");
System.out.println("inside cuming erase");
//float val = 20;
String thh = mc.getdrawThAttributes();
float f = Float.parseFloat(thh);
paint1.setStrokeWidth(f);
Log.d("Eraser", "Im in eraser");
if (bckimage == null) {
paint1.setColor(Color.WHITE); //Toast.makeText(getContext(),"ERASE",Toast.LENGTH_LONG).show();
} else
paint1.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
invalidate();
}
else
{
System.out.println("Eraser--a1!=0---elsellop");
float f = Float.parseFloat(th);
paint1.setStrokeWidth(f);
String col = mc.getdrawColorAttributes().substring(1);
col = col.toLowerCase();
col = "#ff" + col;
int coll = Color.parseColor(col);
paint1.setColor(coll);
if ((t.compareTo("marker") == 0))
{
Log.d("MARKER", "Hi im marker");
paint1.setAlpha(10);
paint1.setStrokeWidth(20);
if (bckimage == null)
{
}
else
{
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.XOR));
}
paint1.setStrokeWidth(f);
mc.getTelephoneNumber(Integer.toHexString(color).substring(2));
MainActivity.super.loadUrl("javascript:colorSelectListener('')");
}
else
{
}
}
path1.moveTo(xx11, yy11);
// path1.lineTo(xx21,yy21);
path1.quadTo(xx11, yy11, (xx11 + xx21) / 2, (yy11 + yy21) / 2);
a1 = xx11;
b1 = yy11;
c1 = xx21;
d1 = yy21;
}
invalidate();
//------------------------ End Reciving points--------------------------
}
I have a custom indicator view that I have created.
as you can see on the first picture everything is drawn correctly,
but sometimes when i close the app and start it again it is not drawn correctly (the second picture)
trying to figure out what could be the reason for this.
maybe some caching ?
this is my onDraw Code:
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawUnselected(canvas, mUnselectedPaint);
drawSelected(canvas, mSelectedPaint);
drawDone(canvas, mDonePaint);
}
private void drawDone(Canvas canvas, Paint mDonePaint) {
for (Integer page : mDonePages) {
canvas.drawBitmap(mDoneItemBitmap, dotCenterX[page], mDotTopY, mDonePaint);
}
}
private void drawSelected(Canvas canvas, Paint mSelectedPaint) {
float dist = ((mSelectedPaint.descent() + mSelectedPaint.ascent()) / 2);
for (Integer page : mSelectedPages) {
canvas.drawBitmap(mSelectedItemBitmap, dotCenterX[page], mDotTopY, mSelectedPaint);
canvas.drawText("" + (page + 1), dotCenterX[page] + mDotRadius + dist, mDotTopY + mDotRadius - dist, mSelectedPaint);
}
}
private void drawUnselected(Canvas canvas, Paint mUnselectedPaint) {
int paddingTop = getPaddingTop();
for (int page = 0; page < mDotsNumber; page++) {
Paint test = new Paint();
test.setColor(Color.BLACK);
test.setStrokeWidth(30);
canvas.drawBitmap(mUnSelectedItemBitmap, dotCenterX[page], mDotTopY, mUnselectedPaint);
float dist = ((mNumbersPaint.descent() + mNumbersPaint.ascent()) / 2);
canvas.drawText("" + (page + 1), dotCenterX[page] + mDotRadius + dist, mDotTopY + mDotRadius - dist, mNumbersPaint);
if (page == mDotsNumber - 1) {
//last page
} else {
canvas.drawLine(dotCenterX[page] + mDotDiameter - 2, mDotRadius + paddingTop, dotCenterX[page] + mDotDiameter + mDotGap + 1, mDotRadius + paddingTop, mUnselectedPaint);
}
}
}
I have a game board with 5x5 squares made of canvas drawrect:
protected void onDraw(Canvas canvas) {
for (int rowNo = 0; rowNo < nSquares; rowNo++) {
paint.setColor(((rowNo & 1) == 0) ? colorA : colorB);
for (int colNo = 0; colNo < nSquares; colNo++) {
int left = colNo * squareWidth;
int top = rowNo * squareWidth;
Rect areaRect = new Rect(left, top, left + squareWidth, top + squareWidth);
canvas.drawRect(areaRect, paint);
paint.setColor((paint.getColor() == colorA) ? colorB : colorA);
paint.setTextSize((float)(squareWidth*0.8));
RectF bounds = new RectF(areaRect);
String letter = "A";
bounds.right = paint.measureText(letter, 0, letter.length());
bounds.bottom = paint.descent() - paint.ascent();
bounds.left += (areaRect.width() - bounds.right) / 2.0f;
bounds.top += (areaRect.height() - bounds.bottom) / 2.0f;
canvas.drawText(letter, bounds.left, bounds.top - paint.ascent(), paint);
}
}
I want to track touch input to get the squares the user are touching..
My attempt was
public boolean onTouchEvent(MotionEvent event){
int action = MotionEventCompat.getActionMasked(event);
int x = (int)event.getX();
int y = (int)event.getY();
Log.i(DEBUG_TAG, "Position: (" + x + ", " + y + ")");
int squareTouched = gameBoard.getSquare(x,y);
}
where getSquare is
public int getSquare(int x, int y) {
int row = 0;
int col = 0;
for(int rowNo = 1; rowNo <= nSquares; rowNo++) {
Log.i("Row", "Width: " + squareWidth + " rowNo: " + rowNo + " rowNo*squareW: " + rowNo*squareWidth + " y: " + y);
if(rowNo*squareWidth > y)
{
row = rowNo;
break;
}
}
for (int colNo = 1; colNo <= nSquares; colNo++) {
if(colNo*squareWidth > x)
{
col = colNo;
break;
}
}
Log.i(DEBUG_TAG, "Row: " + row + " Col: " + col);
return (row-1)*nSquares + col;
}
The problem is that the onTouchEvent getX and getY are referring to the screen 0,0, but when I draw the squares 0,0,0,0 is referring to the view origin? Am I right?
How can I get the input position relative to the game board view?
Could it be a solution to get the view position in the screen and add/subtract this to the tochEvent x- and y position?
I assume that the onDraw() and getSquare() belong to GameBoardView and onTouchEvent() to its immediate parent. If so then the onTouchEvent() should be like this
public boolean onTouchEvent(MotionEvent event){
int action = MotionEventCompat.getActionMasked(event);
int x = (int)event.getX() - gameBoard.getX();
int y = (int)event.getY() - gameBoard.getY();
Log.i(DEBUG_TAG, "Position: (" + x + ", " + y + ")");
int squareTouched = gameBoard.getSquare(x, y);
}
In a View x and y in both onDraw() and onTouchEvent() is relative to the View itself (Except when the View is scrolled). Since in your case onTouchEvent() belongs to parent and onDraw() to child, I used View.getX() and getY() to translate the coordinates. View.getX() returns the x position plus translationX of the View relative to its parent.
I could not get the gameBoard().getX/Y() to return the correct values. My guess is that the action bar is excluded?
I now use getLocationOnScreen
#Override
public boolean onTouchEvent(MotionEvent event){
int action = MotionEventCompat.getActionMasked(event);
int boardLocation[] = new int[2];
gameBoard.getLocationOnScreen(boardLocation);
int touchX = (int)event.getX();
int touchY = (int)event.getY();
int x = touchX - boardLocation[0];
int y = touchY - boardLocation[1];
int squareTouched = gameBoard.getSquare(x,y);
}
Which solved my issue..
I have created a circle in custom view. I want to add 6 colors to it based on a condition. The 6 regions will keep changing based on the condition. For eg, each region can vary from 30 degrees to 90 degrees to 120 degrees.
My question is
1) How do I add 6 colors to the circle. Please note that I cannot divide the circle into 6 equal regions, thats not how it is supposed to be.
2) How do I assign the starting and ending points of the regions. For example if I want to add green color from 45degrees to 90 degrees. How do I do this?
The end product is supposed to look as below
package com.example.submission_customclock;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.os.CountDownTimer;
import android.os.Handler;
import android.text.format.Time;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.RemoteViews.RemoteView;
import java.util.TimeZone;
/**
* This widget display an analogic clock with two hands for hours and
* minutes.
*
* #attr ref android.R.styleable#AnalogClock_dial
* #attr ref android.R.styleable#AnalogClock_hand_hour
* #attr ref android.R.styleable#AnalogClock_hand_minute
*/
#RemoteView
public class AnalogClock extends View {
private Time mCalendar;
private static final String DEBUGTAG = "FA";
private Drawable mHourHand;
private Drawable mMinuteHand;
private Drawable mSecondHand;
private Drawable mDial;
private Drawable mDial_frame;
private Drawable mDial_center;
private int mDialWidth;
private int mDialHeight;
private boolean mAttached;
private final Handler mHandler = new Handler();
private float mMinutes;
private float mHour;
private boolean mChanged;
public AnalogClock(Context context) {
this(context, null);
}
public AnalogClock(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
Context mContext;
public AnalogClock(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
Resources r = context.getResources();
mContext=context;
Log.d(AnalogClock.DEBUGTAG,"Analog clock started");
mDial = r.getDrawable(R.drawable.clock4);
mDial_frame = r.getDrawable(R.drawable.clock_frame);
mDial_center = r.getDrawable(R.drawable.clock_dot);
mHourHand = r.getDrawable(R.drawable.hour_hand);
mMinuteHand = r.getDrawable(R.drawable.minute_hand);
mSecondHand = r.getDrawable(R.drawable.second_hand);
mCalendar = new Time();
mDialWidth = mDial.getIntrinsicWidth();
mDialHeight = mDial.getIntrinsicHeight();
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (!mAttached) {
mAttached = true;
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_TIME_TICK);
filter.addAction(Intent.ACTION_TIME_CHANGED);
filter.addAction(Intent.ACTION_TIMEZONE_CHANGED);
getContext().registerReceiver(mIntentReceiver, filter, null, mHandler);
}
// NOTE: It's safe to do these after registering the receiver since the receiver always runs
// in the main thread, therefore the receiver can't run before this method returns.
// The time zone may have changed while the receiver wasn't registered, so update the Time
mCalendar = new Time();
// Make sure we update to the current time
onTimeChanged();
counter.start();
}
#Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (mAttached) {
counter.cancel();
getContext().unregisterReceiver(mIntentReceiver);
mAttached = false;
}
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#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);
float hScale = 1.0f;
float vScale = 1.0f;
if (widthMode != MeasureSpec.UNSPECIFIED && widthSize < mDialWidth) {
hScale = (float) widthSize / (float) mDialWidth;
}
if (heightMode != MeasureSpec.UNSPECIFIED && heightSize < mDialHeight) {
vScale = (float )heightSize / (float) mDialHeight;
}
float scale = Math.min(hScale, vScale);
Log.d(AnalogClock.DEBUGTAG,"onMeasure params: " + widthSize + " "
+ heightSize + " " + hScale + " " + vScale + " " + scale);
try {
setMeasuredDimension(resolveSizeAndState((int) (mDialWidth * scale), widthMeasureSpec, 0),
resolveSizeAndState((int) (mDialHeight * scale), heightMeasureSpec, 0));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mChanged = true;
}
boolean mSeconds=false;
float mSecond=0;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
boolean changed = mChanged;
if (changed) {
mChanged = false;
}
boolean seconds = mSeconds;
if (seconds ) {
mSeconds = false;
}
int availableWidth = this.getMeasuredWidth();
int availableHeight = this.getMeasuredHeight();
int x = availableWidth / 2;
int y = availableHeight / 2;
final Drawable dial = mDial;
final Drawable dial_frame = mDial_frame;
final Drawable dial_dot = mDial_center;
int w = dial.getIntrinsicWidth();
int h = dial.getIntrinsicHeight();
boolean scaled = false;
// Log.d(AnalogClock.DEBUGTAG,"onDraw params: " + availableWidth +" "+ availableHeight + " " +
// x + " " + y + " " + w + " "+ h + " " + changed);
if (availableWidth < w || availableHeight < h) {
scaled = true;
//float scale = Math.min((float) availableWidth / (float) w,
// (float) availableHeight / (float) h);
canvas.save();
float scale1 = (float) 0.6;
float scale2 = (float) 0.8;
// Log.d(AnalogClock.DEBUGTAG,"scale params: " + scale1 + " " + scale2);
canvas.scale(scale1, scale2, x, y);
}
if (changed) {
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - (w / 2)) + " " + (y - (h / 2)) + " " + ( x + (w / 2)) + " " + (y + (h / 2)));
dial.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
//dial_frame.setBounds(x - (w / 2), y - (h / 2), x + (w / 2), y + (h / 2));
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - (w / 2 + w/10)) + " " + (y - (h / 2 + h/10)) + " " + ( x + (w / 2 + w/10)) + " " +
// (y + (h / 2 + h/10)));
dial_frame.setBounds(x - (w/2 + w/10), y - (h/2 + h/10), x + (w/2 + w/10), y + (h/2 + h/10));
dial_dot.setBounds(x -30 , y -20 , x + 30, y + 20);
//Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x ) + " " + (y) + " " + ( x + (w / 2 )) + " " +
// (y + (h / 2)));
}
int radius = 0;
if(x>y)
radius=y-10;
else
radius=x-10;
Paint circlepaint;
circlepaint = new Paint();
circlepaint.
dial.draw(canvas);
dial_frame.draw(canvas);
// canvas.drawCircle(x, y, radius, circlepaint);
canvas.save();
canvas.rotate(mHour / 12.0f * 180.0f, x - 10, y - 10);
final Drawable hourHand = mHourHand;
if (changed) {
w = hourHand.getIntrinsicWidth();
h = hourHand.getIntrinsicHeight();
hourHand.setBounds(x -w/2, y - h/2 - h/4 , x + w/6, y + h/6);
}
hourHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mMinutes / 60.0f * 360.0f, x - 10, y - 10);
final Drawable minuteHand = mMinuteHand;
if (changed) {
w = minuteHand.getIntrinsicWidth();
h = minuteHand.getIntrinsicHeight();
//minuteHand.setBounds(x, y, x + (w / 2 + w/10), y + (h / 2 + w/10));
minuteHand.setBounds(x - w, y - h/2, x + w/6, y + h/6);
// Log.d(AnalogClock.DEBUGTAG,"Bounds params:x " + (x) + " y " + (y) + " w " + ( w ) + " h " +
// (h));
// Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x - w) + " " + (y - h/2) + " " + ( x ) + " " +
// (y));
}
minuteHand.draw(canvas);
canvas.restore();
canvas.save();
canvas.rotate(mSecond, x, y);
if (seconds) {
w = mSecondHand.getIntrinsicWidth();
h = mSecondHand.getIntrinsicHeight();
// mSecondHand.setBounds(x, y, x + (w / 2 + w/10), y + (h / 2 + w/10));
mSecondHand.setBounds(x-w/6, y-h/6, x + w,y + h/2);
Log.d(AnalogClock.DEBUGTAG,"Bounds params: " + (x ) + " " + (y) + " " + ( w) + " " +
(h));
}
mSecondHand.draw(canvas);
canvas.restore();
canvas.save();
dial_dot.draw(canvas);
if (scaled) {
canvas.restore();
}
}
MyCount counter = new MyCount(10000, 1000);
public class MyCount extends CountDownTimer{
public MyCount(long millisInFuture, long countDownInterval) {
super(millisInFuture, countDownInterval);
}
#Override
public void onFinish() {
counter.start();
}
#Override
public void onTick(long millisUntilFinished) {
mCalendar.setToNow();
int second = mCalendar.second;
mSecond=6.0f*second;
mSeconds=true;
//mChanged = true;
AnalogClock.this.invalidate();
}
}
private void onTimeChanged() {
mCalendar.setToNow();
int hour = mCalendar.hour;
int minute = mCalendar.minute;
int second = mCalendar.second;
mMinutes = minute + second / 60.0f;
mHour = hour + mMinutes / 60.0f;
mChanged = true;
}
private final BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(Intent.ACTION_TIMEZONE_CHANGED)) {
String tz = intent.getStringExtra("time-zone");
mCalendar = new Time(TimeZone.getTimeZone(tz).getID());
}
onTimeChanged();
invalidate();
}
};
}