How to disable invalidate()? - android

At first my programm looks like this:
But when i am moving the picture around the screen programm turns to:
Red graph is random-generated in onDraw method. So i want to draging picture around and have static background that not inavalidates while im moving picture.
here is my code:
Custom View:
package com.graph.base;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
import java.util.Random;
public class CustomView extends View
{
Random random=new Random();
public CustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomView(Context context) {
super(context);
}
public void onDraw (Canvas canvas)
{
super.onDraw(canvas);
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.WHITE);
canvas.drawPaint(paint);
Path path=new Path();
path.moveTo(10, 10);
for (float i=0.5f; i<=140; i+=10)
{
path.quadTo(10+i*5, 10+random.nextInt(500), 10+(i+10)*5, 10+random.nextInt(500));
}
paint.setDither(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStrokeWidth(2);
canvas.drawPath(path, paint);
}
}
MainActivity
package com.graph.base;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
public class MainActivity extends Activity {
FrameLayout frame;
ImageView image;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
frame=(FrameLayout)findViewById(R.id.frameLayout1);
image=(ImageView)findViewById(R.id.imageView1);
image.setOnTouchListener(new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
Log.e("TAG", "Touch happend");
switch (event.getAction())
{
case MotionEvent.ACTION_MOVE:
{
image.setPadding((int)event.getX(), (int)event.getY(), 0, 0);
break;
}
}
return true;
}
});
}
public void invalidateButton_Click (View v)
{
frame.invalidate();
}
}

You're drawing random lines onto your canvas. This code is called each time the screen is invalidated. If you want to keep the drawing from changing, then set a bitmap into a canvas and draw into the bitmap. In your onDraw() method you'll then draw the bitmap onto the canvas.
// Outside of onDraw()
Bitmap bmDest = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
Canvas mycanvas = new Canvas(bmDest);
// Do your drawing on the canvas outside of the onDraw() method
In onDraw(), you'll simply do this:
canvas.drawBitmap(bmDest, x, y, null);

Actually, you should not "disable invalidate" but really do call "invalidate"...
In
case MotionEvent.ACTION_MOVE:
{
image.setPadding((int)event.getX(), (int)event.getY(), 0, 0);
// here call frame.invalidate(Rect dirty), with dirty set to where the image was previously
break;
}
Note that if your custom View draws "Randomly", then you can get a Bitmap with the cached version and draw from that (blit copy)

Related

A reset Button on canvas

I need to make a Button that cleans my canvas and also a safe button.
I would like that the Activity stays like it is . And just Path what was drawn would be deleted.Thank you so much for any help. My Code:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class TouchEventDraw extends View {
//Variable
private Paint paint = new Paint();
private Path path = new Path();
//Konstruktor
public TouchEventDraw(Context context, AttributeSet attrset) {
super(context, attrset);
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStrokeJoin(Paint.Join.MITER);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5f);
}
/**
* The most important step in drawing a custom view is to override the
* #param canvas object that the view can use to draw itself. */
#Override
protected void onDraw(Canvas canvas) {
if(path.isEmpty())
canvas.drawColor(Color.WHITE);
else
canvas.drawPath(path, paint);
}
/**
* Method to handle touch screen motion events.
* #param event The motion event
* #return True if the event was handled, false otherwise.*/
#Override
public boolean onTouchEvent(MotionEvent event) {
float xPos = event.getX();
float yPos = event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.moveTo(xPos,yPos);
return true;
case MotionEvent.ACTION_MOVE:
path.lineTo(xPos,yPos);
break;
case MotionEvent.ACTION_UP:
break;
default:
return false;
}
invalidate();
return true;
}
public void clear(){
path = new Path();
invalidate();
}
}
And my Activity with Buttons:
import android.graphics.Canvas;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
public class DrawingScreen extends AppCompatActivity {
Button btn;
TouchEventDraw ted;
Canvas canva;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ted=new TouchEventDraw(this,null);
setContentView(R.layout.activity_drawing_screen);
btn=(Button) findViewById(R.id.button);
btn.setOnClickListener(onClickListener);
}
private final View.OnClickListener onClickListener=new View.OnClickListener() {
#Override
public void onClick(View v) {
ted.clear();
ted.invalidate();
}
};
}
You need to add a method to your TouchEventDraw class, and call the following in it
canva.drawColor(Color.WHITE);
Then on your button click, call the method you created.
You should be able to implement the solution with the information I supplied.
I think there are more fatal issues through your code though, as I see the following:
The view is never being put on screen.
You extend View, rather than SurfaceView.
Another way, you should be able to create a method, and instead set path empty
public void clear(){
path = new Path();
}
then change your draw to
#Override
protected void onDraw(Canvas canvas) {
if(path.isEmpty())
canvas.drawColor(Color.WHITE);
else
canvas.drawPath(path, paint);
}
and call View.invalidate();

Android - Dynamic Mask Shape

I am trying to implement Masking of an image for my android project.
I am trying to accomplish the same as below image :
and the output would be the same as below link:
The link below is close to what I want to achieve only that I need to create the mask at runtime and handle onTouchListener to draw the mask but how?
Masking(crop) image in frame
I can't figure out myself and I feel stuck at this problem.
Any help or tutorials that will help is highly appreciated.
Although I didn't write a complete solution it could show you right direction.
package com.example.masktest.app;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.NonNull;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MaskDrawingView extends View {
private Path path = new Path();
private Paint pathPaint = new Paint();
public MaskDrawingView(Context context) {
super(context);
init();
}
public MaskDrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MaskDrawingView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
pathPaint.setStyle(Paint.Style.STROKE);
pathPaint.setAlpha(150);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawPath(path, pathPaint);
invalidate();
}
#Override
public boolean onTouchEvent(#NonNull MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
path.lineTo(event.getX(), event.getY());
break;
}
return super.onTouchEvent(event);
}
public Bitmap finishDrawingAndGetMask() {
pathPaint.setStyle(Paint.Style.FILL);
path.close();
setDrawingCacheEnabled(true);
Bitmap result = Bitmap.createBitmap(getDrawingCache());
setDrawingCacheEnabled(false);
path.reset();
return result;
}
}

Android Clip drawText to Paint over that text

I am new to 2d graphics..
I create a text using drawText method.
I have to paint over the drawtext area..
how can i clip the area of the text and paint over the surface
package com.example.testingcanvas;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
public class MainActivity extends Activity {
class MyCustomView extends View {
private float x = 0, y = 0;
Path path = new Path();
Paint paint = new Paint();
Bitmap bm = BitmapFactory.decodeResource(getResources(), R.drawable.ii);
private Rect m_ImageRect;
private Rect m_TextRect;
Context m_Context;
// you need these constructor
// you can init paint object or anything on them
public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
m_Context = context;
}
public MyCustomView(Context context, AttributeSet attrs) {
super(context, attrs);
m_Context = context;
}
public MyCustomView(Context context) {
super(context);
m_Context = context;
}
// then override on draw method
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(Paint.Join.ROUND);
paint.setStrokeWidth(3);
paint.setTextSize(100);
// here frist create two rectangle
// one for your image and two for text you want draw on it
m_ImageRect = canvas.getClipBounds();
m_TextRect = canvas.getClipBounds();
// it gives you an area that can draw on it,
// the width and height of your rect depend on your screen size
// device
canvas.save();
canvas.drawBitmap(bm, null, m_ImageRect, paint);
canvas.drawPath(path, paint);
canvas.restore();
canvas.save();
canvas.clipRect(m_TextRect);
canvas.drawText("A", 100, 300, paint);
// canvas.drawText("A", 20, 20,50,50, paint);
// canvas.restore();
}
public boolean onTouchEvent(MotionEvent event) {
// TODO Auto-generated method stub
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_MOVE:
x = event.getX();
y = event.getY();
path.lineTo(x, y);
break;
case MotionEvent.ACTION_DOWN:
x = event.getX();
y = event.getY();
path.moveTo(x, y);
break;
case MotionEvent.ACTION_UP: {
}
default:
}
invalidate();
return true;
}
}
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new MyCustomView(this));
}
public void onBackPressed() {
int pid = android.os.Process.myPid();
android.os.Process.killProcess(pid);
finish();
onDestroy();
}
}
i am trying to draw over the text area.but i cant get it.

[Android]canvas.drawText is very slow while changing text size continuously

I'm trying to scale the text continuously by changing text size. And I implement my own view to drawText on canvas every time the text size changed. But the procedure of invalidate and redraw canvas became very slow which lead to some animation became slow too.
The specific os version is 4.0.3(The application works well on the same kind device with os version 4.1.1)
The hardware acceleration is on.(works well when it's off)
I wrote a simple project to reproduce this issue.
The custom view:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class MyTextView extends View {
private Paint mPaint;
private float mTextSize = 80f;
public MyTextView(Context context) {
this(context, null);
}
public MyTextView(Context context, AttributeSet attr) {
super(context, attr);
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setTextSize(mTextSize);
}
#Override
public void onDraw(Canvas canvas) {
canvas.save();
mPaint.setTextSize(mTextSize);
canvas.drawText("Test test test", 200, 200, mPaint);
canvas.restore();
mTextSize += 1f;
}
}
The Activity:
import android.os.Bundle;
import android.view.MotionEvent;
import android.app.Activity;
public class MainActivity extends Activity {
private MyTextView mTextView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mTextView = (MyTextView)findViewById(R.id.text);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mTextView.invalidate();
return true;
}
}
Finally I used StaticLayout.draw(Canvas) instead call Canvas.drawText

draw object/image on canvas

Is there another way to draw an object on a canvas in android?
This code inside draw() doesn't work:
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pushpin);
canvas.drawBitmap(bmp, screenPts.x, screenPts.y-50, null);
Well actually, it's working on my 1st code but when I've transfered this to another class called MarkOverlay, it's not working anymore.
markerOverlay = new MarkerOverlay(getApplicationContext(), p);
listOfOverlays.add(markerOverlay);
What parameter should I pass to MarkerOverlay to make this code work? The error is somewhere in getResources().
FYI, canvas.drawOval is perfectly working but I really want to draw an Image not an Oval. :)
I prefer to do this as it only generates the image once:
public class CustomView extends View {
private Drawable mCustomImage;
public CustomView(Context context, AttributeSet attrs) {
super(context, attrs);
mCustomImage = context.getResources().getDrawable(R.drawable.my_image);
}
...
protected void onDraw(Canvas canvas) {
Rect imageBounds = canvas.getClipBounds(); // Adjust this for where you want it
mCustomImage.setBounds(imageBounds);
mCustomImage.draw(canvas);
}
}
package com.canvas;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class Keypaint extends View {
Paint p;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
p=new Paint();
Bitmap b=BitmapFactory.decodeResource(getResources(), R.drawable.icon);
p.setColor(Color.RED);
canvas.drawBitmap(b, 0, 0, p);
}
public Keypaint(Context context) {
super(context);
}
}

Categories

Resources