I am trying to redraw the custom view in onCreate() method
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
circleView = (CircleView)findViewById(R.id.circleView);
circleView.setCircle(100, 100, 25);
circleView.wrapView();
}
and custom view is :
public class CircleView extends View
{
private Paint paint = null;
private int x = 50;
private int y = 50;
private int radius = 50;
public CircleView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
public CircleView(Context context)
{
super(context);
init();
}
private void init()
{
paint = new Paint();
}
public void setCircle(int x, int y, int radius)
{
this.x = x;
this.y = y;
this.radius = radius;
init();
this.invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
paint.setColor(Color.WHITE);
canvas.drawCircle(x, y, radius, paint);
Log.e("", "radius : " + radius);
}
public void setColor(int color)
{
paint.setColor(color);
}
public void wrapView()
{
this.setLayoutParams(new RelativeLayout.LayoutParams(radius*2, radius*2));
this.invalidate();
}
}
and xml is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="#+id/layoutMain"
>
<com.pep1439.view.CircleView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/circleView" />
</RelativeLayout>
i just want to resize the circle, but failed. Help me to draw circle with any radius. How to do this. Its working fine if i use default values. It draws the circle when i remove the line circleView.setCircle(100, 100, 25);. I want to adjust circle at run time.
thanks.
You set x and y to 100 and radius to 25. Then you resize your view to radius*2, which is 50, so in the end you're drawing a circle of radius 25 at position 100,100 on a view that is only 50x50 in size. In other words: You draw your circle outside the area of your view.
Related
I have a custom view that is a circle. Here is the code for my CircleView:
public class CircleView extends View {
private static final int START_ANGLE_POINT = 90;
private final Paint paint;
private final RectF rect;
private float angle;
public CircleView(Context context, AttributeSet attrs) {
super(context, attrs);
final int strokeWidth = 40;
paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(strokeWidth);
//Circle color
paint.setColor(Color.RED);
rect = new RectF(strokeWidth, strokeWidth, 1000 + strokeWidth, 1000 + strokeWidth);
//Initial angle is zero
angle = 0;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawArc(rect, START_ANGLE_POINT, angle, false, paint);
}
public float getAngle() {
return angle;
}
public void setAngle(float angle) {
this.angle = angle;
} }
and here is how I declare it in the xml layout of an activity:
<com.my_package.ui.recording.CircleView
android:id="#+id/circleView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
All standard stuff. This is how my custom image looks like
Now, I want to place an imageView in the centre on the circleView? Does any one know how can I achieve that?
This is ideally what I would like to end up with:
Thank you in advance.
If you aren't set on using an ImageView and really just want to draw the bitmap in the center then have a look at canvas' drawBitmap method. This will allow you to draw it however/wherever you want.
I'm working on a project that requires me to draw a circle at a random location on the screen when the user touches the screen. When the touch event occurs it also needs to remove the last circle I drew, so that there can only be one circle on the screen at one time.
I have a class Circle, that I use to create a circle:
public class Circle extends View {
private final float x;
private final float y;
private final int r;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
public Circle(Context context, float x, float y, int r) {
super(context);
mPaint.setColor(0x000000);
this.x = x;
this.y = y;
this.r = r;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
canvas.drawCircle(x, y, r, mPaint);
}
}
This is the activity from which a new Circle is created. It will also monitor touch events. Right now it is drawing a circle in the upper left hand corner of the screen, but that code will need to be moved into the onTouch method. I will likely calculate the random number using Random.
public class FingerTappingActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_finger_tapping);
LinearLayout circle = (LinearLayout) findViewById(R.id.lt);
View circleView = new Circle(this, 300, 300, 150);
circleView.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
circle.addView(circleView);
circle.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return true;
}
});
}
}
I have never worked with touch events before such as these and have no idea how to go about this. Some tips would be greatly appreciated.
Do some thing like this ,
public class DrawCircles extends View {
private float x = 100;
private float y = 100;
private int r = 50;
private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setStyle(Paint.Style.FILL);
mPaint.setColor(Color.RED);
canvas.drawCircle(x, y, r, mPaint);
}
public DrawCircles(Context context) {
super(context);
init();
}
public DrawCircles(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public DrawCircles(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
void init() {
mPaint.setColor(0x000000);
// logic for random call here;
}
Random random = new Random();
void generateRandom() {
int minRadius = 100;
int w = getWidth();
int h = getHeight();
this.x = random.nextInt(w);
this.y = random.nextInt(h);
this.r = minRadius + random.nextInt(100);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
generateRandom();
invalidate();
return super.onTouchEvent(event);
}
}
This view will draw random circles inside the view . make some adjustments for generating x & y coordinates . add this view to xml then it will work.
I wanted to show map inside a circle view where circle's outside area filled with a color. I referred a post Draw transparent circle filled outside. But now the problem is touch events. Map can be touched through outside circle view while I need map can be touched (zoom or move) only form inside Circle view (where the map is visible).
What I tried,
setEnabled=false
clickable=false
but still map is touched from outside circle view.
Is that possible to achieve that map can be touched from inside circle view.
public class RadiusOverlayView extends LinearLayout {
private Bitmap windowFrame;
public RadiusOverlayView(Context context) {
super(context);
}
public RadiusOverlayView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (windowFrame == null) {
createWindowFrame(); // Lazy creation of the window frame, this is needed as we don't know the width & height of the screen until draw time
}
canvas.drawBitmap(windowFrame, 0, 0, null);
}
#Override
public boolean isEnabled() {
return false;
}
#Override
public boolean isClickable() {
return false;
}
protected void createWindowFrame() {
windowFrame = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); // Create a new image we will draw over the map
Canvas osCanvas = new Canvas(windowFrame); // Create a canvas to draw onto the new image
RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Anti alias allows for smooth corners
paint.setColor(Color.CYAN); // This is the color of your activity background
osCanvas.drawRect(outerRectangle, paint);
//paint.setColor(Color.TRANSPARENT); // An obvious color to help debugging
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // A out B http://en.wikipedia.org/wiki/File:Alpha_compositing.svg
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
float radius = Math.min(getWidth(), getHeight()) / 2 - 50;
osCanvas.drawCircle(centerX, centerY, radius, paint);
}
#Override
public boolean isInEditMode() {
return true;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
windowFrame = null; // If the layout changes null our frame so it can be recreated with the new width and height
}
}
XML layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--loading map in container-->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<mypackage.RadiusOverlayView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Result:
Any help will be appreciated.
You could set a View.OnTouchListener to your RadiusOverlayView and calculate whether the RadiusOverlayView needs to manage the touch events or not.
In this example I calculate this by testing if the RadiusOverlayView color touched is != 0 (maybe you want to improve this):
final RadiusOverlayView radiusOverlayView = (RadiusOverlayView) findViewById(R.id.radiusView);
radiusOverlayView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
view.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bmp.getPixel((int) motionEvent.getX(), (int) motionEvent.getY()) != 0;
}
});
How can i make a layout look like following snap in the case i don't want to use background image.
Create a nine patch image of a single image. Following link is helpful to you for generate nine patch image.
https://romannurik.github.io/AndroidAssetStudio/nine-patches.html
You can create an ImageView like that triangle and put it in the place you need.
Have a look how you can create triangle using xml: Android triangle (arrow) defined as an XML shape
Or even you can create a TextView:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="▼"/>
and put it in the place.
Unicode for the triangle: link
Use below code in Relative Layout. Hope it helps you.
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableRight="#drawable/triangleImage"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"/>
You can also draw custom view:
public class MyBackground extends View{
private Path path = new Path();
private Paint paint = new Paint();
public MyBackground(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyBackground(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
}
public MyBackground(Context context) {
this(context, null);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.GRAY);
int triangleSide = getWidth() / 10; // triangle is 1/10-th of side
int offsetFromRightSide = triangleSide;
int startX = getWidth() - triangleSide - offsetFromRightSide;
path.reset();
path.moveTo(startX, 0);
path.lineTo(startX + triangleSide/2, triangleSide/2);
path.lineTo(startX + triangleSide, 0);
canvas.drawPath(path, paint);
}
}
and use it like this
<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"
android:background="#drawable/background"
tools:context=".MainActivity">
<your.package.name.MyBackground
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Or there is one more "code way". Create custom background Drawable
public class Background extends Drawable {
private Path path = new Path();
private Paint paint = new Paint();
public Background(){
paint.setColor(Color.WHITE);
paint.setStyle(Paint.Style.FILL);
paint.setAntiAlias(true);
}
#Override
public void draw(Canvas canvas) {
int triangleSide = getBounds().width() / 10; // triangle is 1/10-th of side
int offsetFromRightSide = triangleSide;
int startX = getBounds().width() - triangleSide - offsetFromRightSide;
path.reset();
path.moveTo(startX, 0);
path.lineTo(startX + triangleSide/2, triangleSide/2);
path.lineTo(startX + triangleSide, 0);
canvas.drawColor(Color.GRAY);
canvas.drawPath(path, paint);
}
#Override public void setAlpha(int alpha) {}
#Override public void setColorFilter(ColorFilter cf) {}
#Override public int getOpacity() {return 0;}
}
And use it like this:
RelativeLayout layout = (RelativeLayout) findViewById(R.id.root);
layout.setBackgroundDrawable(new Background());
I'm doing a simple drum set app where the users can click the button to make the corresponding sound and draw a circle on the canvas at a random location. For the canvas, I created a custom view called CanvasView, then I implements that CanvasView into the MainActivity, so I can control that View each time the buttons are clicked with OnClickListener in the MainActivity.
However, I don't know how to actually control (draw a circle on) the CanvasView using the OnClickListener. I need help on this part
This is my code for the MainActivity class:
public class MainActivity extends Activity {
//setup variables for soundpool
.
.
.
//implements CanvasView
CanvasView mCanvasView;
//set up soundID for each sound
.
.
.
//setup buttons
Button mKick;
.
.
.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//set up soundpools
.
.
.
//example, the kick drum button
//kick drum
mKick = (Button) findViewById(R.id.kick);
mKick.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
soundPool.play(kick, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
// mCanvasView.draw(CanvasView.mCanvas);
}
});
This is my code for the CanvasView
public class CanvasView extends View {
public Paint mPaint;
public static Canvas mCanvas;
//constructor
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
}
//what I want to draw is here
protected void onDraw(Canvas canvas) {
mCanvas = canvas;
super.onDraw(mCanvas);
canvas.drawColor(Color.GRAY);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Style.STROKE);
mPaint.setAntiAlias(true);
canvas.drawCircle(30, 30, radius, mPaint);
This is my layout XML for the MainActivity
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/GridLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:columnCount="3"
android:orientation="horizontal"
android:rowCount="5"
tools:context=".GridXMLActivity" >
<Button
android:id="#+id/kick"
android:layout_width="78dp"
android:layout_height="wrap_content"
android:layout_column="1"
android:layout_gravity="center_horizontal|fill_vertical"
android:layout_row="3"
android:text="Kick" />
<com.example.virtualdrumset.CanvasView
android:id="#+id/canvasView1"
android:layout_width="143dp"
android:layout_height="169dp"
android:layout_column="1"
android:layout_gravity="left|top"
android:layout_row="0" />
I deeply apologize for any inconvenience or mistakes. This is my first time asking question.
You shouldn't call onDraw function of the canvas directly from the activity. Instead make a public method in the canvas view and write your logic there and call invalidate at the end. This calls onDraw method and contents are drawn on the screen again according to your new logic.
If you want a circle to be drawn at random locations on screen each time button is clicked you can do something like this
public class CanvasView extends View {
public Paint mPaint;
public static Canvas mCanvas;
private int mPivotX = 0;
private int mPivotY = 0;
private int radius = 60;
//constructor
public CanvasView(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
}
public void drawCircle() {
int minX = radius * 2;
int maxX = getWidth() - (radius *2 );
int minY = radius * 2;
int maxY = getHeight() - (radius *2 );
//Generate random numbers for x and y locations of the circle on screen
Random random = new Random();
mPivotX = random.nextInt(maxX - minX + 1) + minX;
mPivotY = random.nextInt(maxY - minY + 1) + minY;
//important. Refreshes the view by calling onDraw function
invalidate();
}
//what I want to draw is here
protected void onDraw(Canvas canvas) {
mCanvas = canvas;
super.onDraw(mCanvas);
canvas.drawColor(Color.GRAY);
mPaint.setColor(Color.BLUE);
mPaint.setStyle(Style.STROKE);
mPaint.setAntiAlias(true);
canvas.drawCircle(mPivotX, mPivotY, radius, mPaint);
}
}
And then onButtonClick
mKick.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
soundPool.play(kick, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
mCanvasView.drawCircle()
}
Hope it helps!