There are two classes: Renderer which extends View and Grid. In the onDraw method of Renderer, I want to pass Canvas to the function of Grid. Since Java passes arguments only by value the code below does not work. I mean it does not draw a rectangle on the screen and says that program has stopped on my phone. Any idea?
public class Renderer extends View {
Paint paint;
Grid grid;
public Renderer(Context context, Grid grid) {
super(context);
paint = new Paint();
this.grid = grid;
}
protected void onDraw (Canvas canvas) {
canvas.drawRGB(255, 255, 255);
grid.tempName(canvas); // removing this solves problem
invalidate();
}
}
public class Grid {
Paint paint;
public void tempName (Canvas canvas) {
paint.setStyle(Style.FILL);
paint.setColor(Color.RED);
canvas.drawRect(100, 100, 200, 200, paint);
}
}
Related
class SquareImageView extends View {
public SquareImageView(Context context) {
super(context);
init();
}
private void init() {
bitmap = Bitmap.createBitmap(500, 500, Bitmap.Config.ARGB_8888);
=mCanvas = new Canvas(bitmap);
mpaint = new Paint();
mpaint.setAntiAlias(true);
mpaint.setStyle(Paint.Style.STROKE);
mpaint.setColor(Color.RED);
mCanvas.drawColor(Color.BLUE, PorterDuff.Mode.DARKEN);
mCanvas.drawRect(100, 100, 200, 200, mpaint);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
}``
}
if i use mCanas.drawRect() inside init method then it's not drawing anything but if i use inBuilt canvas object inside OnDraw(Canvas canvas) method like this
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(100, 100, 200, 200, mpaint);
}
then rectangle is drawing and if i used mCanvas inside onDraw() then again it's not showing anything can anybody explain to me why this happening i m really get frustrated any help would be appreciated
It means that onDraw is the only drawing gate for you. https://developer.android.com/training/custom-views/custom-drawing#java
I have code that I need to improve.
Here's what's wrong: it's a little slow and choppy, meaning the lines aren't smooth and the drawing is a bit delayed.
public void touchStarted(Point point) {
if (null == drawingModePath) {
drawingModePath = new Path();
}
drawingModePath.moveTo(point.x, point.y);
}
public void touchMoved(Point point) {
drawingModePath.lineTo(point.x, point.y);
Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager()
.getDefaultDisplay().getWidth(), (int) getWindowManager()
.getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
mainDrawingView.setImageBitmap(bitmap);
// Path
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
canvas.drawPath(drawingModePath, paint);
}
public void touchEnded(Point point) {
touchMoved(point);
}
In essence what this code does is drawing a path based on touchStarted, touchMoved, and touchEnded. If someone can help me optimize this, I'd be grateful. Perhaps if I don't recreate the bitmap each time touchMoved occurs? Not sure here... not sure... I use a UIBezierPath to perform this code on iOS and it's a bit faster (and smoother). Anyway, I come to you for help. Input appreciated.
you are recreating everything every move. that will affect the performance of drawing a lot. the event triggers every 8ms (or 16ms im not sure), imagine you are reinstantiating everything every 8ms? thats tough.
so this must be in the instantiation part
Bitmap bitmap = Bitmap.createBitmap((int) getWindowManager()
.getDefaultDisplay().getWidth(), (int) getWindowManager()
.getDefaultDisplay().getHeight(), Bitmap.Config.ARGB_8888);
canvas = new Canvas(bitmap);
mainDrawingView.setImageBitmap(bitmap);
paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.WHITE);
The touchMoved() should only record the new path and call the invalidate() to make the View redraw itself resulting in calling the draw method (onDraw()).
public void touchMoved(Point point) {
drawingModePath.lineTo(point.x, point.y);
invalidate();
}
and then implement onDraw() method to do the drawing
Heres how i do the drawing interface in one of my projects:
public class SignatureView extends View {
public SignatureView(Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
// instantiating my paint object
paint = new Paint(Paint.ANTI_ALIAS_FLAG);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(5);
path = new Path();
}
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld)
{
// this is where i initialize my canvas, because in constructor, the view is not completely instantiated yet, so getting the height and width there will result in null exception.
bitmap = Bitmap.createBitmap(xNew, yNew, Bitmap.Config.ARGB_8888);
background_canvas = new Canvas(bitmap);
}
#Override
protected void onDraw(Canvas canvas)
{
// draw the new path to a buffer canvas
background_canvas.drawPath(path, paint);
// put the buffer in the real canvas
canvas.drawBitmap(bitmap, 0, 0, paint);
}
#Override
public boolean onTouchEvent(MotionEvent ev)
{
//this is like your move event, it just records the new path every move.
int action = ev.getActionMasked();
if ( action == MotionEvent.ACTION_DOWN )
{
path.moveTo(ev.getX(), ev.getY());
}
else if ( action == MotionEvent.ACTION_MOVE )
{
path.lineTo(ev.getX(), ev.getY());
// call invalidate() to make the view redraw itself, resulting in calling the onDraw() method.
invalidate();
}
else if ( action == MotionEvent.ACTION_UP )
{
onDone.method();
}
return true;
}
public void clear()
{
background_canvas.drawColor(Color.WHITE);
path.reset();
invalidate();
}
interface OnDone{
void method();
}
public void setOnDone(OnDone new_onDone)
{
onDone = new_onDone;
}
OnDone onDone;
private Paint paint;
private Bitmap bitmap;
private Canvas background_canvas;
private Path path;
public Bitmap getBitmap()
{
return bitmap;
}
}
I'm tring to draw some line and shapes on canvas and then convert it to bitmap on ImageView. I'm usin a custom class that extands "View" and on "OnDraw method i'm drawing the lines. here is my code(this class only draw simple lines) :
public class finalDraw extends View {
public finalDraw(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.BLUE);
for (int i = 0; i <100; i++) {
canvas.drawLine(xStart * i + 50 , yStart , stopX + 30 , stopY,paint);
}
invalidate();
}
}
How can i get the drawing result and show it on ImageView?
Thanks!
Found this article may help: http://www.informit.com/articles/article.aspx?p=2143148&seqNum=2
draw.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Bitmap imageBitmap = Bitmap.createBitmap(imageView.getWidth(), imageView.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(imageBitmap);
float scale = getResources().getDisplayMetrics().density;
Paint p = new Paint();
p.setColor(Color.BLUE);
p.setTextSize(24*scale);
canvas.drawText("Hello", imageView.getWidth()/2, imageView.getHeight()/2, p);
imageView.setImageBitmap(imageBitmap);
}
});
Create a Canvas with a bitmap, by Canvas(Bitmap bitmap). All draws to that canvas will in that bitmap.
i'm trying to show a Toast message with a custom view i created.
the view has a bitmap on the background and i want to write some text on it.
if I assign the bitmap to an ImageView on the main code I manage to make it show up with Toast t; (...) t.show();
but when it's the onDraw() method of my class to assign the bitmap nothing shows up.
i checked, and my view has a size of (0, 0) when created the way i transcribe under.
help please.
Main.java
Toast t = new Toast(this);
LimitView lv = new LimitView(this);
t.setView(lv);
t.setDuration(Toast.LENGTH_LONG);
t.show();
LimitView.java
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.save();
canvas.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.limit));
canvas.restore();
}
try this code:
Main.java
Context context = this;
Toast t = new Toast(context);
LeftBorder lv = new LimitView(context);
t.setView(lv);
t.setDuration(Toast.LENGTH_LONG);
t.show();
LimitView.java
public class LimitView extends View {
public LimitView (Context context) {
super(context);
}
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.button_pressed), getMatrix(), new Paint());
}
}
There are several errors here.
BitmapFactory.decodeResource(getResources(), R.drawable.limit)
This is a heavy operation and should not be on view drawing phase.
canvas.setBitmap();
This method does not drawing bitmap on canvas but setting the canvas buffer to use this bitmap.
Try some thing like this:
public class MyView extends View{
private Bitmap bitmap;
public MyView(Context context) {
super(context);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.limit);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
}
}
replace this
canvas.setBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.limit));
to this:
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.button_pressed),left,top, new Paint());
here left and right are the position of the screen.
Below is my new painter app for android.
However, it does not reflect previously drawn object.
(when i touch up the screen, it lost the shape)
To, reflect previously drawn object, I tried to use 'Bitmap.createBitmap' method but it does not work.
please help me.
public class CreativePainterActivity extends Activity {
//
//private MyView vw;
Paint mPaint;
//--Variables to store the current figure info
private float _currentStartX; //where mouse first pressed
private float _currentStartY;
private float _currentEndX; //where dragged to or released
private float _currentEndY;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
setContentView(new MyView(this));
mPaint = new Paint();
mPaint.setAntiAlias(true);
mPaint.setDither(true);
mPaint.setColor(0xFFFFFF00);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeJoin(Paint.Join.ROUND);
mPaint.setStrokeCap(Paint.Cap.ROUND);
mPaint.setStrokeWidth(8);
}
//view class
public class MyView extends View{
private Canvas mCanvas;
private Bitmap mBitmap;
private Paint mBitmapPaint;
Bitmap bm;
//private Paint mBitmapPaint;
public MyView(Context context){
super(context);
//ADDED
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
mBitmap = Bitmap.createBitmap(metrics.widthPixels, metrics.heightPixels, Bitmap.Config.ARGB_8888);
mCanvas = new Canvas(mBitmap);
mBitmapPaint = new Paint(Paint.DITHER_FLAG);
mCanvas.drawColor(0xFFFFFFFF);
bm = BitmapFactory.decodeResource(getResources(),R.drawable.ic_launcher);
}
public void onDraw(Canvas canvas){
//canvas.drawColor(Color.LTGRAY);
canvas.drawBitmap(bm, 0, 0, mBitmapPaint);
canvas.drawLine(_currentStartX, _currentStartY, _currentEndX, _currentEndY, mPaint);
}
//Methods for touch events
public boolean onTouchEvent(MotionEvent event){
if (event.getAction() == MotionEvent.ACTION_DOWN){
_currentStartX=event.getX();
_currentStartY=event.getY();
return true;
}
if(event.getAction() == MotionEvent.ACTION_MOVE){
_currentEndX=event.getX();
_currentEndY=event.getY();
invalidate();
return true;
}
return true;
}
}//end of the class MyView
}//end of the class CreativePainterActivity
You will need to know a bit more about how views are drawn. Your views won't preserve whatever is there on, after you draw again. So, you should somehow save whatever was there before, and redraw the old stuff, along with the new changes.
A simpler solution, would be to save the previous drawings to a Bitmap, and then draw that Bitmap again on the canvas first, and add new stuff.
The flow
onDraw(){
drawBitmap(bmp);
drawOtherStuff();
bmp = saveOnScreenBitmap();
}
So, each time you need to save the last drawn bitmap, and re-draw it. Hope it's more clear now.
Some sample tutorials:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/FingerPaint.html
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/graphics/TouchPaint.html
http://www.tutorialforandroid.com/2009/06/drawing-with-canvas-in-android.html