create/change/delete/undo number of different shapes on canvas, onClick() of button
up vote
1
down vote
favorite
I'm creating android application for shapes on canvas onClick of button.
What I want:
I have three buttons 'Square','Circle','Triangle'.
Each time I tap on button and object of that shape will be created & displayed in a random position on one canvas.(done)
On tap of each shape will cause it to become another shape.
tapping on a square will make it a circle
tapping on a circle will make it a triangle
tapping on a triangle will make it a square (done)
On long tap on a shape can delete the shape.(done)
How to implement undo functionality!
Tried and Error: To achieve this functionality I tried so far following code in which I can create one shape on click of button using bitmap in java and image view in xml.
Update_29/10: I work on same code and create multiple shapes on canvas using dynamic relative layout adding views.
My Question:
Is this right way(bitmap and imageview) to create shape on canvas by clicking on button?
I can create multiple shapes on canvas now but every time I'm creating new canvas instance!any other way to achieve this?
Update_29_10:
How to get click of shape so I can delete shape and undo functionality as well.
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/relative4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_above="@+id/btnCircle"
android:background="@color/colorAccent">
</RelativeLayout>
<Button
android:id="@+id/btnSquare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="@string/square" />
<Button
android:id="@+id/btnCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnSquare"
android:text="@string/circle" />
<Button
android:id="@+id/btnTriangle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnCircle"
android:text="@string/triangle" />
<Button
android:id="@+id/btnUndo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/btnTriangle"
android:layout_alignParentBottom="true"
android:text="@string/undo" />
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Context mContext;
private Resources mResources;
private RelativeLayout mRelativeLayout;
private Button btnSquare, btnCircle, btnTriangle,btnUndo,btnState;
private int mSuareCount=0,mCircleCount=0,mTriangelCount=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
mContext = getApplicationContext();
mResources = getResources();
mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
btnSquare = (Button) findViewById(R.id.btnSquare);
btnCircle = (Button)findViewById(R.id.btnCircle);
btnTriangle = (Button)findViewById(R.id.btnTriangle);
btnUndo=(Button)findViewById(R.id.btnUndo);
setOnClickListeners();
}
private void setOnClickListeners() {
btnSquare.setOnClickListener(this);
btnCircle.setOnClickListener(this);
btnTriangle.setOnClickListener(this);
btnUndo.setOnClickListener(this);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnSquare:
drawSquare(null);
mSuareCount++;
break;
case R.id.btnCircle:
drawCircle(null);
mCircleCount++;
break;
case R.id.btnTriangle:
drawTriangle(null);
mTriangelCount++;
break;
case R.id.btnUndo:
break;
}
}
private void drawSquare(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.LTGRAY);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
int padding = 50;
Rect rectangle = new Rect(
padding, // Left
padding, // Top
canvas.getWidth() - padding, // Right
canvas.getHeight() - padding // Bottom
);
canvas.drawRect(rectangle, paint);
addViews(bitmap,imageView,1);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
}
});
}
private void drawCircle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
int radius = Math.min(canvas.getWidth(), canvas.getHeight() / 2);
int padding = 5;
canvas.drawCircle(
canvas.getWidth() / 2, // cx
canvas.getHeight() / 2, // cy
radius - padding, // Radius
paint // Paint
);
addViews(bitmap,imageView,2);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
}
});
}
private void drawTriangle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
500, // Width
500, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(),
bitmap.getHeight());
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
Point point1_draw = new Point(90, 0);
Point point2_draw = new Point(0, 180);
Point point3_draw = new Point(180, 180);
Path path = new Path();
path.moveTo(point1_draw.x, point1_draw.y);
path.lineTo(point2_draw.x, point2_draw.y);
path.lineTo(point3_draw.x, point3_draw.y);
path.lineTo(point1_draw.x, point1_draw.y);
path.close();
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#3F51B5"));
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//addViews(bitmap,imageView);
addViews(bitmap,imageView,3);
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawSquare(finalImageView);
mSuareCount++;
mTriangelCount--;
}
});
}
private void addViews(Bitmap bitmap, ImageView imageView, final int value) {
final int min = 20;
final int max = 80;
Drawable d = getResources().getDrawable(R.mipmap.ic_launcher_round);
final int w = d.getIntrinsicWidth();
final int random = new Random().nextInt((max - min) + 1) + min;
RelativeLayout relative4 = (RelativeLayout) findViewById(R.id.relative4);
int width = relative4.getMeasuredWidth();
int height = relative4.getMeasuredHeight();
if (imageView == null) {
imageView = new ImageView(this);
}
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
params.setMargins(new Random().nextInt((width - 0) + 1), new Random().nextInt((height - 0) + 1), 10, 10);
imageView.setLayoutParams(params);
imageView.setImageBitmap(bitmap);
if (imageView != null) {
ViewGroup parent = (ViewGroup) imageView.getParent();
if (parent != null) {
parent.removeView(imageView);
}
}
relative4.addView(imageView);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (value) {
case 1:
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
break;
case 2:
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
break;
case 3:
drawSquare(finalImageView);
mTriangelCount--;
mSuareCount++;
break;
}
}
});
imageView.setOnLongClickListener(new View.OnLongClickListener(){
@Override
public boolean onLongClick(View v) {
switch (value) {
case 1:
relative4.removeView(finalImageView);
mSquareCount--;
break;
case 2:
relative4.removeView(finalImageView);
mCircleCount--;
break;
case 3:
relative4.removeView(finalImageView);
mTriangleCount--;
break;
}
return true;
});
}
}
android canvas shapes buttonclick ondraw
|
show 8 more comments
up vote
1
down vote
favorite
I'm creating android application for shapes on canvas onClick of button.
What I want:
I have three buttons 'Square','Circle','Triangle'.
Each time I tap on button and object of that shape will be created & displayed in a random position on one canvas.(done)
On tap of each shape will cause it to become another shape.
tapping on a square will make it a circle
tapping on a circle will make it a triangle
tapping on a triangle will make it a square (done)
On long tap on a shape can delete the shape.(done)
How to implement undo functionality!
Tried and Error: To achieve this functionality I tried so far following code in which I can create one shape on click of button using bitmap in java and image view in xml.
Update_29/10: I work on same code and create multiple shapes on canvas using dynamic relative layout adding views.
My Question:
Is this right way(bitmap and imageview) to create shape on canvas by clicking on button?
I can create multiple shapes on canvas now but every time I'm creating new canvas instance!any other way to achieve this?
Update_29_10:
How to get click of shape so I can delete shape and undo functionality as well.
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/relative4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_above="@+id/btnCircle"
android:background="@color/colorAccent">
</RelativeLayout>
<Button
android:id="@+id/btnSquare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="@string/square" />
<Button
android:id="@+id/btnCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnSquare"
android:text="@string/circle" />
<Button
android:id="@+id/btnTriangle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnCircle"
android:text="@string/triangle" />
<Button
android:id="@+id/btnUndo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/btnTriangle"
android:layout_alignParentBottom="true"
android:text="@string/undo" />
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Context mContext;
private Resources mResources;
private RelativeLayout mRelativeLayout;
private Button btnSquare, btnCircle, btnTriangle,btnUndo,btnState;
private int mSuareCount=0,mCircleCount=0,mTriangelCount=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
mContext = getApplicationContext();
mResources = getResources();
mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
btnSquare = (Button) findViewById(R.id.btnSquare);
btnCircle = (Button)findViewById(R.id.btnCircle);
btnTriangle = (Button)findViewById(R.id.btnTriangle);
btnUndo=(Button)findViewById(R.id.btnUndo);
setOnClickListeners();
}
private void setOnClickListeners() {
btnSquare.setOnClickListener(this);
btnCircle.setOnClickListener(this);
btnTriangle.setOnClickListener(this);
btnUndo.setOnClickListener(this);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnSquare:
drawSquare(null);
mSuareCount++;
break;
case R.id.btnCircle:
drawCircle(null);
mCircleCount++;
break;
case R.id.btnTriangle:
drawTriangle(null);
mTriangelCount++;
break;
case R.id.btnUndo:
break;
}
}
private void drawSquare(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.LTGRAY);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
int padding = 50;
Rect rectangle = new Rect(
padding, // Left
padding, // Top
canvas.getWidth() - padding, // Right
canvas.getHeight() - padding // Bottom
);
canvas.drawRect(rectangle, paint);
addViews(bitmap,imageView,1);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
}
});
}
private void drawCircle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
int radius = Math.min(canvas.getWidth(), canvas.getHeight() / 2);
int padding = 5;
canvas.drawCircle(
canvas.getWidth() / 2, // cx
canvas.getHeight() / 2, // cy
radius - padding, // Radius
paint // Paint
);
addViews(bitmap,imageView,2);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
}
});
}
private void drawTriangle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
500, // Width
500, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(),
bitmap.getHeight());
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
Point point1_draw = new Point(90, 0);
Point point2_draw = new Point(0, 180);
Point point3_draw = new Point(180, 180);
Path path = new Path();
path.moveTo(point1_draw.x, point1_draw.y);
path.lineTo(point2_draw.x, point2_draw.y);
path.lineTo(point3_draw.x, point3_draw.y);
path.lineTo(point1_draw.x, point1_draw.y);
path.close();
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#3F51B5"));
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//addViews(bitmap,imageView);
addViews(bitmap,imageView,3);
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawSquare(finalImageView);
mSuareCount++;
mTriangelCount--;
}
});
}
private void addViews(Bitmap bitmap, ImageView imageView, final int value) {
final int min = 20;
final int max = 80;
Drawable d = getResources().getDrawable(R.mipmap.ic_launcher_round);
final int w = d.getIntrinsicWidth();
final int random = new Random().nextInt((max - min) + 1) + min;
RelativeLayout relative4 = (RelativeLayout) findViewById(R.id.relative4);
int width = relative4.getMeasuredWidth();
int height = relative4.getMeasuredHeight();
if (imageView == null) {
imageView = new ImageView(this);
}
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
params.setMargins(new Random().nextInt((width - 0) + 1), new Random().nextInt((height - 0) + 1), 10, 10);
imageView.setLayoutParams(params);
imageView.setImageBitmap(bitmap);
if (imageView != null) {
ViewGroup parent = (ViewGroup) imageView.getParent();
if (parent != null) {
parent.removeView(imageView);
}
}
relative4.addView(imageView);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (value) {
case 1:
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
break;
case 2:
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
break;
case 3:
drawSquare(finalImageView);
mTriangelCount--;
mSuareCount++;
break;
}
}
});
imageView.setOnLongClickListener(new View.OnLongClickListener(){
@Override
public boolean onLongClick(View v) {
switch (value) {
case 1:
relative4.removeView(finalImageView);
mSquareCount--;
break;
case 2:
relative4.removeView(finalImageView);
mCircleCount--;
break;
case 3:
relative4.removeView(finalImageView);
mTriangleCount--;
break;
}
return true;
});
}
}
android canvas shapes buttonclick ondraw
Creating bitmap cause an Oop memory allocation issue.
– Piyush
Oct 26 at 11:10
@Piyush then how to achieve this fuctionality?
– Rucha Bhatt Joshi
Oct 26 at 11:20
1
Why do you need to generate bitmap? Are you getting it from resource drawable or another folder?
– Piyush
Oct 26 at 12:04
@Piyush how to draw shape on canvas without bitmap!?
– Rucha Bhatt Joshi
Oct 26 at 12:17
You can go through this too.
– Piyush
Oct 26 at 12:20
|
show 8 more comments
up vote
1
down vote
favorite
up vote
1
down vote
favorite
I'm creating android application for shapes on canvas onClick of button.
What I want:
I have three buttons 'Square','Circle','Triangle'.
Each time I tap on button and object of that shape will be created & displayed in a random position on one canvas.(done)
On tap of each shape will cause it to become another shape.
tapping on a square will make it a circle
tapping on a circle will make it a triangle
tapping on a triangle will make it a square (done)
On long tap on a shape can delete the shape.(done)
How to implement undo functionality!
Tried and Error: To achieve this functionality I tried so far following code in which I can create one shape on click of button using bitmap in java and image view in xml.
Update_29/10: I work on same code and create multiple shapes on canvas using dynamic relative layout adding views.
My Question:
Is this right way(bitmap and imageview) to create shape on canvas by clicking on button?
I can create multiple shapes on canvas now but every time I'm creating new canvas instance!any other way to achieve this?
Update_29_10:
How to get click of shape so I can delete shape and undo functionality as well.
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/relative4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_above="@+id/btnCircle"
android:background="@color/colorAccent">
</RelativeLayout>
<Button
android:id="@+id/btnSquare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="@string/square" />
<Button
android:id="@+id/btnCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnSquare"
android:text="@string/circle" />
<Button
android:id="@+id/btnTriangle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnCircle"
android:text="@string/triangle" />
<Button
android:id="@+id/btnUndo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/btnTriangle"
android:layout_alignParentBottom="true"
android:text="@string/undo" />
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Context mContext;
private Resources mResources;
private RelativeLayout mRelativeLayout;
private Button btnSquare, btnCircle, btnTriangle,btnUndo,btnState;
private int mSuareCount=0,mCircleCount=0,mTriangelCount=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
mContext = getApplicationContext();
mResources = getResources();
mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
btnSquare = (Button) findViewById(R.id.btnSquare);
btnCircle = (Button)findViewById(R.id.btnCircle);
btnTriangle = (Button)findViewById(R.id.btnTriangle);
btnUndo=(Button)findViewById(R.id.btnUndo);
setOnClickListeners();
}
private void setOnClickListeners() {
btnSquare.setOnClickListener(this);
btnCircle.setOnClickListener(this);
btnTriangle.setOnClickListener(this);
btnUndo.setOnClickListener(this);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnSquare:
drawSquare(null);
mSuareCount++;
break;
case R.id.btnCircle:
drawCircle(null);
mCircleCount++;
break;
case R.id.btnTriangle:
drawTriangle(null);
mTriangelCount++;
break;
case R.id.btnUndo:
break;
}
}
private void drawSquare(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.LTGRAY);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
int padding = 50;
Rect rectangle = new Rect(
padding, // Left
padding, // Top
canvas.getWidth() - padding, // Right
canvas.getHeight() - padding // Bottom
);
canvas.drawRect(rectangle, paint);
addViews(bitmap,imageView,1);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
}
});
}
private void drawCircle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
int radius = Math.min(canvas.getWidth(), canvas.getHeight() / 2);
int padding = 5;
canvas.drawCircle(
canvas.getWidth() / 2, // cx
canvas.getHeight() / 2, // cy
radius - padding, // Radius
paint // Paint
);
addViews(bitmap,imageView,2);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
}
});
}
private void drawTriangle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
500, // Width
500, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(),
bitmap.getHeight());
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
Point point1_draw = new Point(90, 0);
Point point2_draw = new Point(0, 180);
Point point3_draw = new Point(180, 180);
Path path = new Path();
path.moveTo(point1_draw.x, point1_draw.y);
path.lineTo(point2_draw.x, point2_draw.y);
path.lineTo(point3_draw.x, point3_draw.y);
path.lineTo(point1_draw.x, point1_draw.y);
path.close();
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#3F51B5"));
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//addViews(bitmap,imageView);
addViews(bitmap,imageView,3);
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawSquare(finalImageView);
mSuareCount++;
mTriangelCount--;
}
});
}
private void addViews(Bitmap bitmap, ImageView imageView, final int value) {
final int min = 20;
final int max = 80;
Drawable d = getResources().getDrawable(R.mipmap.ic_launcher_round);
final int w = d.getIntrinsicWidth();
final int random = new Random().nextInt((max - min) + 1) + min;
RelativeLayout relative4 = (RelativeLayout) findViewById(R.id.relative4);
int width = relative4.getMeasuredWidth();
int height = relative4.getMeasuredHeight();
if (imageView == null) {
imageView = new ImageView(this);
}
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
params.setMargins(new Random().nextInt((width - 0) + 1), new Random().nextInt((height - 0) + 1), 10, 10);
imageView.setLayoutParams(params);
imageView.setImageBitmap(bitmap);
if (imageView != null) {
ViewGroup parent = (ViewGroup) imageView.getParent();
if (parent != null) {
parent.removeView(imageView);
}
}
relative4.addView(imageView);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (value) {
case 1:
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
break;
case 2:
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
break;
case 3:
drawSquare(finalImageView);
mTriangelCount--;
mSuareCount++;
break;
}
}
});
imageView.setOnLongClickListener(new View.OnLongClickListener(){
@Override
public boolean onLongClick(View v) {
switch (value) {
case 1:
relative4.removeView(finalImageView);
mSquareCount--;
break;
case 2:
relative4.removeView(finalImageView);
mCircleCount--;
break;
case 3:
relative4.removeView(finalImageView);
mTriangleCount--;
break;
}
return true;
});
}
}
android canvas shapes buttonclick ondraw
I'm creating android application for shapes on canvas onClick of button.
What I want:
I have three buttons 'Square','Circle','Triangle'.
Each time I tap on button and object of that shape will be created & displayed in a random position on one canvas.(done)
On tap of each shape will cause it to become another shape.
tapping on a square will make it a circle
tapping on a circle will make it a triangle
tapping on a triangle will make it a square (done)
On long tap on a shape can delete the shape.(done)
How to implement undo functionality!
Tried and Error: To achieve this functionality I tried so far following code in which I can create one shape on click of button using bitmap in java and image view in xml.
Update_29/10: I work on same code and create multiple shapes on canvas using dynamic relative layout adding views.
My Question:
Is this right way(bitmap and imageview) to create shape on canvas by clicking on button?
I can create multiple shapes on canvas now but every time I'm creating new canvas instance!any other way to achieve this?
Update_29_10:
How to get click of shape so I can delete shape and undo functionality as well.
XML:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#ffffff"
tools:context=".MainActivity">
<RelativeLayout
android:id="@+id/relative4"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:layout_above="@+id/btnCircle"
android:background="@color/colorAccent">
</RelativeLayout>
<Button
android:id="@+id/btnSquare"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:text="@string/square" />
<Button
android:id="@+id/btnCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnSquare"
android:text="@string/circle" />
<Button
android:id="@+id/btnTriangle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_toRightOf="@+id/btnCircle"
android:text="@string/triangle" />
<Button
android:id="@+id/btnUndo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/btnTriangle"
android:layout_alignParentBottom="true"
android:text="@string/undo" />
MainActivity.java:
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Context mContext;
private Resources mResources;
private RelativeLayout mRelativeLayout;
private Button btnSquare, btnCircle, btnTriangle,btnUndo,btnState;
private int mSuareCount=0,mCircleCount=0,mTriangelCount=0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews() {
mContext = getApplicationContext();
mResources = getResources();
mRelativeLayout = (RelativeLayout) findViewById(R.id.rl);
btnSquare = (Button) findViewById(R.id.btnSquare);
btnCircle = (Button)findViewById(R.id.btnCircle);
btnTriangle = (Button)findViewById(R.id.btnTriangle);
btnUndo=(Button)findViewById(R.id.btnUndo);
setOnClickListeners();
}
private void setOnClickListeners() {
btnSquare.setOnClickListener(this);
btnCircle.setOnClickListener(this);
btnTriangle.setOnClickListener(this);
btnUndo.setOnClickListener(this);
}
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.btnSquare:
drawSquare(null);
mSuareCount++;
break;
case R.id.btnCircle:
drawCircle(null);
mCircleCount++;
break;
case R.id.btnTriangle:
drawTriangle(null);
mTriangelCount++;
break;
case R.id.btnUndo:
break;
}
}
private void drawSquare(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
canvas.drawColor(Color.LTGRAY);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
int padding = 50;
Rect rectangle = new Rect(
padding, // Left
padding, // Top
canvas.getWidth() - padding, // Right
canvas.getHeight() - padding // Bottom
);
canvas.drawRect(rectangle, paint);
addViews(bitmap,imageView,1);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
}
});
}
private void drawCircle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
50, // Width
50, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.RED);
paint.setAntiAlias(true);
int radius = Math.min(canvas.getWidth(), canvas.getHeight() / 2);
int padding = 5;
canvas.drawCircle(
canvas.getWidth() / 2, // cx
canvas.getHeight() / 2, // cy
radius - padding, // Radius
paint // Paint
);
addViews(bitmap,imageView,2);
// Display the newly created bitmap on app interface
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
}
});
}
private void drawTriangle(ImageView imageView) {
Bitmap bitmap = Bitmap.createBitmap(
500, // Width
500, // Height
Bitmap.Config.ARGB_8888 // Config
);
Canvas canvas = new Canvas(bitmap);
Paint paint = new Paint();
final Rect rect = new Rect(0, 0, bitmap.getWidth(),
bitmap.getHeight());
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
paint.setAntiAlias(true);
Point point1_draw = new Point(90, 0);
Point point2_draw = new Point(0, 180);
Point point3_draw = new Point(180, 180);
Path path = new Path();
path.moveTo(point1_draw.x, point1_draw.y);
path.lineTo(point2_draw.x, point2_draw.y);
path.lineTo(point3_draw.x, point3_draw.y);
path.lineTo(point1_draw.x, point1_draw.y);
path.close();
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#3F51B5"));
canvas.drawPath(path, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
canvas.drawBitmap(bitmap, rect, rect, paint);
//addViews(bitmap,imageView);
addViews(bitmap,imageView,3);
if (imageView == null) {
imageView = new ImageView(this);
}
imageView.setImageBitmap(bitmap);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
drawSquare(finalImageView);
mSuareCount++;
mTriangelCount--;
}
});
}
private void addViews(Bitmap bitmap, ImageView imageView, final int value) {
final int min = 20;
final int max = 80;
Drawable d = getResources().getDrawable(R.mipmap.ic_launcher_round);
final int w = d.getIntrinsicWidth();
final int random = new Random().nextInt((max - min) + 1) + min;
RelativeLayout relative4 = (RelativeLayout) findViewById(R.id.relative4);
int width = relative4.getMeasuredWidth();
int height = relative4.getMeasuredHeight();
if (imageView == null) {
imageView = new ImageView(this);
}
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(100, 100);
params.setMargins(new Random().nextInt((width - 0) + 1), new Random().nextInt((height - 0) + 1), 10, 10);
imageView.setLayoutParams(params);
imageView.setImageBitmap(bitmap);
if (imageView != null) {
ViewGroup parent = (ViewGroup) imageView.getParent();
if (parent != null) {
parent.removeView(imageView);
}
}
relative4.addView(imageView);
final ImageView finalImageView = imageView;
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
switch (value) {
case 1:
drawCircle(finalImageView);
mSuareCount--;
mCircleCount++;
break;
case 2:
drawTriangle(finalImageView);
mCircleCount--;
mTriangelCount++;
break;
case 3:
drawSquare(finalImageView);
mTriangelCount--;
mSuareCount++;
break;
}
}
});
imageView.setOnLongClickListener(new View.OnLongClickListener(){
@Override
public boolean onLongClick(View v) {
switch (value) {
case 1:
relative4.removeView(finalImageView);
mSquareCount--;
break;
case 2:
relative4.removeView(finalImageView);
mCircleCount--;
break;
case 3:
relative4.removeView(finalImageView);
mTriangleCount--;
break;
}
return true;
});
}
}
android canvas shapes buttonclick ondraw
android canvas shapes buttonclick ondraw
edited Nov 7 at 11:07
asked Oct 26 at 10:43
Rucha Bhatt Joshi
66611026
66611026
Creating bitmap cause an Oop memory allocation issue.
– Piyush
Oct 26 at 11:10
@Piyush then how to achieve this fuctionality?
– Rucha Bhatt Joshi
Oct 26 at 11:20
1
Why do you need to generate bitmap? Are you getting it from resource drawable or another folder?
– Piyush
Oct 26 at 12:04
@Piyush how to draw shape on canvas without bitmap!?
– Rucha Bhatt Joshi
Oct 26 at 12:17
You can go through this too.
– Piyush
Oct 26 at 12:20
|
show 8 more comments
Creating bitmap cause an Oop memory allocation issue.
– Piyush
Oct 26 at 11:10
@Piyush then how to achieve this fuctionality?
– Rucha Bhatt Joshi
Oct 26 at 11:20
1
Why do you need to generate bitmap? Are you getting it from resource drawable or another folder?
– Piyush
Oct 26 at 12:04
@Piyush how to draw shape on canvas without bitmap!?
– Rucha Bhatt Joshi
Oct 26 at 12:17
You can go through this too.
– Piyush
Oct 26 at 12:20
Creating bitmap cause an Oop memory allocation issue.
– Piyush
Oct 26 at 11:10
Creating bitmap cause an Oop memory allocation issue.
– Piyush
Oct 26 at 11:10
@Piyush then how to achieve this fuctionality?
– Rucha Bhatt Joshi
Oct 26 at 11:20
@Piyush then how to achieve this fuctionality?
– Rucha Bhatt Joshi
Oct 26 at 11:20
1
1
Why do you need to generate bitmap? Are you getting it from resource drawable or another folder?
– Piyush
Oct 26 at 12:04
Why do you need to generate bitmap? Are you getting it from resource drawable or another folder?
– Piyush
Oct 26 at 12:04
@Piyush how to draw shape on canvas without bitmap!?
– Rucha Bhatt Joshi
Oct 26 at 12:17
@Piyush how to draw shape on canvas without bitmap!?
– Rucha Bhatt Joshi
Oct 26 at 12:17
You can go through this too.
– Piyush
Oct 26 at 12:20
You can go through this too.
– Piyush
Oct 26 at 12:20
|
show 8 more comments
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
While aanshu's solution is probably the more efficient way to do this, his solution makes it difficult to recognize clicks on the single shapes.
Instead of making one big subclass of ImageView and overriding onDraw and drawing each of the sub-shapes, you could make a subclass of ImageView for each class of square, circle and triangle. Something like this:
public class SquareView extends ImageView {
@Override
protected void onDraw(Canvas canvas) {
//draw your Square on the canvas given
}
}
Same for Circle and triangle. Then just generate one of these views as you were generating image views before but do not set the Bitmap. You can add them to the layout and it will call the onDraw function and give it a canvas. Now you can register your onClickListener for each of these views as before. When the view is clicked you replace it with an instance of a different class, for example you replace SquareView with a CircleView.
For the undo operations, you could just make this. This is very pseudocode like, I also might be mixing some programming languages but the idea is everywhere the same. If something is unclear, please ask.
Stack<Runnable> undoStack;
//and now whenever you do something that should be undoable you just add a runnable that will undo it:
//for example if a user clicked a SquareView:
removeView(squareView);
CircleView circleView = new CircleView();
//take the information from the squareView that is needed
circleview.position = squareView.position;
addView(circleView);
undoStack.push(() -> removeView(circleView); addView(squareView););
//When you undo you just call
undoStack.pop().run();
A bit of background about your code, because I think it will help you understand. This is the source of android ImageView. When you call setImageBitmap(bitmap), it passes the bitmap to an instance of BitmapDrawable which it calls mDrawable. Then in the ImageViews onDraw(Canvas canvas) method it calls mDrawable.draw(canvas) which in case of BitmapDrawable (source here) after a lot of other stuff calls canvas.drawBitmap(bitmap). So basically what your code does: it creates a Bitmap from a canvas and then via ImageView and BitmapDrawable the bitmap is drawn back on a canvas. My and aanshu's solution draw directly on this final canvas. That is why they are better than your current solution.
Edit:
While searching something else, I stumbled upon drawable shape resources. As with any drawable resource you can just pass them to ImageViews. This way you probably wouldn't have to override the onDraw function. But I never worked with them, so I'll just leave this here.
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
1
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
|
show 3 more comments
up vote
2
down vote
You may implement the functionality using with the following approach (psudo code):
Step 1:
interface ShapeInfo {
void drawShape(Canvas canvas);
}
Step 2:
Implement the 3 different classes (Rect, Triangle, Circle) with this interface
Step 3: Set a background to RelativeLayout
Step 4: Add a CustomView in RelativeLayout
make this custom view transparent.
public class CustomView extends ImageView{
ArrayList<ShapeInfo> alShapesInfo = new ArrayList();
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for ( ShapeInfo s:alShapesInfo)
s.drawShape(canvas);
}
public void addShapeInfo(ShapeInfo s){alShapeinfo.add(s); invalidate();}
public void undo(){alShapeInfo.delete(alShapeInfo.size()-1); invalidate();}
}
Spte 5:
In main activity on button click of add triangle, circle, rect call customview.addshapeinfo
Step 6: to undo call
customview.undo
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
While aanshu's solution is probably the more efficient way to do this, his solution makes it difficult to recognize clicks on the single shapes.
Instead of making one big subclass of ImageView and overriding onDraw and drawing each of the sub-shapes, you could make a subclass of ImageView for each class of square, circle and triangle. Something like this:
public class SquareView extends ImageView {
@Override
protected void onDraw(Canvas canvas) {
//draw your Square on the canvas given
}
}
Same for Circle and triangle. Then just generate one of these views as you were generating image views before but do not set the Bitmap. You can add them to the layout and it will call the onDraw function and give it a canvas. Now you can register your onClickListener for each of these views as before. When the view is clicked you replace it with an instance of a different class, for example you replace SquareView with a CircleView.
For the undo operations, you could just make this. This is very pseudocode like, I also might be mixing some programming languages but the idea is everywhere the same. If something is unclear, please ask.
Stack<Runnable> undoStack;
//and now whenever you do something that should be undoable you just add a runnable that will undo it:
//for example if a user clicked a SquareView:
removeView(squareView);
CircleView circleView = new CircleView();
//take the information from the squareView that is needed
circleview.position = squareView.position;
addView(circleView);
undoStack.push(() -> removeView(circleView); addView(squareView););
//When you undo you just call
undoStack.pop().run();
A bit of background about your code, because I think it will help you understand. This is the source of android ImageView. When you call setImageBitmap(bitmap), it passes the bitmap to an instance of BitmapDrawable which it calls mDrawable. Then in the ImageViews onDraw(Canvas canvas) method it calls mDrawable.draw(canvas) which in case of BitmapDrawable (source here) after a lot of other stuff calls canvas.drawBitmap(bitmap). So basically what your code does: it creates a Bitmap from a canvas and then via ImageView and BitmapDrawable the bitmap is drawn back on a canvas. My and aanshu's solution draw directly on this final canvas. That is why they are better than your current solution.
Edit:
While searching something else, I stumbled upon drawable shape resources. As with any drawable resource you can just pass them to ImageViews. This way you probably wouldn't have to override the onDraw function. But I never worked with them, so I'll just leave this here.
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
1
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
|
show 3 more comments
up vote
1
down vote
accepted
While aanshu's solution is probably the more efficient way to do this, his solution makes it difficult to recognize clicks on the single shapes.
Instead of making one big subclass of ImageView and overriding onDraw and drawing each of the sub-shapes, you could make a subclass of ImageView for each class of square, circle and triangle. Something like this:
public class SquareView extends ImageView {
@Override
protected void onDraw(Canvas canvas) {
//draw your Square on the canvas given
}
}
Same for Circle and triangle. Then just generate one of these views as you were generating image views before but do not set the Bitmap. You can add them to the layout and it will call the onDraw function and give it a canvas. Now you can register your onClickListener for each of these views as before. When the view is clicked you replace it with an instance of a different class, for example you replace SquareView with a CircleView.
For the undo operations, you could just make this. This is very pseudocode like, I also might be mixing some programming languages but the idea is everywhere the same. If something is unclear, please ask.
Stack<Runnable> undoStack;
//and now whenever you do something that should be undoable you just add a runnable that will undo it:
//for example if a user clicked a SquareView:
removeView(squareView);
CircleView circleView = new CircleView();
//take the information from the squareView that is needed
circleview.position = squareView.position;
addView(circleView);
undoStack.push(() -> removeView(circleView); addView(squareView););
//When you undo you just call
undoStack.pop().run();
A bit of background about your code, because I think it will help you understand. This is the source of android ImageView. When you call setImageBitmap(bitmap), it passes the bitmap to an instance of BitmapDrawable which it calls mDrawable. Then in the ImageViews onDraw(Canvas canvas) method it calls mDrawable.draw(canvas) which in case of BitmapDrawable (source here) after a lot of other stuff calls canvas.drawBitmap(bitmap). So basically what your code does: it creates a Bitmap from a canvas and then via ImageView and BitmapDrawable the bitmap is drawn back on a canvas. My and aanshu's solution draw directly on this final canvas. That is why they are better than your current solution.
Edit:
While searching something else, I stumbled upon drawable shape resources. As with any drawable resource you can just pass them to ImageViews. This way you probably wouldn't have to override the onDraw function. But I never worked with them, so I'll just leave this here.
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
1
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
|
show 3 more comments
up vote
1
down vote
accepted
up vote
1
down vote
accepted
While aanshu's solution is probably the more efficient way to do this, his solution makes it difficult to recognize clicks on the single shapes.
Instead of making one big subclass of ImageView and overriding onDraw and drawing each of the sub-shapes, you could make a subclass of ImageView for each class of square, circle and triangle. Something like this:
public class SquareView extends ImageView {
@Override
protected void onDraw(Canvas canvas) {
//draw your Square on the canvas given
}
}
Same for Circle and triangle. Then just generate one of these views as you were generating image views before but do not set the Bitmap. You can add them to the layout and it will call the onDraw function and give it a canvas. Now you can register your onClickListener for each of these views as before. When the view is clicked you replace it with an instance of a different class, for example you replace SquareView with a CircleView.
For the undo operations, you could just make this. This is very pseudocode like, I also might be mixing some programming languages but the idea is everywhere the same. If something is unclear, please ask.
Stack<Runnable> undoStack;
//and now whenever you do something that should be undoable you just add a runnable that will undo it:
//for example if a user clicked a SquareView:
removeView(squareView);
CircleView circleView = new CircleView();
//take the information from the squareView that is needed
circleview.position = squareView.position;
addView(circleView);
undoStack.push(() -> removeView(circleView); addView(squareView););
//When you undo you just call
undoStack.pop().run();
A bit of background about your code, because I think it will help you understand. This is the source of android ImageView. When you call setImageBitmap(bitmap), it passes the bitmap to an instance of BitmapDrawable which it calls mDrawable. Then in the ImageViews onDraw(Canvas canvas) method it calls mDrawable.draw(canvas) which in case of BitmapDrawable (source here) after a lot of other stuff calls canvas.drawBitmap(bitmap). So basically what your code does: it creates a Bitmap from a canvas and then via ImageView and BitmapDrawable the bitmap is drawn back on a canvas. My and aanshu's solution draw directly on this final canvas. That is why they are better than your current solution.
Edit:
While searching something else, I stumbled upon drawable shape resources. As with any drawable resource you can just pass them to ImageViews. This way you probably wouldn't have to override the onDraw function. But I never worked with them, so I'll just leave this here.
While aanshu's solution is probably the more efficient way to do this, his solution makes it difficult to recognize clicks on the single shapes.
Instead of making one big subclass of ImageView and overriding onDraw and drawing each of the sub-shapes, you could make a subclass of ImageView for each class of square, circle and triangle. Something like this:
public class SquareView extends ImageView {
@Override
protected void onDraw(Canvas canvas) {
//draw your Square on the canvas given
}
}
Same for Circle and triangle. Then just generate one of these views as you were generating image views before but do not set the Bitmap. You can add them to the layout and it will call the onDraw function and give it a canvas. Now you can register your onClickListener for each of these views as before. When the view is clicked you replace it with an instance of a different class, for example you replace SquareView with a CircleView.
For the undo operations, you could just make this. This is very pseudocode like, I also might be mixing some programming languages but the idea is everywhere the same. If something is unclear, please ask.
Stack<Runnable> undoStack;
//and now whenever you do something that should be undoable you just add a runnable that will undo it:
//for example if a user clicked a SquareView:
removeView(squareView);
CircleView circleView = new CircleView();
//take the information from the squareView that is needed
circleview.position = squareView.position;
addView(circleView);
undoStack.push(() -> removeView(circleView); addView(squareView););
//When you undo you just call
undoStack.pop().run();
A bit of background about your code, because I think it will help you understand. This is the source of android ImageView. When you call setImageBitmap(bitmap), it passes the bitmap to an instance of BitmapDrawable which it calls mDrawable. Then in the ImageViews onDraw(Canvas canvas) method it calls mDrawable.draw(canvas) which in case of BitmapDrawable (source here) after a lot of other stuff calls canvas.drawBitmap(bitmap). So basically what your code does: it creates a Bitmap from a canvas and then via ImageView and BitmapDrawable the bitmap is drawn back on a canvas. My and aanshu's solution draw directly on this final canvas. That is why they are better than your current solution.
Edit:
While searching something else, I stumbled upon drawable shape resources. As with any drawable resource you can just pass them to ImageViews. This way you probably wouldn't have to override the onDraw function. But I never worked with them, so I'll just leave this here.
edited Nov 7 at 15:37
answered Nov 6 at 11:07
findusl
729724
729724
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
1
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
|
show 3 more comments
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
1
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
for daw square,circle and triangle same function I should use?
– Rucha Bhatt Joshi
Nov 7 at 10:27
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
You make three classes SquareView, CircleView and TriangleView. In each of these classes you implement the drawing in the onDraw function.
– findusl
Nov 7 at 10:28
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
which function I have to use to create that shape same function which I used before? I'll try your solution
– Rucha Bhatt Joshi
Nov 7 at 10:38
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
Yes you draw the shapes the same way as you did before on the canvas that is passed to onDraw. Make sure the view has the right size then the canvas should have the size as well.
– findusl
Nov 7 at 10:41
1
1
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
A quick comment: you probably want to extend View instead of ImageView. Not only do you lose all of ImageView's functionality when you override onDraw(), but you're going to do something very different from an ImageView (drawing vectors vs. drawing bitmaps).
– Project
Nov 7 at 19:50
|
show 3 more comments
up vote
2
down vote
You may implement the functionality using with the following approach (psudo code):
Step 1:
interface ShapeInfo {
void drawShape(Canvas canvas);
}
Step 2:
Implement the 3 different classes (Rect, Triangle, Circle) with this interface
Step 3: Set a background to RelativeLayout
Step 4: Add a CustomView in RelativeLayout
make this custom view transparent.
public class CustomView extends ImageView{
ArrayList<ShapeInfo> alShapesInfo = new ArrayList();
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for ( ShapeInfo s:alShapesInfo)
s.drawShape(canvas);
}
public void addShapeInfo(ShapeInfo s){alShapeinfo.add(s); invalidate();}
public void undo(){alShapeInfo.delete(alShapeInfo.size()-1); invalidate();}
}
Spte 5:
In main activity on button click of add triangle, circle, rect call customview.addshapeinfo
Step 6: to undo call
customview.undo
add a comment |
up vote
2
down vote
You may implement the functionality using with the following approach (psudo code):
Step 1:
interface ShapeInfo {
void drawShape(Canvas canvas);
}
Step 2:
Implement the 3 different classes (Rect, Triangle, Circle) with this interface
Step 3: Set a background to RelativeLayout
Step 4: Add a CustomView in RelativeLayout
make this custom view transparent.
public class CustomView extends ImageView{
ArrayList<ShapeInfo> alShapesInfo = new ArrayList();
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for ( ShapeInfo s:alShapesInfo)
s.drawShape(canvas);
}
public void addShapeInfo(ShapeInfo s){alShapeinfo.add(s); invalidate();}
public void undo(){alShapeInfo.delete(alShapeInfo.size()-1); invalidate();}
}
Spte 5:
In main activity on button click of add triangle, circle, rect call customview.addshapeinfo
Step 6: to undo call
customview.undo
add a comment |
up vote
2
down vote
up vote
2
down vote
You may implement the functionality using with the following approach (psudo code):
Step 1:
interface ShapeInfo {
void drawShape(Canvas canvas);
}
Step 2:
Implement the 3 different classes (Rect, Triangle, Circle) with this interface
Step 3: Set a background to RelativeLayout
Step 4: Add a CustomView in RelativeLayout
make this custom view transparent.
public class CustomView extends ImageView{
ArrayList<ShapeInfo> alShapesInfo = new ArrayList();
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for ( ShapeInfo s:alShapesInfo)
s.drawShape(canvas);
}
public void addShapeInfo(ShapeInfo s){alShapeinfo.add(s); invalidate();}
public void undo(){alShapeInfo.delete(alShapeInfo.size()-1); invalidate();}
}
Spte 5:
In main activity on button click of add triangle, circle, rect call customview.addshapeinfo
Step 6: to undo call
customview.undo
You may implement the functionality using with the following approach (psudo code):
Step 1:
interface ShapeInfo {
void drawShape(Canvas canvas);
}
Step 2:
Implement the 3 different classes (Rect, Triangle, Circle) with this interface
Step 3: Set a background to RelativeLayout
Step 4: Add a CustomView in RelativeLayout
make this custom view transparent.
public class CustomView extends ImageView{
ArrayList<ShapeInfo> alShapesInfo = new ArrayList();
public CustomView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
for ( ShapeInfo s:alShapesInfo)
s.drawShape(canvas);
}
public void addShapeInfo(ShapeInfo s){alShapeinfo.add(s); invalidate();}
public void undo(){alShapeInfo.delete(alShapeInfo.size()-1); invalidate();}
}
Spte 5:
In main activity on button click of add triangle, circle, rect call customview.addshapeinfo
Step 6: to undo call
customview.undo
edited Nov 6 at 7:43
answered Nov 6 at 7:28
aanshu
1,035611
1,035611
add a comment |
add a comment |
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53006963%2fcreate-change-delete-undo-number-of-different-shapes-on-canvas-onclick-of-but%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Creating bitmap cause an Oop memory allocation issue.
– Piyush
Oct 26 at 11:10
@Piyush then how to achieve this fuctionality?
– Rucha Bhatt Joshi
Oct 26 at 11:20
1
Why do you need to generate bitmap? Are you getting it from resource drawable or another folder?
– Piyush
Oct 26 at 12:04
@Piyush how to draw shape on canvas without bitmap!?
– Rucha Bhatt Joshi
Oct 26 at 12:17
You can go through this too.
– Piyush
Oct 26 at 12:20