I want to move the text over an image to fix the text on the desired place over the image.
I run this code successfully But its not optimum as its not user friendly.Text Movement doesn't match to finger's pick and drop even sometimes.If anybody have better code Please share with me or let me know if i am missing something.
//Listeners for the Canvas that is being awarded
popImgae.setOnTouchListener( new OnTouchListener(){
public boolean onTouch(View v, MotionEvent e) {
someGlobalXvariable = e.getX();
someGlobalYvariable = e.getY();
setTextPosition();
//saveImage(imgRecord.get(1),leftPos,topPos,popText.getTextSize(),popText.getText().toString());
return true;
}
});
public void setTextPosition(){
try {
redrawImage(imgRecord.get(1),Integer.parseInt(imgRecord.get(8)),imgRecord.get(6),Integer.parseInt(imgRecord.get(9)));
} catch (Exception e) {
// TODO: handle exception
System.out.println("##########Error in setTextPositio========="+e.getMessage());
}
}
///Redrawing the image & touchin Move of the Canvas with text
public void redrawImage(String path,float sizeValue,String textValue,int colorValue) {
//Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.fashion_pic);
BitmapFactory.Options options = new BitmapFactory.Options();
try {
options.inMutable = true;
} catch (Exception e) {
// TODO: handle exception
System.out.println("#############Error is======"+e.getMessage());
}
Bitmap bm = BitmapFactory.decodeFile(path,options);
//bm = imageManipulation.convertToMutable(bm);
proxy = Bitmap.createBitmap(bm.getWidth(), bm.getHeight(), Config.ARGB_8888);
Canvas c = new Canvas(proxy);
//Here, we draw the background image.
c.drawBitmap(bm, new Matrix(), null);
Paint paint = new Paint();
paint.setColor(colorValue); // Text Color
paint.setStrokeWidth(30); // Text Size
paint.setTextSize(sizeValue);
System.out.println("Values passing=========="+someGlobalXvariable+", "+someGlobalYvariable+", "
+sizeValue+", "+textValue);
//Here, we draw the text where the user last touched.
c.drawText(textValue, someGlobalXvariable, someGlobalYvariable, paint);
popImgae.setImageBitmap(proxy);
}
class MyView extends View{
public MyView(Context context) {
super(context);
//get your drawable image
setBackgroundDrawable(drawable);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawText("text", x, y, new Paint());
}
float x,y;
#Override
public boolean onTouchEvent(MotionEvent event) {
x= event.getX();
y= event.getX();
invalidate();
return true;
}
}
Related
I want to create application like this.
Flood fill algorithm
I applied that code and it is working fine with JPG or PNG file.
But I want to use that algorithm with Vector drawable imageview
Vector drawable imageview before flood fill
After flood fill of vector imageview
Expected result should be like this (Flood fill work perfectly when I set JPG or PNG file)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flood_fill);
iv_FloodFillActivity_image = findViewById(R.id.iv_FloodFillActivity_image);
iv_FloodFillActivity_image.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
floodColor(event.getX(), event.getY());
}
return true;
}
});
}
private void floodColor(float x, float y) {
final Point p1 = new Point();
p1.x = (int) x;// X and y are co - ordinates when user clicks on the screen
p1.y = (int) y;
Bitmap bitmap = getBitmapFromVectorDrawable(iv_FloodFillActivity_image.getDrawable());
//bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true);
int pixel = bitmap.getPixel((int) x, (int) y);
int[] sourceColorRGB = new int[]{
Color.red(pixel),
Color.green(pixel),
Color.blue(pixel)
};
final int targetColor = Color.parseColor("#FF2200");
QueueLinearFloodFiller queueLinearFloodFiller = new QueueLinearFloodFiller(bitmap, sourceColor, targetColor);
int toleranceHex = Color.parseColor("#545454");
int[] toleranceRGB = new int[]{
Color.red(toleranceHex),
Color.green(toleranceHex),
Color.blue(toleranceHex)
};
queueLinearFloodFiller.setTolerance(toleranceRGB);
queueLinearFloodFiller.setFillColor(targetColor);
queueLinearFloodFiller.setTargetColor(sourceColorRGB);
queueLinearFloodFiller.floodFill(p1.x, p1.y);
bitmap = queueLinearFloodFiller.getImage();
iv_FloodFillActivity_image.setImageBitmap(bitmap);
}
private Bitmap getBitmapFromVectorDrawable(Drawable drawable) {
try {
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
drawable.draw(canvas);
return bitmap;
} catch (OutOfMemoryError e) {
return null;
}
}
Check Class : QueueLinearFloodFiller
How can I use vector drawable?
I have class allows you draw on an image from the filesystem. It has methods that I've shared below. The idea is that, as the image is touched, circles will be drawn on top of that image at each of the points that have been touched.
#Override
protected void onDraw(Canvas canvas) {
try{
if (mTextPaint == null)
{
mTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mTextPaint.setColor(Color.CYAN);
}
if (cachedBitmap == null)
{
Bitmap immutableBitmap = MediaStore.Images.Media.getBitmap(getContext().getContentResolver(), Uri.fromFile(CameraActivity.getFile()));
cachedBitmap = immutableBitmap.copy(Bitmap.Config.ARGB_8888, true);
}
if (cachedCanvas == null)
{
cachedCanvas = canvas;
cachedCanvas.setBitmap(cachedBitmap);
}
if (! mPoints.isEmpty())
{
for (Point point : mPoints)
{
cachedCanvas.drawCircle(point.x, point.y, 25, mTextPaint);
}
Log.i(TAG, "Drawing points...");
}
}
catch (Exception e)
{
Log.e(TAG, "Error on draw: " + e.toString());
}
}
/**
* populates a list of points that have been touched
*
* #param event
* #return
*/
#Override
public boolean onTouchEvent(MotionEvent event)
{
Point point = new Point((int)event.getX(), (int)event.getY());
mPoints.add(point);
invalidate();
return true;
}
After this is done, I'd like to include a static method that returns the now drawn on bitmap, something like this:
public static Bitmap getCachedBitmap()
{
return cachedBitmap;
}
The problem is, the cachedBitmap variable is not being updated as it is being drawn on, so when I inspect the return value of cachedBitmap, I just get the Bitmap from the file URI specified in the initial immutableBitmap variable.
Any idea how I can return the altered bitmap?
You can take an image of outer layout which contains both the bitmap and the canvas on which circles are drawn:
View v = yourlayout.getRootView();
v.setDrawingCacheEnabled(true);
Bitmap bitmap = v.getDrawingCache();
BitmapDrawable drawable=new BitmapDrawable(bitmap);
By this way, you will get your initial image + edits.
I am working a project in which an erasing functionality is there I want to user can undo
his erasing if he want but this functionality is not working for me.
My code is as:-
public EraserView(Context context) {
super(context);
setFocusable(true);
setBackgroundResource(R.drawable.back);
// setting paint
mPaint = new Paint();
mPath = new Path();
mPaint.setAlpha(0);
mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
mPaint.setColor(Color.TRANSPARENT);
mPaint.setAntiAlias(true);
// getting image from resources
Resources r = this.getContext().getResources();
Bitmap bm = BitmapFactory.decodeResource(getResources(),
R.drawable.image2);
// converting image bitmap into mutable bitmap
bitmap = bm.createBitmap(295, 260, Config.ARGB_8888);
pcanvas = new Canvas();
pcanvas.setBitmap(bitmap); // drawXY will result on that Bitmap
pcanvas.drawBitmap(bm, 0, 0, null);
paths.add(mPath);
}
#Override
protected void onDraw(Canvas canvas) {
// draw a circle that is erasing bitmap
pcanvas.drawCircle(x,y,r,mPaint);
/*for (Path objpath : paths) {
pcanvas.drawPath(objpath, mPaint);
}*/
canvas.drawBitmap(bitmap, 0, 0, null);
setBitmap(bitmap);
super.onDraw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
r = 8;
// Atlast invalidate canvas
invalidate();
break;
case MotionEvent.ACTION_UP:
x = (int) event.getX();
y = (int) event.getY();
r = 8;
// Atlast invalidate canvas
invalidate();
break;
case MotionEvent.ACTION_MOVE:
x = (int) event.getX();
y = (int) event.getY();
r = 8;
// Atlast invalidate canvas
invalidate();
break;
case MotionEvent.ACTION_POINTER_UP:
x = (int) event.getX();
y = (int) event.getY();
r = 8;
// Atlast invalidate canvas
invalidate();
break;
}
return true;
}
public void setBitmap(Bitmap bitmap) {
this.bitmap = bitmap;
}
public Bitmap getBitmap() {
return bitmap;
}
public void onClickUndo () {
if (paths.size()>0)
{
paths.add(paths.remove(paths.size()-1));
invalidate();
}
else
{
}
}![enter image description here][1]
as shown in image we erase some part of dog after that click undo button dog should come in his initial position.please any one guide me.
Have you tried saving (Canvas.save()) the Canvas before erasing any portion of the bitmap and then restoring (Canvas.restore()) and redrawing once the button is clicked?
In Android, how to give draw a rotating/flipping coin wrt user on SurfaceView. It's very easy to use an animation and show the flipping coin in an ImageView, but I require this on SurfaceView with the same smoothness. Is there any way that I can give flipping animation in an ImageView then take out its content at every instant and then draw it on the SurfaceView continuously?
you can use Matrix class to perfom these operation on drawing bitmap.
something like
Paint paint = new Paint();
paint.setAntiAlias(true);
Matrix needleTransMatrix = new Matrix();
needleTransMatrix.postRotate(rotationAngle,needleImage.getWidth()/2,needleImage.getHeight());
needleTransMatrix.postTranslate( centerX+METER_OFFSET-needleImage.getWidth()/2, centerY-needleImage.getHeight());
Matrix dialTransMatrix = new Matrix();
dialTransMatrix.postRotate(rotationAngle,dialImage.getWidth()/2,dialImage.getHeight()/2);
dialTransMatrix.postTranslate( METER_OFFSET,0);
canvas.drawBitmap(bgImage, METER_OFFSET, 0, paint);
canvas.drawBitmap(dialImage, dialTransMatrix, paint);
canvas.drawBitmap(needleImage, needleTransMatrix, paint);
The below is the drawing thread about which i am talking about
private class AnimationThread extends Thread{
private boolean isRunning = true;
private int destinationNeedlePosition = NEEDLE_POSITION_ENQURIES;
public AnimationThread(int destinationNeedlePosition) {
this.destinationNeedlePosition = destinationNeedlePosition;
}
public void cancelAnimation(){
isRunning = false;
}
#Override
public void run() {
int destinationAngle = destinationNeedlePosition *45;
while(isRunning && destinationAngle != rotationAngle){
if(destinationAngle > rotationAngle)
rotationAngle++;
else
rotationAngle--;
postInvalidate();
try {
sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
I have to draw a circle in live wallpaper when it touches the boundary the direction of drawing gets reversed (something like in zigzag format).
The problem is i am able to draw circle in this format. But:
How to remove the previously drawn circle so that only single circle (dot) is visible at a time.
When i redraw the bitmap it starts flickering why this happens?
Code is as follows:
Thread to draw circle:
{animRunnable = new Runnable() {
public void run() {
if (!isRightEndReached && moveCircleX < 320) {
moveCircleX++;
moveCircleY++;
} else if (isRightEndReached) {
moveCircleX--;
moveCircleY++;
}
if (moveCircleX >= 320) {
isRightEndReached = true;
} else if (moveCircleX <= 0) {
isRightEndReached = false;
}
moveCircle(moveCircleX, moveCircleY);
if (moveCircleY == 480) {
// end of screen -re-init x and y point to move circle.
moveCircleX = intialStartX-10;
moveCircleY = intialStartY+1;
isRightEndReached = false;
// show wallpaper.
showWallpaper();
moveCircle(moveCircleX, moveCircleY);
}
}
};
/**
* Method to move circle
*
* #param x
* #param y
*/
private void moveCircle(int x, int y) {
Log.d("x==" + x, "y==" + y);
Paint paint = new Paint();
SurfaceHolder surfaceHolder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
canvas.save();
paint.setColor(Color.RED);
canvas.drawCircle(x, y, 5, paint);
canvas.restore();
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
animHandler.removeCallbacks(animRunnable);
if (isVisible()) {
animHandler.postDelayed(animRunnable, 1000L / 500L);
}
}
//Show wallpaper method.
/**
* Method to show wallpaper.
*/
void showWallpaper() {
SurfaceHolder surfaceHolder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
System.out
.println("Drawing bitmap in show Wallpaper method.");
canvas.save();
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.aquarium, options);
canvas.drawColor(0xff000000);
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.restore();
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
}
}
SOLVED: finally i got the solution by not concentrating on removing circle but drawing bitmap again and again with new point. The method is as follows:
{
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPurgeable = true;
bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.aquarium, options);
Paint paint = new Paint();
/**
* Method to move circle i.e to draw bitmap with new circle position.
*
* #param x
* #param y
*/
private void renderBackground(int x, int y) {
Log.d("x==" + x, "y==" + y);
surfaceHolder = getSurfaceHolder();
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
if (canvas != null) {
paint.setColor(Color.RED);
canvas.save();
// set Back ground
canvas.drawBitmap(bitmap, 0, 0, null);
// write draw circle.
paint.setAntiAlias(true);
canvas.drawCircle(x, y, 15, paint);
canvas.restore();
bitmap.recycle();
}
} catch (Exception e) {
e.printStackTrace();
}
finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
// showWallpaper();
}
}
animHandler.removeCallbacks(animRunnable);
if (isVisible()) {
animHandler.postDelayed(animRunnable, 1000L / 25L);
}
}
}