When I use the rotate method with my canvas object, the canvas object doesn't rotate. Why is this happening? Here is my code
package com.example.hello;
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; import android.widget.LinearLayout;
public class CanvasDrawExample extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.example);
LinearLayout rl=(LinearLayout)findViewById(R.id.rl);
rl.addView(new CircleView(this));
}
public class CircleView extends View
{
public CircleView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Paint p=new Paint(Paint.ANTI_ALIAS_FLAG);
p.setStrokeWidth(100);
p.setStyle(Paint.Style.STROKE);
p.setColor(Color.BLUE);
canvas.drawRect(200, 100, 200, 100, p);
canvas.save();
canvas.rotate((float)145);
canvas.restore();
}
}
}
You save your canvas, rotate it and then restore it without doing any drawing on it. If you are trying to rotate the Rectangle 145ยบ to the right, do the following:
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
canvas.save();
canvas.rotate((float)-145,canvas.getWidth()/2,canvas.getHeight()/2);
Paint p=new Paint(Paint.ANTI_ALIAS_FLAG);
p.setStrokeWidth(100);
p.setStyle(Paint.Style.STROKE);
p.setColor(Color.BLUE);
canvas.drawRect(200, 100, 200, 100, p);
canvas.restore();
}
Also, it is not recommended to instantiate and define a Paint inside onDraw(). You should declare and define it in the constructor and then, reuse it.
In order this to work you need to comment the canvas.restore();
Related
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.. :)
So basically i want to use a xml layout, but i also want a canvas where i can have graphics performed. What i did was make a view in my xml layout as you can see below. Then in my application i made the view draw the canvas, but it is not working. I'm not sure if my method for solving this is completely wrong or what. So please just take a look at my code and tell me if you see a quick fix or if you have a better method. Thanks in advance I really appreciate it.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:id="#+id/bTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<View
android:id="#+id/vMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
that is the xml layout
package sm.view.test;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Button;
public class ViewActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
View v;
Button b;
boolean isRun =true;
SurfaceHolder ourHolder;
Thread ourThread;
Canvas canvas;
boolean isTure = true;
TheSurface ourSurfaceView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
b= (Button) findViewById(R.id.bTest);
v = (View) findViewById(R.id.vMain);
canvas = new Canvas();
ourSurfaceView = new TheSurface(this);
ourSurfaceView.setOnTouchListener(this);
v.draw(canvas);
// v.setBackgroundColor(Color.BLUE);
}
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
ourSurfaceView.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
ourSurfaceView.resume();
}
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
public class TheSurface extends SurfaceView implements Runnable{
public TheSurface(Context context) {
super(context);
ourHolder= getHolder();
}
public void resume(){
isRun= true;
ourThread = new Thread(this);
ourThread.start();
}
public void pause(){
isRun = false;
while(true){
try {
ourThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
ourThread= null;
}
public void run() {
// TODO Auto-generated method stub
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
while(isTure){
if(!ourHolder.getSurface().isValid())
continue;
//v.draw(canvas);
canvas = ourHolder.lockCanvas();
canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint);
ourHolder.unlockCanvasAndPost(canvas);
v.draw(canvas);
}
}
}
}
Start here (and this needs your input as well for the namespace portion "yourProjectNamespace"):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button android:id="#+id/bTest"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button" />
<sm.view.test.TheSurface android:id="#+id/vMain"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
In your TheSurface
Implement the overideable routines:
public TheSurface(Context C){
super(C);
// Other setup code you want here
}
public TheSurface(Context C, AttributeSet attribs){
super(C, attribs);
// Other setup code you want here
}
public TheSurface(Context C, AttributeSet attribs, int defStyle){
super(C, attribs, defStyle);
// Other setup code you want here
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint);
// Other drawing functions here!!!
}
This should get your drawing done!!!
Also in my case, you dont have to implement this as a SurfaceView, you could just implement it as a View, and it does not need to implement runnable!!!
I'm not 100% sure I understand what you are trying to do, but based on the fact that you don't seem to be doing anything with the canvas after you call View.draw() I believe you may be confused. View.draw(Canvas) draws the View onto the Canvas, it doesn't alter the view.
However, if you create the canvas from a bitmap you could then set the bitmap as an ImageView's image:
Bitmap bm = Bitmap.createBitmap( x-size, y-size, Config.ARGB_8888);
Canvas c = new Canvas(bm);
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint);
ImageView iView = (ImageView) view;
iView.setImageBitmap(bm);
However, this is a less correct way than to implement your own View:
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View view) {
((MyView)view).mContextVariable = true; //or false, etc
//you might not need this invalidate, because the click event probably causes and invalidate to be called
view.invalidate();
}
}
class MyView extends View
{
Paint myPaint;
boolean mContextVariable;
public MyView(Context context)
{
super(context);
textPaint = new Paint();
textPaint.setColor(Color.WHITE);
}
#Override
protected void onDraw(Canvas canvas)
{
if(mContextVariable)
{
canvas.drawLine(0, 0, canvas.getWidth(), canvas.getHeight(), textPaint);
}
else
{
//draw something else
}
canvas.drawText("testing", 0,0, textPaint);
}
}
I have a child view and I want the canvas that to draw a circle that has "pixels" in the negative side of the axis
canvas.drawCircle(0, 0, 50f, paint);
In order to do that i use clipRect, this works fine and i see the full cirlce.
However when I use requestLayout on the parent view and changes the x,y postion of the child view
the negative sids of the circle are not shown
please advise me what to do
here is the code:
package natan.android.TestCanvas;
import android.app.Activity;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
public class TestCanvasActivity extends Activity {
View childView;
RelativeLayout parentView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
childView = new View(this)
{
#Override
protected void onDraw(Canvas canvas) {
canvas.clipRect(-50, -50, 50, 50,android.graphics.Region.Op.REPLACE);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
canvas.drawCircle(0, 0, 50f, paint);
super.onDraw(canvas);
}
};
parentView = new RelativeLayout(this);
parentView.addView(childView);
LayoutParams layoutParms = (LayoutParams)(childView.getLayoutParams());
layoutParms.leftMargin=150;
layoutParms.topMargin=150;
setContentView(parentView);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
LayoutParams layoutParms = (LayoutParams)(childView.getLayoutParams());
layoutParms.leftMargin=100;
layoutParms.topMargin=100;
parentView.requestLayout();
return super.onTouchEvent(event);
}
}
I think i figured out a soulation
I took it from here
http://www.devdaily.com/java/jwarehouse/android/core/java/android/view/ViewGroup.java.shtml
using this line of codes fixed the problem
parentView.setClipChildren(false);
and
parentView.requestLayout();
parentView.invalidate();
Hopes this helps someone else and If someone has more insight on this problem please add it
here is the full code:
public class TestCanvasActivity extends Activity {
View childView;
RelativeLayout parentView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
childView = new View(this)
{
#Override
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
canvas.drawCircle(0, 0, 50f, paint);
super.onDraw(canvas);
}
};
parentView = new RelativeLayout(this)
{
#Override
protected void onLayout(boolean changed, int l, int t,
int r, int b) {
// TODO Auto-generated method stub
super.onLayout(changed, l, t, r, b);
}
};
parentView.setClipChildren(false);
parentView.addView(childView);
parentView.setClipChildren(false);
LayoutParams layoutParms = (LayoutParams)(childView.getLayoutParams());
layoutParms.leftMargin=150;
layoutParms.topMargin=150;
setContentView(parentView);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
LayoutParams layoutParms = (LayoutParams)(childView.getLayoutParams());
layoutParms.leftMargin=100;
layoutParms.topMargin=100;
parentView.requestLayout();
parentView.invalidate();
return super.onTouchEvent(event);
}
}
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)
I am new to Android.My application requires to redraw a canvas circle over and over again. However, the speed of redraw is less than what I want. How may I increase the same.
My code is as follows:
--> ImagePracActivity.java
package com.pkg.ImagPrac;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;
public class ImagePracActivity extends Activity {
//DrawView drawView;
movement mv;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Set full screen view
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
mv=new movement(getApplicationContext());
setContentView(mv);
mv.requestFocus();
}
}
--> movement.java
package com.pkg.ImagPrac;
import android.content.Context;
import android.content.Intent;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
public class movement extends View implements OnTouchListener{
Display display;
float x=0,y=0;
Paint paint=new Paint();
private boolean flag;
public movement(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
paint.setColor(Color.BLUE);
paint.setAntiAlias(true);
display = ((WindowManager)
context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
x = 0;
y = display.getHeight();
}
#Override
protected void onDraw(Canvas canvas) {
if(x<(display.getWidth()/2))
{
canvas.drawCircle(x++, y--, 5, paint);
}
else if(x<(display.getWidth()))
{
canvas.drawCircle(x++, y++, 5, paint);
}
this.invalidate();
}
public boolean onTouch(View arg0, MotionEvent arg1) {
// TODO Auto-generated method stub
return false;
}
}
A would advice you to use SurfaceView class instead of View, because SurfaceView faster and allows you to have all drawing logic in separate thread. Read more about SurfaceView : http://developer.android.com/guide/topics/graphics/2d-graphics.html
try this
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(5);