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);
}
}
Related
I'm trying to understand how to dynamically generate 2D graphics on Android. I haven't been able to find an example on the web of someone doing this.
My example below randomly draws 1000 lines of random colors. I'd like to see all of the lines being drawn, but I don't see anything until the setContentView() call (at which point all of the lines are already drawn).
I've tried many permutations, including moving the setContentView() to before the draw() call, and adding ourView.invalidate() inside the for loop, but in every case the screen stays white until after all the lines are drawn.
If someone can point to an example of this working, I'd be happy to go research it and add the correct answer here myself.
package com.example.graphicsdemo;
+imports
public class MainActivity extends Activity {
ImageView ourView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
draw();
setContentView(ourView);
}
public void draw() {
Bitmap blankBitmap = Bitmap.createBitmap(600,600,Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(blankBitmap);
ourView = new ImageView(this);
ourView.setImageBitmap(blankBitmap);
Paint paint = new Paint();
Random random = new Random();
for(int i = 0 ; i < 1000 ; i++) {
paint.setColor(Color.argb(255, random.nextInt(255), random.nextInt(255), random.nextInt(255)));
canvas.drawLine(random.nextInt(600), random.nextInt(600), random.nextInt(600), random.nextInt(600), paint);
}
}
}
I hope this Example will help :
first make your own View and lets call it DynamicView :
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class DynamicView extends View {
int i = 0;
public DynamicView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
Random random = new Random();
paint.setColor(Color.argb(255, random.nextInt(255),
random.nextInt(255), random.nextInt(255)));
canvas.drawLine(random.nextInt(600), random.nextInt(600),
random.nextInt(600), random.nextInt(600), paint);
if (i < 1000) {
i++;
invalidate();
}
}
}
this view will invalidate a 1000 time after each draw
now here is your main activity's onCreate method :
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DynamicView myView = new DynamicView(this);
setContentView(myView);
}
as simple as this.
Responding to your question this is a better code and more complicated but still easy to understand
All we have to do is to draw the lines on a bitmap and then draw that bitmap on the view, so the bitmap will not change and will have all previous drawn lines and still draw on it
now here is the updated code :
DynamicView
import java.util.Random;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
public class DynamicView extends View {
int i = 0;
Bitmap frame ;
Canvas frameDrawer;
Rect bounds;
Paint paint ;
Random random ;
int width , height;
public DynamicView(Context context ,int width ,int height) {
super(context);
this.width = width;
this.height = height;
frame = Bitmap.createBitmap(width,height,Bitmap.Config.ARGB_8888);
frameDrawer = new Canvas(frame);
bounds = new Rect(0 , 0, width,height);
//this initialization will make the frameDrawer draw on the frame bitmap
//always avoid allocating new objects in the draw method to optimize the performance
paint = new Paint();
random = new Random();
}
#Override
protected void onDraw(Canvas canvas) {
paint.setColor(Color.argb(255, random.nextInt(255),
random.nextInt(255), random.nextInt(255)));
//instead of drawing on the view canvas draw on the frame bitmap
frameDrawer.drawLine(random.nextInt(width), random.nextInt(height),
random.nextInt(width), random.nextInt(height), paint);
// and then draw the bitmap on the view canvas
canvas.drawBitmap(frame, null, bounds , null);
if (i < 1000) {
i++;
invalidate();
}
}
}
now the new thing in the MainActivity is that now we can take controll over the view drawing bounds but still not the view's bounds which take all the screen space (if you want to adjust the view's bounds just implement the onLayout method and enter your value's )
MainActivity
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
DynamicView myView = new DynamicView(this,320,480);
setContentView(myView);
}
}
I have a bitmap image and i want to draw a Square over this image for special position , i researched but i could not found any solution , all solutions are for create Square on empty view , please advise a i am beginner
public class DrawView extends View
{
Paint paint = new Paint();
public DrawView(Context context)
{
super(context);
}
#Override
public void onDraw(Canvas canvas)
{
Paint myPaint = new Paint();
myPaint.setColor(Color.WHITE);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(2);
canvas.drawRect(10, 10, 100, 100, myPaint);
}
}
should i convert my bit map image to convas?how?
Try this, It does what you want and some more:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.BLACK);
paint.setStrokeWidth(3);
canvas.drawRect(30, 30, 80, 80, paint);
paint.setStrokeWidth(0);
paint.setColor(Color.CYAN);
canvas.drawRect(33, 60, 77, 77, paint );
paint.setColor(Color.YELLOW);
canvas.drawRect(33, 33, 77, 60, paint );
}
}
To draw it:
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
public class StartDraw extends Activity {
DrawView drawView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
drawView = new DrawView(this);
drawView.setBackgroundColor(Color.WHITE);
setContentView(drawView);
}
}
Source: Android canvas draw rectangle
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
I want to rotate circle continuously in canvas on android. i am drawing circle using canvas and i am rotate circle continuously.it is possible,if possible how do it
with code or example can help me with greatly appreciated!
Here's my code for draw circle on canvas:
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class AnimationActivity extends Activity {
/** Called when the activity is first created. */
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
public class SampleView extends View
{
public SampleView(Context context)
{
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas)
{
Paint mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPaint.setColor(Color.RED);
canvas.drawCircle(75, 75, 75, mPaint);
}
}
}
Thanks in Advance!
You can use Animation to rotate the circle you've drawn (using Canvas). The code below works. I've modified your code and added necessary changes.
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
public class AnimationActivity extends Activity {
public class SampleView extends View {
Paint mPaint = new Paint();
private Animation anim;
public SampleView(Context context) {
super(context);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(10);
mPaint.setColor(Color.RED);
}
private void createAnimation(Canvas canvas) {
anim = new RotateAnimation(0, 360, getWidth()/2, getHeight()/2);
anim.setRepeatMode(Animation.RESTART);
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(10000L);
startAnimation(anim);
}
protected void onDraw(Canvas canvas) {
int cx = getWidth()/2; // x-coordinate of center of the screen
int cy = getHeight()/2; // y-coordinate of the center of the screen
// Starts the animation to rotate the circle.
if (anim == null)
createAnimation(canvas)
canvas.drawCircle(cx, cy, 150, mPaint); // drawing the circle.
}
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
}
Enjoy!
canvas.rotate(-rotate_angle, rotate_center_x, rotate_center_y);
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
RectF oval3 = new RectF(rotate_center_x-150, rotate_center_y-50, rotate_center_x+150, rotate_center_y+50);
canvas.drawOval(oval3, paint);
//resume original angle
canvas.rotate(rotate_angle, rotate_center_x, rotate_center_y);
For More Information, click here.. :)
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)