Currently on a view I have a ImageView and A custom class that draws a circle on the view. It will draw the circle on the view but it is hidden behind the image view. I know its there because when the radius is big enough I can see a small section that isn't behind the imageview. What code would bring it to the front?
EDIT: Found out that the above issue is not the problem. It seems that it is only drawing it on the portion that is reserved for the seekbar I have on the view?
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.image_process);
mDraw = new Draw(this);
addContentView(mDraw, new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
seekBar1 = (SeekBar) findViewById(R.id.seekBar1);
b = (Button) findViewById(R.id.button1);
seekBar1.setMax(500);
seekBar1.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
mDraw.setCords(500, 500, seekBar1.getProgress());
}
public void onStartTrackingTouch(SeekBar seekBar) {
mDraw.setCords(500, 500, seekBar1.getProgress());
}
public void onStopTrackingTouch(SeekBar seekBar) {
mDraw.setCords(500, 500, seekBar1.getProgress());
}
});
}
Here is the Draw class:
package org.DTS.boltsize;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.View;
public class Draw extends View {
private int x = 1;
private int y = 1;
private int r = 1;
public Draw(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public void setCords(int mx, int my, int mr ){
x = mx;
y = my;
r = mr;
}
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
System.out.println("Drew :)");
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
canvas.drawCircle(x, y, r, paint);
super.onDraw(canvas);
}
public void DrawCirlce(Canvas canvas, int x, int y, int r){
Paint paint = new Paint();
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
canvas.drawCircle(x, y, r, paint);
super.onDraw(canvas);
}
}
Here is what it looks like. That red circle should cover the entire screen.
I would draw to a seperate bitmap that you have in a different imageView in the same space as your curent bitmap possibly in a FrameLayout. You can then use .bringToFront to decide the z order.
Solved by converting source to bitmap, then drawing a circle on that bitmap and sending that final bitmap to the imageview.
Related
I have a view and I want to draw a shape on it (circle for example) after click.
I've tried to do this but there are two problems -
onDraw is never called.
Not sure the setLayoutParams(v.getLayoutParams) will give me the result I want.
#Override
public void onClick(View v) {
CircleView circle = new CircleView(GameXoActivity.this, v.getWidth(), v.getHeight());
circle.setLayoutParams(v.getLayoutParams());
circle.startDrawing();
}
CircleView:
public CircleView(Context context, int width, int height) {
super(context);
this.width = width;
this.height = height;
}
protected void startDrawing() {
this.postInvalidate();
}
#Override
protected void onDraw(Canvas canvas) {
Log.d("TAG", "onDraw");
// draw circle
}
}
}
UPDATE:
The shape is not an image and I want to draw it with animation (I didn't write the entire code).
Also, the shape is not always a circle, so using a drawable-state is not an option.
Because there is not just one view, but 9, I don't think the making 9 more on top of them would be right.
As I'm sure you'll need to customize this quite a bit, I've left things rather generic. The following example will animate a blue circle being drawn clockwise, starting from the east (0 degrees), on top of the View's content when the View is clicked.
public class CircleView extends View
{
private static final int MARGIN = 50;
Handler handler = new Handler();
Paint paint = new Paint();
RectF rect = new RectF();
boolean drawing = false;
float sweep = 0;
public CircleView(Context context)
{
this(context, null);
}
public CircleView(Context context, AttributeSet attrs)
{
super(context, attrs);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(15);
paint.setColor(Color.BLUE);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawArc(rect, 0, sweep, false, paint);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
rect.set(MARGIN, MARGIN, w - MARGIN, h - MARGIN);
}
public void startAnimation()
{
drawing = true;
handler.post(runnable);
}
Runnable runnable = new Runnable()
{
#Override
public void run()
{
sweep += 10;
if (!(sweep > 360))
{
invalidate();
handler.postDelayed(this, 20);
}
else
{
drawing = false;
sweep = 0;
}
}
};
}
In this Activity example, I used an image that most developers would already have in their project, but it can obviously be changed to your custom image. Also, for the sake of simplicity and brevity, the CircleView is set as the entire content of the Activity, but it can easily be listed in an xml layout, as well.
public class MainActivity extends Activity
{
CircleView circle;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
circle = new CircleView(this);
circle.setBackgroundResource(R.drawable.ic_launcher);
circle.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
circle.startAnimation();
}
}
);
setContentView(circle);
}
}
I suggest, create two imageView with same dimensions, set the image you want to display on image view and then make the second image invisible .
For example :
circleimage.setVisibility(View.INVISIBLE);//now its hidden(do it OnCreate)
and then show 2ndimage when 1stimage is clicked(do it in onclick of 1st image)
circleimage.setVisibility(View.VISIBLE);
If you want to mess with drawing of the object you should overridepublic void draw(Canvas canvas) and not protected void onDraw(Canvas canvas)
EDIT:Please read comments, this first statement of my answer is probably wrong
but I would use a FrameLayout or a RelativeLayout and put the images one on top of another.
Then you can play with the visibility of the overlaying image in order to hide/show it.
EDIT:
In case your circle is not an image and needs to be drawn, make your own circle class extending View and use it as a component in the FrameLayout or RelativeLayout as you would do if it were an image
I have an bitmap that I want to apply an alpha mask to. I know I can easily use Porter Duff mode to do that with another bitmap, but I want to programmatically create the alpha mask because it needs to change continually. So, I'm trying to use a path to create it, but I can't make the connection between the finished path and creating the bitmap to use from that path.
Here is my layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${relativePackage}.${activityClass}" >
<SeekBar
android:id="#+id/seekBar_percent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:progress="50" />
<ImageView
android:id="#+id/imageView_canvas"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="#+id/seekBar_percent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true" />
</RelativeLayout>
Here is my main activity:
package com.wheeler.daniel.xxx;
import android.app.Activity;
import android.os.Bundle;
import android.view.Display;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
public class MainActivity extends Activity {
PathRectangle alphaPath;
ImageView canvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_main);
canvas = (ImageView) findViewById(R.id.imageView_canvas);
canvas.post(new Runnable()
{
#Override
public void run() {
Display display = getWindowManager().getDefaultDisplay();
int canvasWidth = display.getWidth();
int canvasHeight = display.getHeight();
alphaPath = new PathRectangle(getApplicationContext(), canvas, canvasWidth, canvasHeight);
}
});
SeekBar percentBar = (SeekBar) findViewById(R.id.seekBar_percent);
percentBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser){
alphaPath.updatePercent(progress);
}
public void onStartTrackingTouch(SeekBar seekBar) {
}
public void onStopTrackingTouch(SeekBar seekBar) {
}
});
}
}
I created a class to draw my path (a basic rectangle to cover the image) called PathRectangle:
public class PathRectangle extends View {
ImageView layoutCanvas;
Bitmap canvasBitmap;
Paint paint;
Path path;
float width;
float height;
int percent;
Canvas tempCanvas;
public PathRectangle(Context context, ImageView canvasImage, float width, float height)
{
super(context);
layoutCanvas = canvasImage;
path = new Path();
paint = new Paint();
paint.setColor(Color.BLACK);
paint.setStrokeWidth(1);
paint.setStyle(Paint.Style.FILL);
this.width = width;
this.height = height;
percent = 50;
Bitmap.Config config = Bitmap.Config.ARGB_8888;
canvasBitmap = Bitmap.createBitmap((int)width, (int)height, config);
tempCanvas = new Canvas( canvasBitmap );
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
path.reset();
path.moveTo(0,0);
path.lineTo(percent, 0);
path.lineTo(percent, height);
path.lineTo(0, height);
tempCanvas.drawPath(path, paint);
layoutCanvas.setImageBitmap(canvasBitmap);
}
public void updatePercent(int newPercent)
{
percent = (int) (width * (newPercent * .01));
invalidate();
}
}
This is just my testing to generate the Bitmap, but nothing is displayed in my ImageView. I feel like by drawing the path to the tempCanvas isn't actually drawing it to the bitmap I used in the creation of the tempCanvas.
Example of what I want:
Source Bitmap
Alpha Mask to create
Result
I want to draw a stack which should raise from the bottom. For example the stack height is 400, from the height 10 it should grow till it reaches 400.
I want to do this using paint and canvas.
I don't want to do it with image view/bitmap and scale animation.
Is it possible to do this with canvas and paint? if so how to achieve it?
Thanks in advance.
You could try using something like this (have not tested myself):
Paint paint = new Paint();
paint.setColor(Color.BLACK);
for(int i = 10; i < 400; i = i + 10)
{
try
{
// To slow the for loop down, can change 100 accordingly or remove altogther
Thread.sleep(100);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
canvas.drawRect(0, i, 10, 0, paint); // this will make 10 x 10 square starting from bottom
invalidate();
}
What ever you do with canvas, even if you try for loop or invalidate, sleep, after all its drawing the shape in single stretch. I found the result in following way. May be it would be helpful for someone else, so adding the code here.
import android.os.Bundle;
import android.os.CountDownTimer;
import android.app.Activity;
import android.graphics.Color;
import android.util.Log;
import android.view.Menu;
public class AndroidDraw extends Activity {
private DrawView drawView;
private int height = 300;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_android_draw);
CountDownTimer timer = new CountDownTimer(2000, 50) {
#Override
public void onTick(long millisUntilFinished) {
height = height - 10;
drawView = new DrawView(AndroidDraw.this, height);
drawView.setBackgroundColor(Color.WHITE);
setContentView(drawView);
}
#Override
public void onFinish() {
}
};
timer.start();
}
}
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();
private int height;
public DrawView(Context context, int height) {
super(context);
this.height = height;
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.RED);
canvas.drawRect(30, height, 60, 300, paint );
}
}
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);
}
}
I'd Like to know how to draw a Line on ImageView as user swipe their finger ?
Could any body explain this ? Or perhaps any Link to get start on this.
You must have your own ImageView and override onDraw function. Use something like this
public class MyImageView extends ImageView{
public MyImageView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
canvas.drawLine(0, 0, 20, 20, p);
}
}
and in your main class create object MyImageView; and when you touch your display call the update(); function
This is a complete example of how you can draw green rectangle over another image:
package CustomWidgets;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
/**
* Allows to draw rectangle on ImageView.
*
* #author Maciej Nux Jaros
*/
public class DrawImageView extends ImageView {
private Paint currentPaint;
public boolean drawRect = false;
public float left;
public float top;
public float right;
public float bottom;
public DrawImageView(Context context, AttributeSet attrs) {
super(context, attrs);
currentPaint = new Paint();
currentPaint.setDither(true);
currentPaint.setColor(0xFF00CC00); // alpha.r.g.b
currentPaint.setStyle(Paint.Style.STROKE);
currentPaint.setStrokeJoin(Paint.Join.ROUND);
currentPaint.setStrokeCap(Paint.Cap.ROUND);
currentPaint.setStrokeWidth(2);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (drawRect)
{
canvas.drawRect(left, top, right, bottom, currentPaint);
}
}
}
When you have this defined you can replace ImageView with above View (widget) for example:
<CustomWidgets.DrawImageView
android:id="#+id/widgetMap"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:src="#drawable/map_small"
/>
Then you can use this for example in touch event of the activity that controls the layout:
mapImageView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
DrawImageView drawView = (DrawImageView) v;
// set start coords
if (event.getAction() == MotionEvent.ACTION_DOWN) {
drawView.left = event.getX();
drawView.top = event.getY();
// set end coords
} else {
drawView.right = event.getX();
drawView.bottom = event.getY();
}
// draw
drawView.invalidate();
drawView.drawRect = true;
return true;
}
});
Of course you could make some getters and setters and other Java over-engineering routines ;-).
For drawing the line the user actually drew you have to override the dispatchTouchEvent. From that event you can get the coordinates of the line and draw them in the onDraw as shown by george.
http://developer.android.com/reference/android/app/Activity.html#dispatchTouchEvent(android.view.MotionEvent)
Take a look at the ApiDemos sample FingerPaint.
By using this you can draw line on ImageView by touching on the screen.