Draw rectangle multiple times in new position not working - android

Each time I create a new rectangle with this code it does not work, I can only draw to a specified position, if I use a variable to change position on execution it does not draw anything.
Inside a Asynctask method:
rect = new desenho(main.this, x, y);
Which calls this:
public class desenho extends View{
int x, y;
Paint mPaint = new Paint();
public desenho(Context context, int x, int y) {
super(context);
this.x = x;
this.y = y;
mPaint.setStrokeWidth(3);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLACK);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(width, y);
}
#Override
protected void onDraw(Canvas c) {
// TODO Auto-generated method stub
super.onDraw(c);
c.drawRect(5, y, width-5, y+x, mPaint);
}
}

It seems to me that you want the size to be independent of position. For that, these requirements must be met in your Canvas.drawRect(left, top, right, bottom, paint):
left - right = a
top - bottom = b
where a, b are constant. Example:
c.drawRect(xPos, yPos, xPos + width - 1, yPos + height - 1, mPaint);
You see in this example that
left - right = xPos - (xPos + width - 1) = 1 - width
top - bottom = yPos - (yPos + height - 1) = 1 - height
Both are constant → size is constant.

Related

diamond shape in android studio

I'm having trouble using a path to create a diamond shape on Android studio. It looks like I have a little more than half of the diamond, but I don't know what I am doing wrong and why the rest of it isn't printing out. I've been trying to change my code for hours and nothing is working. Could anyone please point out what I am doing wrong? Here is my code so far:
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.drawable.shapes.Shape;
public class Diamond extends Shape {
private int strokeWidth;
private final int fillColor;
private int strokeColor;
private Path path;
private Paint strokePaint;
private Paint fillPaint;
public Diamond(int strokeWidth, int fillColor, int strokeColor) {
this.strokeWidth = strokeWidth;
this.fillColor = fillColor;
this.strokeColor = strokeColor;
this.strokePaint = new Paint();
this.strokePaint.setStyle(Paint.Style.STROKE);
this.strokePaint.setStrokeWidth(strokeWidth);
this.fillPaint = new Paint();
this.fillPaint.setStyle(Paint.Style.FILL);
this.fillPaint.setColor(fillColor);
}
#Override
public void draw(Canvas canvas, Paint paint) {
canvas.drawPath(path, fillPaint);
canvas.drawPath(path, strokePaint);
}
#Override
protected void onResize(float width, float height) {
super.onResize(width, height);
path = new Path();
path.moveTo(width/2, 0);
path.lineTo(width, height);
path.lineTo(width/2, height*4);
path.lineTo(0, height);
path.close();
}
}
I think you should just need to change path.lineTo(width/2, height*4); to instead multiply the height by 2 as in path.lineTo(width/2, height*2);, using 4 makes the bottom half skewed longer than the top. There's also an example on this page drawing a rhombus which you can modify to draw a diamond by using the full width like:
public void drawRhombus(Canvas canvas, Paint paint, int x, int y, int width) {
int halfWidth = width / 2;
Path path = new Path();
path.moveTo(x, y + width); // Top
path.lineTo(x - halfWidth, y); // Left
path.lineTo(x, y - width); // Bottom
path.lineTo(x + halfWidth, y); // Right
path.lineTo(x, y + width); // Back to Top
path.close();
canvas.drawPath(path, paint);
}

Canvas draw circles horizontally in android view

I'm trying to draw 4 circles horizontally in a view. But the problem is I see only 3 half circles. Circles are not being drawn properly. What is wrong with below code?
CircleView.java
public class CircleView extends View
{
private int radius;
private Paint blackPaint = new Paint();
float eachDotWidth;
float x = 0;
float circleRadius;
float width, height;
public CircleView(Context context)
{
this(context, null);
}
public CircleView(Context context, AttributeSet attrs)
{
super(context, attrs);
blackPaint.setStyle(Paint.Style.STROKE);
blackPaint.setColor(Color.BLACK);
blackPaint.setStrokeWidth(5f);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh)
{
super.onSizeChanged(w, h, oldw, oldh);
calculateDimensions();
}
private void calculateDimensions()
{
width = getWidth() ;
height = getHeight();
invalidate();
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
width = getWidth();
height = getHeight();
eachDotWidth = getWidth()/5;
circleRadius = getHeight()/2;
canvas.drawColor(Color.WHITE);
for(int i=0; i < 4; i++) {
x=(i*eachDotWidth)-circleRadius;
canvas.drawCircle(x, 2*circleRadius, circleRadius/2, blackPaint);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
FrameLayout circleLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
circleLayout = (FrameLayout) findViewById(R.id.circle_layout);
CircleView circleView = new CircleView(this);
circleLayout.addView(circleView, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
}
}
Please help me find and resolve the issue. Thanks.
You can create vertically circles:
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
width = getWidth();
height = getHeight();
eachDotWidth = getWidth()/8;
circleRadius = getHeight()/2;
canvas.drawColor(Color.WHITE);
for(int i=0; i < 4; i++) {
x=(2*i*eachDotWidth)+eachDotWidth;
canvas.drawCircle(x, eachDotWidth, eachDotWidth, blackPaint);
}
}
Also you can create horizontally circles:
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
width = getWidth();
height = getHeight();
eachDotWidth = getWidth()/8;
circleRadius = getHeight()/8;
canvas.drawColor(Color.WHITE);
for(int i=0; i < 4; i++) {
x=(2*i*circleRadius)+circleRadius;
canvas.drawCircle(circleRadius, x, circleRadius, blackPaint);
}
}
And also you can create diagonal circles (create y variable):
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
width = getWidth();
height = getHeight();
eachDotWidth = getWidth()/8;
circleRadius = getHeight()/8;
canvas.drawColor(Color.WHITE);
for(int i=0; i < 4; i++) {
y=(2*i*circleRadius)+circleRadius;
x=(2*i*eachDotWidth)+eachDotWidth;
canvas.drawCircle(x, y, circleRadius, blackPaint);
}
}
I think you need to revise the code drawing the circles. I don't know why you, for example, have separate values for a circle's radius and a "dot's width". I suggest that you count only with an each circle's (~ dot's) radius and add some spacing in between them to compound the width to suit your needs.
Try something like this (it draws four equal circles at zero coordinates across the canvas' width, but it doesn't account for the stroke's thickness):
// we want four equal circles across the whole width, so each circle's radius will be equal to 'width/(2*4)'
circleRadius = width/8;
// zero spacing for this example, but it can be defined
int spacingPx = 0;
canvas.drawColor(Color.WHITE);
for(int i=0; i < 4; i++) {
// the x-coordinate of each circle's middle will be a circle's radius offset by the width of the circles previously drawn plus a single spacing width multiplied by the number of the circles already drawn
x=(i*2*circleRadius) + circleRadius + i*spacingPx;
// we just simply pass the values – calculated x coordinate, y coordinate (here we want to have the circle's top at 0, so we need to set its middle y-coordinate to the value of its radius), the circle's radius and the Paint object that you already defined
canvas.drawCircle(x, circleRadius, circleRadius, blackPaint);
}
Here's how it looks like
If you want to customize it more to your needs, please specify how exactly would you like the circles to be drawn.
Using a Path and a RectF is more flexible if you want to draw shapes, you can take a look at this tutorial :
http://raphaelfavero.github.io/Creating_Animated_Custom_View/

How to draw a circle which fills the entire changed view

i am trying to draw a circle which fills the entire changed view (for any device).
Circle will fill as much screen space as possible (without deforming its circular shape).
Rotating the screen orientation will adjust the clock view.
lass Circles extends View
{
private int x = 0;
private int y = 0;
private final int rsec=240;
private final int rmin=200;
private final int rhrs=150;
private Date date;
int viewWidth = 0;
int viewHeight = 0;
int Radius = 0;
public Circles(Context context)
{
super(context);
}
public void onDraw(final Canvas canvas)
{
super.onDraw(canvas);
String msg = "width: " + viewWidth + "height: " + viewHeight;
System.out.println(msg);
x = viewWidth / 2 ;
y = viewHeight / 2 ;
//2 Circels
Paint p1 = new Paint();
p1.setColor(Color.BLUE);
p1.setStyle(Style.STROKE);
Paint p2 = new Paint();
p2.setColor(Color.RED);
p2.setStyle(Style.FILL);
canvas.drawCircle(x, y , Radius, p1);
canvas.drawCircle(x , y , 20, p2);
#Override
protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld){
super.onSizeChanged(xNew, yNew, xOld, yOld);
viewWidth = xNew;
viewHeight = yNew;
/*
these viewWidth and viewHeight variables
are the global int variables
that were declared above
*/
this.setMeasuredDimension( viewWidth, viewHeight);
Radius=Math.min(viewWidth, viewHeight);
}
the 1st circle , is not display at all when the phone is vertical , but when rotate him horizontal , the edges of the circke can be seen .
is nayone can tell me whats wrong with the onSizeChanged i used. ?
move this line
this.setMeasuredDimension( viewWidth, viewHeight);
after this line
Radius=Math.min(viewWidth, viewHeight);
and see if this works.

Moving a View into AsyncTask

I have a class (SpotDetails) which includes a fragment which is drawn programically. Untill now i've had the fragment drawing class (WindRose) as a child of the main class.
What i would like to do is to move the WindRose class into a AsynTask for better User Experience. Now the Application is suffering from too much work on the main thread.
Code to implement the WindRose :
WindRose windRose = new WindRose(SpotDetails.this);
//Add a new windRose (Which is created under)
FrameLayout.addView(windRose);
WindRose code :
public class WindRose extends View {
public WindRose(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float height = (float) getHeight();
float width = (float) getWidth();
float radius;
if (width > height) {
radius = height / 2;
} else {
radius = width / 2;
}
// radius = (height )/ 2;
Path path = new Path();
path.addCircle(width, height, radius, Path.Direction.CCW);
// / 2
Resources resources = getResources();
int color = resources.getColor(R.color.green_back);
Paint paint = new Paint();
paint.setColor(color);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.FILL);
float center_x, center_y;
center_x = width / 2;
center_y = height / 2;
final RectF oval = new RectF();
//Formulas :
//SD = Start Degree
//ED = End Degree
//If cakepiece passes 0 (East)
//SD, 360-(SD+ED)
//Else :
//SD, (ED-SD)
oval.set(center_x - radius, center_y - radius, center_x + radius, center_y + radius);
if (End > Start) {
canvas.drawArc(oval, Start, (End - Start), true, paint);
} else if (End < Start) {
canvas.drawArc(oval, Start, ((360 - Start) + End), true, paint);
}
}
}
Im not sure if i explained things right so please tell me if things are unclear :)
I have tried to do this :
public class WindRose extends Activity {
float Start, End;
Context context;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
public View DrawRose (Context context){
this.context = context;
WindRoseDrawer windRoseDrawer = new WindRoseDrawer(context);
return null; //What should i return here ?
}
private class DrawWindRose extends AsyncTask<String, Void, Void> {
#Override
protected void onPreExecute() {
super.onPreExecute();
}
#Override
protected Void doInBackground(String... strings) {
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
super.onPostExecute(aVoid);
}
}
public class WindRoseDrawer extends View {
public WindRoseDrawer(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
float height = (float) getHeight();
float width = (float) getWidth();
float radius;
if (width > height) {
radius = height / 2;
} else {
radius = width / 2;
}
// radius = (height )/ 2;
Path path = new Path();
path.addCircle(width, height, radius, Path.Direction.CCW);
// / 2
Resources resources = getResources();
int color = resources.getColor(R.color.green_back);
Paint paint = new Paint();
paint.setColor(color);
paint.setStrokeWidth(5);
paint.setStyle(Paint.Style.FILL);
float center_x, center_y;
center_x = width / 2;
center_y = height / 2;
final RectF oval = new RectF();
//Formulas :
//SD = Start Degree
//ED = End Degree
//If cakepiece passes 0 (East)
//SD, 360-(SD+ED)
//Else :
//SD, (ED-SD)
oval.set(center_x - radius, center_y - radius, center_x + radius, center_y + radius);
if (End > Start) {
canvas.drawArc(oval, Start, (End - Start), true, paint);
} else if (End < Start) {
canvas.drawArc(oval, Start, ((360 - Start) + End), true, paint);
}
}
}
}
But how should i implement this back to the SpotDetails ? And what should i return from DrawRose ?
You should draw only in the UI thread. You can't draw in the background if using the Draw inheritance method from View. Better to use a SurfaceView with lock / unlock canvas. It will use an optimized algorithm which allows for background drawing.
#Override
public void run() {
while(locker){
//checks if the lockCanvas() method will be success,and if not, will check this statement again
if(!holder.getSurface().isValid()){
continue;
}
/** Start editing pixels in this surface.*/
Canvas canvas = holder.lockCanvas();
//ALL PAINT-JOB MAKE IN draw(canvas); method.
draw(canvas);
// End of painting to canvas. system will paint with this canvas,to the surface.
holder.unlockCanvasAndPost(canvas);
}
}

Creating game gravity in Android?

I am trying to create in game gravity in Android. I created an update method, a display, and gravity. Right now the app does not force close, but the ball just doesn't move. Do I need to use a canvas for the .getHieght() and .getWidth() methods?
public class MainActivity extends Activity {
private int c = Color.YELLOW;
private Canvas g;
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
draw();
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
// draws the ball
public void draw ()
{
Display display = getWindowManager().getDefaultDisplay();
int width = display.getHeight();
int height = display.getWidth();
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
g = new Canvas(bitmap);
g.drawColor(c);
Paint paint = new Paint();
paint.setColor(Color.BLACK);
g.drawCircle(50, 10, 25, paint); //Put your values
update();
// In order to display this image, we need to create a new ImageView that we can display.
ImageView imageView = new ImageView(this);
// Set this ImageView's bitmap to ours
imageView.setImageBitmap(bitmap);
// Create a simple layout and add imageview to it.
RelativeLayout layout = new RelativeLayout(this);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.CENTER_IN_PARENT);
layout.addView(imageView, params);
layout.setBackgroundColor(Color.BLACK);
// Show layout in activity.
setContentView(layout);
}
private void update(){
// wall collisions;
if (x + dx > sp.getWidth() - radius - 1) {
x = sp.getWidth() - radius - 1;
// bounce off right wall;
dx = -dx;
// bounce off left wall;
} else if (x + dx < 0 + radius) {
x = 0 + radius;
dx = -dx;
} else {
x += dx;
}
// friction;
if (y == sp.getHeight() - radius - 1) {
dx *= xFriction;
if (Math.abs(dx) < .8) {
dx = 0;
}
}
// gravity;
if (y > sp.getHeight() - radius - 1) {
y = sp.getHeight() - radius - 1;
dy *= energyloss;
dy = -dy;
} else {
// velocity formula;
dy += gravity * dt;
// position formula;
y += dy * dt + .5 * gravity * dt * dt;
}
}
}
In my opinion, your approach is all wrong and is creating complexity.
Here's how I'd do it. Create two classes, one for the ball and one for somewhere to draw it. Something along these lines:
public class Ball{
private int radius;
private int xPosition;
private int yPosition;
private int color;
private Paint paint;
public Ball(int x, int y, int radius, int color)
{
this.xPosition = x; this.yPosition = y; this.radius = radius;
paint = new Paint(color);
}
void moveBall(int x, int y){
xPosition = x; yPosition =y;
}
void onDraw(Canvas canvas){
canvas.drawCircle(x, y, radius, paint);
}
}
Now somewhere to draw it.
public class Playground extends ImageView{
public Ball ball;
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
if (ball != null ){
ball.onDraw(canvas);
}
}
}
In your activity, probably in onStart():
imageView.ball = new Ball(startX, startY, radius, Color.BLUE);
Move your "update" method into the ball class also and call ball.update() on a timer (or whenever you want to update it).
Replace the ImageView in your layout with the Playground class (first name that popped into my head).
Override onMeasure() in the ImageView extension to get height and width of the "playground".
That gives you the basics. I wrote this off the top of my head so please excuse typos etc
Also, review the answers given to you in your multiple previous questions on this topic and read the Android documentation on extending View classes, onDraw and onMeasure.
I think you're drawing just once, you may add a timer to trigger the draw() method

Categories

Resources