I have a custom view where in I'm drawing 6 circles using canvas in Android. Those circles act as Page indicators; which means that on the click of each circle (drawn using canvas), the different items are being displayed in a view pager. Now my requirement is to set individual focus to each circles and set different accessibility to each one. Please help. Thanks in advance.
Thanks,
Rakesh
I had to use ExploreByTouchHelper to achieve my requirement as explained by #alanv and #pskink in the comment.
https://youtu.be/ld7kZRpMGb8?t=1196
Thanks guys!
You should take position of the view with View.getX() and View.getY() to get x and y of the upper left corner and also assuming You know the radius (or able to obtain width/height of the view to determine radius). After that, obtain :
xTouch = MotionEvent.getX();
yTouch = MotionEvent.getY();
Then check the condition if:
(xTouch - (x + radius)) * (xTouch - (x + radius)) + (yTouch - (y + radius)) * (yTouch - (y + radius)) <= radius * radius
The formula is just interpretation of schools geometry for determining if dot is inside circle area or not. Refer to circle equation for Cartesian coordinates for more details.
Values explanation is:
(x + radius) and (y + radius) is the center of circle.
(xTouch - (x + radius)) is distance from touch point to center by X.
(yTouch - (y + radius)) is distance from touch point to center by Y.
for the accessibility of the each circle and the accessibility text to be read it out if the TackBack is turned on then so the code for the complete scenario is:
package com.example.hello_world;
import java.util.Locale;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Bundle;
import android.speech.tts.TextToSpeech;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;
public class MainActivity extends Activity implements OnInitListener {
String mText_To_Speach_text;
private int MY_DATA_CHECK_CODE = 0;
TextToSpeech myTTS;
int initStatus = 0;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
Intent checkTTSIntent = new Intent();
checkTTSIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkTTSIntent, MY_DATA_CHECK_CODE);
}
class MyView extends View {
private Path mPath, mPath2, mPath3, mPath4, mPath5;
private Paint mPaint;
private RectF mOval, mOval2;
Region mRegion1, mRegion2, mRegion3, mRegion4, mRegion5, mRegion6;
public MyView(Context context) {
super(context);
mPath = new Path();
mPath2 = new Path();
mPath3 = new Path();
mPath4 = new Path();
mPath5 = new Path();
mPaint = new Paint();
mPaint.setColor(0xffff0000);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mPath.reset();
mPath.addCircle((w / 2) - 120, h / 2, 30, Direction.CW);
mPath.close();
mPath2.reset();
mPath2.addCircle((w / 2) - 60, h / 2, 30, Direction.CW);
mPath2.close();
mPath3.reset();
mPath3.addCircle(w / 2, h / 2, 30, Direction.CW);
mPath3.close();
mPath4.reset();
mPath4.addCircle((w / 2) + 60, h / 2, 30, Direction.CW);
mPath4.close();
mPath5.reset();
mPath5.addCircle((w / 2) + 120, h / 2, 30, Direction.CW);
mPath5.close();
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(0xffffffff);
mPaint.setStyle(Style.FILL);
canvas.drawPath(mPath, mPaint);
canvas.drawPath(mPath2, mPaint);
canvas.drawPath(mPath3, mPaint);
canvas.drawPath(mPath4, mPaint);
canvas.drawPath(mPath5, mPaint);
RectF rectF1 = new RectF();
mPath.computeBounds(rectF1, true);
mRegion1 = new Region();
mRegion1.setPath(mPath, new Region((int) rectF1.left,
(int) rectF1.top, (int) rectF1.right, (int) rectF1.bottom));
RectF rectF2 = new RectF();
mPath2.computeBounds(rectF2, true);
mRegion2 = new Region();
mRegion2.setPath(mPath2, new Region((int) rectF2.left,
(int) rectF2.top, (int) rectF2.right, (int) rectF2.bottom));
RectF rectF3 = new RectF();
mPath3.computeBounds(rectF3, true);
mRegion3 = new Region();
mRegion3.setPath(mPath3, new Region((int) rectF3.left,
(int) rectF3.top, (int) rectF3.right, (int) rectF3.bottom));
RectF rectF4 = new RectF();
mPath4.computeBounds(rectF4, true);
mRegion4 = new Region();
mRegion4.setPath(mPath4, new Region((int) rectF4.left,
(int) rectF4.top, (int) rectF4.right, (int) rectF4.bottom));
RectF rectF5 = new RectF();
mPath5.computeBounds(rectF5, true);
mRegion5 = new Region();
mRegion5.setPath(mPath5, new Region((int) rectF5.left,
(int) rectF5.top, (int) rectF5.right, (int) rectF5.bottom));
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (mRegion1.contains(x, y)) {
mText_To_Speach_text = "Circle1";
speakWords(mText_To_Speach_text);
} else if (mRegion2.contains(x, y)) {
mText_To_Speach_text = "Circle2";
speakWords(mText_To_Speach_text);
} else if (mRegion3.contains(x, y)) {
mText_To_Speach_text = "Circle3";
speakWords(mText_To_Speach_text);
} else if (mRegion4.contains(x, y)) {
mText_To_Speach_text = "Circle4";
speakWords(mText_To_Speach_text);
} else if (mRegion5.contains(x, y)) {
mText_To_Speach_text = "Circle5";
speakWords(mText_To_Speach_text);
}
}
return true;
}
}
private void speakWords(String speech) {
myTTS.speak(speech, TextToSpeech.QUEUE_FLUSH, null);
}
#Override
public void onInit(int status) {
if (initStatus == TextToSpeech.SUCCESS) {
if (myTTS.isLanguageAvailable(Locale.US) == TextToSpeech.LANG_AVAILABLE)
myTTS.setLanguage(Locale.US);
} else if (initStatus == TextToSpeech.ERROR) {
Toast.makeText(this, "Sorry! Text To Speech failed...",
Toast.LENGTH_LONG).show();
}
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_DATA_CHECK_CODE) {
if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
myTTS = new TextToSpeech(this, this);
} else {
Intent installTTSIntent = new Intent();
installTTSIntent
.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installTTSIntent);
}
}
}
}
Related
I am trying to create a family tree like structure in android. I am using canvas to draw rectangle and line for family members names and connecting line.
I am drawing rectangle and line by the following method with the help of link
DrawView.java
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
float mx, my, mdensity;
Paint mBGPaint, mTXTPaint,mLINEPaint,mBRDPaint;
String text;
public DrawView(Context context, float x, float y, float density, String text) {
super(context);
paint.setColor(Color.RED);
paint.setStrokeWidth(8);
paint.setStyle(Paint.Style.STROKE);
mx = x;
my = y;
mdensity = density;
this.text = text;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
init();
mLINEPaint.setStrokeWidth(8);
//draw rect border
canvas.drawRect(100, 100, 200, 200, mBRDPaint);
// //draw text
canvas.drawText(text, 150, 150, mTXTPaint);
// //draw line
float x = mx+150;
canvas.drawLine(x, 10, x, 100, mLINEPaint);
}
public void init() {
//rectangle background
mBGPaint = new Paint();
mBGPaint.setColor(Color.parseColor("#80123456"));
//your text
mTXTPaint = new Paint();
mTXTPaint.setColor(Color.parseColor("#123456"));
//your line
mLINEPaint = new Paint();
mLINEPaint.setColor(0xFFFF00FF);
//rectangle border
mBRDPaint = new Paint();
mBRDPaint.setStyle(Paint.Style.STROKE);
mBRDPaint.setStrokeWidth(10);
mBRDPaint.setColor(Color.parseColor("#80123456"));
}
}
Now I am trying to add multiple views in LinearLayout with orientation horizontal like below :
float density = getApplicationContext().getResources().getDisplayMetrics().density;
DrawView drawView;
float x = 100, y = 200;
int count1 = 1;
int id;
LinearLayout layout2 = new LinearLayout(this);
layout2.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
layout2.setOrientation(LinearLayout.HORIZONTAL);
main_layout.addView(layout2);
DrawView drawView1;
CircleView circleView;
for (Map.Entry<String, ArrayList<String>> entry : map.entrySet()) {
String key = entry.getKey();
if (count1 < 2) {
x = dirButton.getX();
y = dirButton.getY();
}
drawView1 = new DrawView(this, x, y, density, key);
drawView1.setId(butId++);
drawView1.setLayoutParams(params);
layout2.addView(drawView1);
count1++;
x = x + 100;
}
But when I do this only one view is added to the canvas and others are not visible. I have no experience in working with canvas in android , I would be glad if someone could guide me with this problem.
I tried working on your project but it is too broad to edit on the answer sheet. I must suggest to look these:
Multiple rect.
Rectangle with view
if (count1 < 2) {
x = dirButton.getX();
y = dirButton.getY();
}
from the code line above, you set condition for when the line is executed.
and use if statement.
int count1 = 1; //Count was initialized to 1
This makes the code to enter the if statement on first call
count1++;
This line increases the value of count to 2, hence the if block do not execute again...
And y value never change which leads to overlay.
May be what you missed is regular increament of y
y+=something;
Hope that helps
Please check how i have done this,
You can check from here form myapp, how it work
// How i call to draw rectangle
This is the SDV.class
public static boolean isDrawing = false;
public static float mStartX;
public static float mStartY;
public static float mx;
public static float my;
public static void Shape14(float x, float y, float radius) {
Path path = new Path();
y -= 2 * radius;
radius *= 2;
path.moveTo(x + radius, y + radius);
path.lineTo(x - radius, y + radius);
path.lineTo(x, y);
path.lineTo(x + radius, y + radius);
float div = (2 * radius) / 5;
float top = y + radius;
RectF rect1 = new RectF(x + radius / 4, y, x + radius / 1.9f, y
+ radius);
RectF rect2 = new RectF(x + div / 2, top, x + div / 2 + div, top + div
* 2);
RectF rect3 = new RectF(x - div / 2 - div, top, x - div / 2, top + div
* 2);
RectF rect4 = new RectF(x - div / 2, top, x + div / 2, top + div);
HashMap<String, Object> hm = new HashMap<String, Object>();
hm.put("type", shape14);
hm.put("paint", new Paint(DrawingView.mColorPaint));
hm.put("path", path);
hm.put("rect1", rect1);
hm.put("rect2", rect2);
hm.put("rect3", rect3);
hm.put("rect4", rect4);
al.add(hm);
Gmap.mDrawingView.invalidate();
}
Here is our view,
public class DrawingView extends View {
public static Paint mPaint;
public static int mCurrentShape;
Point p1, p2, p3, p4;
public static Paint mDotedPaint;
public static Paint mColorPaint;
GoogleMap googleMap;
SeekBar sbWidth;
public static float sx, sy;
public DrawingView(Context context, GoogleMap googleMap, SeekBar sbWidth) {
super(context);
this.googleMap = googleMap;
this.sbWidth = sbWidth;
mPaint = new Paint(Paint.DITHER_FLAG);
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(SDV.colorChoosen);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(SDV.width);
mDotedPaint = new Paint(Paint.DITHER_FLAG);
mDotedPaint.setAntiAlias(true);
mDotedPaint.setDither(true);
mDotedPaint.setColor(SDV.colorChoosen);
mDotedPaint.setStyle(Paint.Style.STROKE);
mDotedPaint.setStrokeJoin(Paint.Join.ROUND);
mDotedPaint.setStrokeCap(Paint.Cap.ROUND);
mDotedPaint.setStrokeWidth(SDV.width);
mColorPaint = new Paint(Paint.DITHER_FLAG);
mColorPaint.setAntiAlias(true);
mColorPaint.setDither(true);
mColorPaint.setFilterBitmap(true);
mColorPaint.setStyle(Paint.Style.FILL);
mColorPaint.setStrokeWidth(SDV.width);
mColorPaint.setColor(SDV.colorChoosen);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
sx = super.getWidth() * 0.5f;
sy = super.getHeight() * 0.5f;
if (SDV.isDrawing) {
new OnGoingDrawings().HandleAllOnGoingDrawings(mCurrentShape,
canvas);
} else {
new ShapeDrawer().DrawEverything(canvas, googleMap, sbWidth);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
SDV.mx = event.getX();
SDV.my = event.getY();
switch (mCurrentShape) {
case SDV.shape14:
TouchEvents.Shape14(event);
break;
return true;
}
}
Here is touch listener,
public static void Shape14(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
SDV.isDrawing = true;
SDV.mStartX = SDV.mx;
SDV.mStartY = SDV.my;
Gmap.mDrawingView.invalidate();
break;
case MotionEvent.ACTION_MOVE:
Gmap.mDrawingView.invalidate();
break;
case MotionEvent.ACTION_UP:
SDV.isDrawing = false;
float x = SDV.mStartX,
y = SDV.mStartY;
float DifX = Math.abs(SDV.mx - SDV.mStartX);
float DifY = Math.abs(SDV.my - SDV.mStartY);
float radius;
if (DifY > DifX)
radius = Math.abs(SDV.my - SDV.mStartY);
else
radius = Math.abs(SDV.mx - SDV.mStartX);
SDV.Shape14(x, y, radius);
break;
}
}
I am making a n app that uses an android phone s accelerometer, I currently have the x value set as the variable mX (that is restricted from 0 - 10) now I have an ImageView widget that I want to rotate left if mX is lower than 5 and rotate right if mX is higher than 5 and reset to horizontal when mX is 5. My problem is that I have tried using animations, matrixs but they don't work . Please help and thanks in advance.
Enjoy this code. If helpful, let me know:
public int getDeviceDefaultOrientation() {
WindowManager windowManager = (WindowManager) getSystemService(WINDOW_SERVICE);
Configuration config = getResources().getConfiguration();
int rotation = windowManager.getDefaultDisplay().getRotation();
if ( ((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) &&
config.orientation == Configuration.ORIENTATION_LANDSCAPE)
|| ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) &&
config.orientation == Configuration.ORIENTATION_PORTRAIT)) {
return Configuration.ORIENTATION_LANDSCAPE;
} else {
return Configuration.ORIENTATION_PORTRAIT;
}
}
I got a similar example
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class SkySurfaceView extends SurfaceView implements OnTouchListener {
private static final String TAG = SkySurfaceView.class.getSimpleName();
private double viewPortX, viewPortY;
private int starX, starY;
private Bitmap target;
private int targetWidth, targetHeight;
private int vpWidth, vpHeight;
private Matrix skyMatrix, skyMatrix2;
private Matrix skyMatrix3;
private Bitmap star;
private Paint paint;
private Rect touchRect, touchRect2, touchRect3;
public SkySurfaceView(Context context, AttributeSet attr) {
super(context, attr);
viewPortX = viewPortY = 0;
skyMatrix = new Matrix();
skyMatrix2 = new Matrix();
skyMatrix3 = new Matrix();
paint = new Paint();
paint.setStrokeWidth(1);
paint.setDither(true);
paint.setColor(Color.RED);
Options opt = new Options();
opt.inSampleSize = 2;
opt.inScaled = false;
opt.inPreferredConfig = Config.RGB_565;
star = BitmapFactory.decodeResource(getResources(), R.drawable.star,
opt);
touchRect = new Rect(0, 0, star.getWidth(), star.getHeight());
touchRect2 = new Rect(0, 0, star.getWidth(), star.getHeight());
touchRect3 = new Rect(0, 0, star.getWidth(), star.getHeight());
this.setWillNotDraw(true);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
this.setOnTouchListener(this);
getHolder().setFormat(PixelFormat.RGB_565);
}
public void setTarget(Bitmap b) {
target = b;
targetHeight = target.getHeight();
targetWidth = target.getWidth();
}
public void init() {
this.starX = (int) (vpWidth * Math.random()) + vpWidth;
this.starY = (int) ((vpHeight - star.getHeight()) * Math.random());
Log.i(TAG, "drawn star on " + starX + "," + starY);
Canvas c = new Canvas();
Log.i(TAG,
"target dimension is " + target.getWidth() + "x"
+ target.getHeight());
Bitmap bitmap = Bitmap.createBitmap(target.getWidth(),
target.getHeight(), Config.RGB_565);
c.setBitmap(bitmap);
c.drawBitmap(target, 0, 0, paint);
c.drawBitmap(star, starX, starY, paint);
c.drawBitmap(star, starX - targetWidth, starY, paint);
target.recycle();
setTarget(bitmap);
setWillNotDraw(false);
}
#Override
public boolean performClick() {
super.performClick();
return false;
}
/**
*
* #param x
* - [-1:1]
* #param y
* - [-1:1]
*/
public void setViewPort(double x, double y) {
viewPortX = x;
viewPortY = y;
int tempX = (int) (targetWidth * (viewPortX));
int tempY = (int) (targetHeight * (viewPortY - 1));
tempY = Math.max(tempY, -(targetHeight - vpHeight) / 2);
tempY = Math.min(tempY, +(targetHeight - vpHeight / 2));
Log.i(TAG,
String.format("%d %d , %d %d, %d %d", tempX, tempY, tempX
- targetWidth, tempY, tempX + targetWidth, tempY));
skyMatrix.reset();
skyMatrix.postTranslate(tempX, tempY);
skyMatrix2.reset();
skyMatrix2.postTranslate(tempX - targetWidth, tempY);
skyMatrix3.reset();
skyMatrix3.postTranslate(tempX + targetWidth, tempY);
int xx = (tempX + starX);
while (xx < targetWidth) {
xx += targetWidth;
}
touchRect.offsetTo(xx % targetWidth, (tempY + starY) % targetHeight);
touchRect2.offsetTo(xx % targetWidth - targetWidth, (tempY + starY)
% targetHeight);
touchRect3.offsetTo(xx % targetWidth + targetWidth, (tempY + starY)
% targetHeight);
postInvalidate();
}
public void setViewportSize(int x, int y) {
vpWidth = x;
vpHeight = y;
}
#Override
protected void onDraw(Canvas c) {
super.onDraw(c);
c.drawBitmap(target, skyMatrix, paint);
c.drawBitmap(target, skyMatrix2, paint);
c.drawBitmap(target, skyMatrix3, paint);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
float ex = event.getX();
float ey = event.getY();
Log.i(TAG, "touched " + ex + " " + ey);
if (touchRect.contains((int) ex, (int) ey)) {
if (listener != null) {
listener.onCaptured();
}
} else if (touchRect2.contains((int) ex, (int) ey)) {
if (listener != null) {
listener.onCaptured();
}
} else if (touchRect3.contains((int) ex, (int) ey)) {
if (listener != null) {
listener.onCaptured();
}
}
return false;
}
public void setListener(OnStarCaptureListener listener) {
this.listener = listener;
}
}
In this class, "target" is the image to be moved according to the viewport. Upon "setViewPort" is called (x and y values from -1 to 1), the view is invalidated and the onDraw() method will draw the image with offset.
I am looking for an animation liberary of code which will help me to do 360 degree animation using set of images (Around 60 images for horizontal rotation). Also images are in SDCARD and not in application.
Thank You
You can create a custom view and override onDraw(Canvas) method and draw the bitmap of desired image.
You can keep track on the current "direction" in degree and calculate which should be displayed in what location using Canvas.drawBitmap(Bitmap,Matrix,Paint).
Here's an example of moving one image according to phone orientation.
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.BitmapFactory.Options;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class SkySurfaceView extends SurfaceView implements OnTouchListener {
private static final String TAG = SkySurfaceView.class.getSimpleName();
private double viewPortX, viewPortY;
private int starX, starY;
private Bitmap target;
private int targetWidth, targetHeight;
private int vpWidth, vpHeight;
private Matrix skyMatrix, skyMatrix2;
private Matrix skyMatrix3;
private Bitmap star;
private Paint paint;
private Rect touchRect, touchRect2, touchRect3;
public SkySurfaceView(Context context, AttributeSet attr) {
super(context, attr);
viewPortX = viewPortY = 0;
skyMatrix = new Matrix();
skyMatrix2 = new Matrix();
skyMatrix3 = new Matrix();
paint = new Paint();
paint.setStrokeWidth(1);
paint.setDither(true);
paint.setColor(Color.RED);
Options opt = new Options();
opt.inSampleSize = 2;
opt.inScaled = false;
opt.inPreferredConfig = Config.RGB_565;
star = BitmapFactory.decodeResource(getResources(), R.drawable.star,
opt);
touchRect = new Rect(0, 0, star.getWidth(), star.getHeight());
touchRect2 = new Rect(0, 0, star.getWidth(), star.getHeight());
touchRect3 = new Rect(0, 0, star.getWidth(), star.getHeight());
this.setWillNotDraw(true);
setLayerType(View.LAYER_TYPE_HARDWARE, null);
this.setOnTouchListener(this);
getHolder().setFormat(PixelFormat.RGB_565);
}
public void setTarget(Bitmap b) {
target = b;
targetHeight = target.getHeight();
targetWidth = target.getWidth();
}
public void init() {
this.starX = (int) (vpWidth * Math.random()) + vpWidth;
this.starY = (int) ((vpHeight - star.getHeight()) * Math.random());
Log.i(TAG, "drawn star on " + starX + "," + starY);
Canvas c = new Canvas();
Log.i(TAG,
"target dimension is " + target.getWidth() + "x"
+ target.getHeight());
Bitmap bitmap = Bitmap.createBitmap(target.getWidth(),
target.getHeight(), Config.RGB_565);
c.setBitmap(bitmap);
c.drawBitmap(target, 0, 0, paint);
c.drawBitmap(star, starX, starY, paint);
c.drawBitmap(star, starX - targetWidth, starY, paint);
target.recycle();
setTarget(bitmap);
setWillNotDraw(false);
}
#Override
public boolean performClick() {
super.performClick();
return false;
}
/**
*
* #param x
* - [-1:1]
* #param y
* - [-1:1]
*/
public void setViewPort(double x, double y) {
viewPortX = x;
viewPortY = y;
int tempX = (int) (targetWidth * (viewPortX));
int tempY = (int) (targetHeight * (viewPortY - 1));
tempY = Math.max(tempY, -(targetHeight - vpHeight) / 2);
tempY = Math.min(tempY, +(targetHeight - vpHeight / 2));
Log.i(TAG,
String.format("%d %d , %d %d, %d %d", tempX, tempY, tempX
- targetWidth, tempY, tempX + targetWidth, tempY));
skyMatrix.reset();
skyMatrix.postTranslate(tempX, tempY);
skyMatrix2.reset();
skyMatrix2.postTranslate(tempX - targetWidth, tempY);
skyMatrix3.reset();
skyMatrix3.postTranslate(tempX + targetWidth, tempY);
int xx = (tempX + starX);
while (xx < targetWidth) {
xx += targetWidth;
}
touchRect.offsetTo(xx % targetWidth, (tempY + starY) % targetHeight);
touchRect2.offsetTo(xx % targetWidth - targetWidth, (tempY + starY)
% targetHeight);
touchRect3.offsetTo(xx % targetWidth + targetWidth, (tempY + starY)
% targetHeight);
postInvalidate();
}
public void setViewportSize(int x, int y) {
vpWidth = x;
vpHeight = y;
}
#Override
protected void onDraw(Canvas c) {
super.onDraw(c);
c.drawBitmap(target, skyMatrix, paint);
c.drawBitmap(target, skyMatrix2, paint);
c.drawBitmap(target, skyMatrix3, paint);
}
#Override
public boolean onTouch(View v, MotionEvent event) {
float ex = event.getX();
float ey = event.getY();
Log.i(TAG, "touched " + ex + " " + ey);
if (touchRect.contains((int) ex, (int) ey)) {
if (listener != null) {
listener.onCaptured();
}
} else if (touchRect2.contains((int) ex, (int) ey)) {
if (listener != null) {
listener.onCaptured();
}
} else if (touchRect3.contains((int) ex, (int) ey)) {
if (listener != null) {
listener.onCaptured();
}
}
return false;
}
public void setListener(OnStarCaptureListener listener) {
this.listener = listener;
}
}
In this example, "target" is a sky image. Whenever setViewPort is called, (x and y [-1:1]), the image's drawing matrix is updated and "invalidate()" is called. The onDraw() method call will draw the "target" with offset.
I am creating an app in android in which the user creates a drawing by touching the screen and then
save it to storage.
My problem is that sometimes the directory does not created , sometimes the image saves but there are a lot of images saved in directory with black images.
The main file saving operation occurs in getDrawnMessage() method.
Here is my code
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.Bitmap.Config;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Environment;
import android.view.MotionEvent;
import android.view.View;
public class DrawWrite extends View {
float TouchXD = 0, TouchYD = 0, TouchXU = 0, TouchYU = 0, TouchXM = 0,
TouchYM = 0; // Define touch co-ordinates
float x1 = 0, y1 = 0, x2 = 0, y2 = 0; // Define drawing path co-ordinates
float stroke = 2; // Define the message structure width
int i=0;
boolean Move = false, moveD = false, moveU = false; // Define whether the
// touch has occurred or
// not
boolean exp = false;
Paint paint = new Paint(); // Paint object
Path mPath = new Path(); // Define the drawing message path
Context context;
public DrawWrite(Context context) {
super(context);
this.context=context;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
invalidate();
paint.setAntiAlias(true);
if (DrawWriteActivity.clearScreen){
mPath.reset();
DrawWriteActivity.clearScreen = false;
}
cleanButton(canvas);
try {
getDrawnMessage(canvas);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
paint.setColor(Color.parseColor(DrawWriteActivity.colorProvider));
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(DrawWriteActivity.strokeProvider);
if (moveD == true) {
x1 = TouchXD;
y1 = TouchYD;
moveD = false;
} else if (Move == true) {
x2 = TouchXD;
y2 = TouchYD;
mPath.moveTo(x1, y1);
mPath.lineTo(x2, y2);
canvas.drawPath(mPath, paint);
x1 = x2;
y1 = y2;
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
TouchXD = (float) event.getX();
TouchYD = (float) event.getY();
moveD = true;
break;
case MotionEvent.ACTION_UP:
TouchXU = (float) event.getX();
TouchYU = (float) event.getY();
moveU = true;
break;
case MotionEvent.ACTION_MOVE:
TouchXD = (float) event.getX();
TouchYD = (float) event.getY();
Move = true;
break;
}
return true;
}
public void getDrawnMessage(Canvas canvas) throws FileNotFoundException{
if(exp){
Bitmap bitmap = null;
String root = Environment.getExternalStorageDirectory().toString();
File imgDir = new File(root+"/ChitBak/");
String imgName;
bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Config.ARGB_8888);
imgDir.mkdirs();
imgName = "img"+i+".jpg";
i++;
File file = new File(imgDir,imgName);
if(file.exists()) file.delete();
FileOutputStream outImg = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, outImg);
exp = false;
Intent in = new Intent(context, MainActivity.class);
in.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
context.startActivity(in);
}
}
private void cleanButton(Canvas canvas) {
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.DKGRAY);
canvas.drawRoundRect(new RectF(getWidth() - 100, getHeight() - 70,
getWidth() - 20, getHeight() - 20), 10, 10, paint);
paint.setColor(Color.LTGRAY);
paint.setTextSize(27);
paint.setTextSkewX((float) 0.2);
canvas.drawText("Save", getWidth() - 92, getHeight() - 35, paint);
}
private void isResetRequested() {
if (TouchXD >= (getWidth() - 100) && TouchYD >= getHeight() - 70
&& TouchXD <= (getWidth() - 20) && TouchYD <= getHeight() - 20){
exp = true;
}
}
}
Please help me friends because i don't know how to resolve this.
Thanks in advance.
If you want anything in code then tell me i will provide it.
I think your capture method is wrong.
Saving the View as a Bitmap
Here is a code I'm using to dump an entire view into a Bitmap (this will not save the notification bar nor the navigation bar):
final DisplayMetrics displayMetrics = ApplicationHelper.resources().getDisplayMetrics();
if (displayMetrics == null) {
LogHelper.warning("DisplayMetrics was NULL");
return null;
}
view.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT));
view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels);
view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
view.buildDrawingCache();
final Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
final Canvas canvas = new Canvas(bitmap);
view.draw(canvas);
return bitmap;
Remember that you can use android.R.id.content to get your entire application's screen space, as a View.
Saving to external storage
With file.mkdirs() your code should work.
I am developing small android application in which I m using my custom linear layout class. In that class i tried to draw one small triangle and tried to include it in to my linear layout but I m not able to do that. I tried it in following ways ...
#SuppressLint("DrawAllocation")
public class SimpleLin extends LinearLayout {
public String TAG = "CustomviewActivity";
LinearLayout parentLayout;
public SimpleLin(Context context)
{
super(context);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(inflater != null){
view = inflater.inflate(R.layout.main2, this);d.lin_llt);
parentLayout.setBackgroundResource(R.drawable.bcd);
}
}
public SimpleLin(Context context, AttributeSet attrs) {
super( context, attrs );
context1= context;
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("############################", "inside ondraw");
Paint p = new Paint();
p.setStyle(Style.FILL);
p.setColor(Color.RED);
Point point = new Point();
point.x = 80;
point.y = 80;
Path path = getEquilateralTriangle(point, 70, Direction.SOUTH);
Bitmap b = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
canvas.drawPath(path, p);
}
public static Path getEquilateralTriangle(Point p1, int width, Direction direction) {
Point p2 = null, p3 = null;
if (direction == Direction.NORTH) {
p2 = new Point(p1.x + width, p1.y);
p3 = new Point(p1.x + (width / 2), p1.y - width);
}
else if (direction == Direction.SOUTH) {
p2 = new Point(p1.x + width,p1.y);
p3 = new Point(p1.x + (width / 2), p1.y + width);
}
else if (direction == Direction.EAST) {
p2 = new Point(p1.x, p1.y + width);
p3 = new Point(p1.x - width, p1.y + (width / 2));
}
else if (direction == Direction.WEST) {
p2 = new Point(p1.x, p1.y + width);
p3 = new Point(p1.x + width, p1.y + (width / 2));
}
Path path = new Path();
path.moveTo(p1.x, p1.y);
path.lineTo(p2.x, p2.y);
path.lineTo(p3.x, p3.y);
return path;
}
public enum Direction
{
NORTH, SOUTH, EAST, WEST;
}
#SuppressWarnings("deprecation")
public void initialiseImages()
{
invalidate();
}
}
I am calling initialiseImages method from my activity where i wanted to use this custom layout. So problem is that It not calling my on draw method when i use invalidate(). That's why it not drawing my triangle. and I am also confuse how to include that triangle into my parentlayout..
Is there wrong in my code..
How to draw such shapes in android...
Need help...
Thank you...
Code for Custom Linear Layout (I modified your code so its easier for you to understand)
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.LinearLayout;
/**
* #author Atrix1987
*
*/
public class CustomView extends LinearLayout {
/**
* #param context
*/
public CustomView(Context context) {
super(context);
commonConstructor(context);
}
/**
* #param context
* #param attrs
*/
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
commonConstructor(context);
}
/**
*
*/
Paint trianglePaint;
/**
*
*/
Path trianglePath;
/**
* #param context
*/
private void commonConstructor(Context context) {
trianglePaint = new Paint();
trianglePaint.setStyle(Style.FILL);
trianglePaint.setColor(Color.RED);
Point point = new Point();
point.x = 80;
point.y = 80;
trianglePath = getEquilateralTriangle(point, 70, Direction.SOUTH);
}
#Override
protected void onDraw(Canvas canvas) {
Log.i("Sample", "inside ondraw");
//avoid creating objects in onDraw
canvas.drawPath(trianglePath, trianglePaint);
}
private Path getEquilateralTriangle(Point p1, int width, Direction direction) {
Log.i("Sample", "inside getEqui");
Point p2 = null, p3 = null;
if (direction == Direction.NORTH) {
p2 = new Point(p1.x + width, p1.y);
p3 = new Point(p1.x + (width / 2), p1.y - width);
} else if (direction == Direction.SOUTH) {
p2 = new Point(p1.x + width, p1.y);
p3 = new Point(p1.x + (width / 2), p1.y + width);
} else if (direction == Direction.EAST) {
p2 = new Point(p1.x, p1.y + width);
p3 = new Point(p1.x - width, p1.y + (width / 2));
} else if (direction == Direction.WEST) {
p2 = new Point(p1.x, p1.y + width);
p3 = new Point(p1.x + width, p1.y + (width / 2));
}
Path path = new Path();
path.moveTo(p1.x, p1.y);
path.lineTo(p2.x, p2.y);
path.lineTo(p3.x, p3.y);
return path;
}
public enum Direction {
NORTH, SOUTH, EAST, WEST;
}
}
The code for the activity (For simplicity and as a shortcut i did this, you can also specify it in the xml and just setContentView):
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
/**
* #author Atrix1987
*
*/
public class SampleActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
CustomView cv = new CustomView(getApplicationContext());
cv.setBackgroundColor(Color.WHITE);
setContentView(cv, new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
}
Do explore the developer site links for custom views, for more insight.
Hope this helps.
PFB the screenshot
If you are wanting a drawable you can use, try this http://looksok.wordpress.com/2013/08/24/android-triangle-arrow-defined-as-an-xml-shape/ sadly I can't claim credit