Updating Canvas? invalidate()? - android

Hi im trying to get my app to update a canvas from a custom view i made
This view creates a square with lines and a circle in the center.
I want to press a button and draw random x and y coordinates to the canvas.
Heres My MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// EditText numDart = (EditText) findViewById(R.id.numDarts);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
public int convertToDpi(int px){
DisplayMetrics metrics = getResources().getDisplayMetrics();
int unit = metrics.widthPixels/20;
return px * unit;
}
public void drawCanvas(View v){
View view = (View) findViewById(R.id.canView);
Paint black = new Paint();
black.setColor(Color.BLACK);
black.setStyle(Style.FILL);
view.invalidate(); //dont know where to go from here
}
Heres My Custom View:
public CanView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
Rect myrect = new Rect();
myrect.set(-10, 10, 10, -10);
Paint blue = new Paint();
Paint white = new Paint();
white.setColor(Color.WHITE);
white.setStyle(Paint.Style.FILL);
Paint black = new Paint();
black.setColor(Color.BLACK);
black.setStyle(Paint.Style.FILL);
blue.setColor(Color.BLUE);
blue.setStyle(Paint.Style.FILL);
canvas.drawRect(myrect, blue);
canvas.drawCircle(convertToDpi(10), convertToDpi(10),convertToDpi(3), white);
canvas.drawLine(convertToDpi(10), 0, convertToDpi(10), convertToDpi(20), black);
canvas.drawLine(0, convertToDpi(10), convertToDpi(20), convertToDpi(10), black);
canvas.scale(5, 5, 0, 0);
}
#Override
public void postInvalidate() { //Logic for redrawig goes here???
// TODO Auto-generated method stub
super.postInvalidate();
}
public int convertToDpi(int px){
DisplayMetrics metrics = getResources().getDisplayMetrics();
int unit = metrics.widthPixels/20;
return px * unit;
}
I dont get how to reference the canvas from my Custom View and change or redraw it. Im assuming you use invalidate(); but im puzzled on how this method works can any1 help me out?

When invalidate is called onDraw is called again, you should also use this.getHolder().addCallback(this); and let your class implement Callback and add the unimplemented methods

I guess you need to draw the view only. First of set your contentview as the View where you are drawing on the canvas. Your are setting your contnet view only as the main layout. If you want to see the View where you drawing on canvas. set that view to your contentView.
setContentView(canView);
Now if you want that button too, then create a relative layout and add the button view and this canView to that relative layout ans set this as your contentView.

Related

Add Imageviews dynamically inside the circle which is already drawn on google map in android

If you observe the above two pictures, there are markers in picture1, if user tap on marker second picture will come with available options dynamically may be 2,3 etc.
For the second picture I have written custom view and able to draw circle but unable to show images inside the circle.
public class CustomView extends ViewGroup {
private Paint paint;
public CustomView(Context context) {
super(context);
// create the Paint and set its color
paint = new Paint();
paint.setColor(0xFF1f5b83);
}
#Override
protected void dispatchDraw(Canvas canvas) {
int width = this.getWidth();
int height = this.getHeight();
canvas.drawCircle(width / 2, height / 2-64, 200, paint);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
}
}
For testing purpose I am adding text instead of image
public void sendMessage(View view) {
circleView = new CustomView(this);
TextView textView = new TextView(this);
textView.setText("Test");
textView.setTextColor(Color.WHITE);
textView.setBackgroundColor(Color.WHITE);
addContentView(circleView, new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
circleView.bringToFront();
}
How to add images inside the circle in Java class I mean Activity class?

How to add drawn Canvas to specific part of Layout?

For example i have a layout (or view in a layout) that covers %20 percent of height of the screen.I want to add a drawn canvas to that part. But I dont want to use it with setContentView because i can not do my layout operations such as textviews and edittexts etc. So how can i add that custom class to my layout. LinearLayout.addView(My custom -view extended- class) does not work.
Note: Scale must be lowered proportionally, for example if i draw it for fullscreen, when adding the scale must be lowered to fit that covered area.
This Works but not desired
DrawShape ds;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
ds = new DrawShape(this);
setContentView(ds); // Dont want it
}
class DrawShape extends View {
Context c;
Paint p = new Paint();
public DrawShape(Context c)
{
super(c);
this.c = c;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int width = canvas.getWidth();
int height = canvas.getHeight();
p.setStyle(Paint.Style.STROKE);
p.setAntiAlias(true);
p.setStrokeWidth(width/40);
p.setColor(Color.rgb(200,140,0));
RectF r = new RectF();
r.set(width/4,height/2-width/4,width-(width/4),height/2+width/4);
canvas.drawCircle(width / 2, height / 2, width / 4, p);
canvas.drawLine(0,0,width,height,p);
canvas.drawLine(width,0,0,height,p);
canvas.drawLine(0,height/2,width,height/2,p);
}
}
This does not work, no draw
LinearLayout ll;
DrawShape ds;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
ds = new DrawShape(this);
setContentView(R.layout.activity_main);
ll = (LinearLayout) findViewById(R.id.mainLL);
mainLL.addView(ds); // Does not work, with layout params it does not work too.
}

Call a method from activity that extends View

I'm doing a genre of a bull's eye, but instead of use circles I'm using squares.
But the problem is:
Everything is done, the algorithm to generate the color the others squares is done.
But I implemented a button, and I made it to refresh the bull's eye.
The problem is that I can't make, need help.
This is the MainActivity, it's from here that I will detect the button click.
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
FrameLayout frame = (FrameLayout) findViewById(R.id.frame);
Draw draw = new Draw(this);
frame.addView(draw);
Button refresh = (Button) findViewById(R.id.refresh);
refresh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
draw.onDraw(canvas);
frame.addView(draw);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
And this is the Draw activity, this is the one that I used to render the image.
public class Draw extends View {
public Draw(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
Paint prop = new Paint();
Random color = new Random();
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
int width = getWidth();
int height = getHeight();
int oriwidth = 0;
int oriheight = 0;
for (int x = 0; x < 20; x++) {
int red = color.nextInt();
int green = color.nextInt();
int blue = color.nextInt();
prop.setARGB(0, red, green, blue);
canvas.drawRect(oriwidth += 10, oriheight += 10, width -= 10,
height -= 10, prop);
}
}
}
Can someone help me? Sorry for the english.
Is there any special reason why you're adding the Draw view programmatically during onCreate?
Try defining the Draw view in the layout xml itself. That should solve any issues with defining the width / height of the view (make sure to define width & height... try hard coded dimensions at first like 100dp by 100dp)
Once you've done that, make sure to capture your "draw" view as a member of the activity:
public class MainActivity extends Activity
{
private Draw mDraw;
Then, in your onCreate:
mDraw = (Draw)findViewById(R.id.myDrawId);
Then, in your button click listener, just call invalidate:
refresh.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
mDraw.invalidate();
}
});
Try to change with this portion of code:
public void onClick(View v) {
MainActivity.this.draw.onDraw(canvas);
MainActivity.this.frame.addView(draw);
}
You shouldn't call onDraw() directly. Try draw.invalidate().

How to Display text on canvas when clicked on a randomly moving bitmap image?

The bitmap image(smiling) in my code moves randomly on screen. I want to display a message whenever user clicks on the randomly moving bitmap image.I tried using Ontouch() method but couldn't find a solution.
public class MainActivity extends Activity {
Myclass ourView;
Bitmap smile;
TextView dis;
int x=0,y=0,a=0,b=0;
#Override
protected void onCreate(Bundle savedInstanceState) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
ourView=new Myclass(this);
setContentView(ourView);
}
public class Myclass extends View implements OnTouchListener{
int changingX=0,changingY=0;
Random crazy = new Random();
Paint ourblue=new Paint();
Paint Text=new Paint();
Paint text=new Paint();
public Myclass(Context context) {
super(context);
// TODO Auto-generated constructor stub
smile=BitmapFactory.decodeResource(getResources(), R.drawable.smiling);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
ourblue.setARGB(220, 221, 243, 249);
canvas.drawPaint(ourblue);
a=crazy.nextInt(350);
b=crazy.nextInt(550);
canvas.drawBitmap(smile,a,b , null);
if(x>(a-20)&&x<(a+20)&&y>(b-20)&&y<(b+20))
{
text.setARGB(220, 0, 0, 0);
text.setTextAlign(Align.CENTER);
text.setTextSize(50);
canvas.drawText("Awesome", 100, 100, text);
}
for(int i=0;i<1000000;i++)
{
}
invalidate();
}
public boolean onTouch(View arg0, MotionEvent event) {
// TODO Auto-generated method stub
x=(int) event.getX();
y=(int) event.getY();
return true;
}
}
}
Keep track of your Bitmap's rectangle as it moves randomly
Create a class-wide flag: boolean displayText
In your onTouch method, always check if the touch occurs inside your Bitmap's rectangle. If it does, then set displayText = true else set it to false
In your onDraw method, check if displayText is true, if so draw the text. If not, don't draw it.

Setting size of a triangle (Android)

So, I have created an android activity that draws a triangle on the canvas. I also added 4 menus(Color, Enlarge, Shrink, and Reset) to the VM. The color works fine but I'm not quite sure how to resize a triangle in android once that menu button is pressed.The assignment says to just fix the top point of the triangle, and then change the coordinates of the bottom two points of the triangle. Can anyone point me in the right direction on how to do that in Android?
Here's my code, although the implementation of enlarge, shrink, and reset are set up to work with a circle(project I did before), not a triangle. Please note that the "Color" menu works so no need to do that.
public class MainActivity extends Activity
{
final Context context = this;
private Graphics graphic;
private Dialog radiusDialog; //Creates dialog box declaration
private SeekBar red;
private SeekBar green;
private SeekBar blue;
private Button radiusButton;
private TextView progress1;
private TextView progress2;
private TextView progress3;
private TextView tv;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
graphic = new Graphics(this); //Create new instance of graphics view
setContentView(graphic); //Associates customized view with current screen
}
#Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) //This acts as a menu listener to override
{
switch(item.getItemId()) //returns menu item
{
case R.id.Color:
showDialog();
break;
case R.id.Shrink:
graphic.setRadius(graphic.getRadius() -1);
graphic.invalidate();
break;
case R.id.Enlarge:
graphic.setRadius(graphic.getRadius() +1);
graphic.invalidate();
break;
case R.id.Reset:
graphic.setColor(Color.CYAN);
graphic.setRadius(75);
graphic.invalidate();
break;
}
return super.onOptionsItemSelected(item);
}
void showDialog() //creates memory for dialog
{
radiusDialog = new Dialog(context);
radiusDialog.setContentView(R.layout.draw_layout); //binds layout file (radius) with current dialog
radiusDialog.setTitle("Select Color:");
red = (SeekBar)radiusDialog.findViewById(R.id.seekBar1);
green = (SeekBar)radiusDialog.findViewById(R.id.seekBar2);
blue = (SeekBar)radiusDialog.findViewById(R.id.seekBar3);
progress1 = (TextView)radiusDialog.findViewById(R.id.textView2);
progress2 = (TextView)radiusDialog.findViewById(R.id.textView4);
progress3 = (TextView)radiusDialog.findViewById(R.id.textView6);
mychange redC = new mychange();
red.setOnSeekBarChangeListener(redC);
mychange greenC = new mychange();
green.setOnSeekBarChangeListener(greenC);
tv = (TextView)radiusDialog.findViewById(R.id.textView7);
mychange c = new mychange();
blue.setOnSeekBarChangeListener(c);
radiusButton = (Button) radiusDialog.findViewById(R.id.button1);
radiusButton.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
int color = Color.rgb(red.getProgress(), green.getProgress(), blue.getProgress());
radiusDialog.dismiss();
setContentView(R.layout.activity_main);
setContentView(graphic);
graphic.setColor(color);//Create new instance of graphics view
graphic.invalidate();
}
});
radiusDialog.show(); //shows dialog on screen
}
public class mychange implements OnSeekBarChangeListener{
#Override
public void onProgressChanged(SeekBar seekBar, int progress,
boolean fromUser) {
// TODO Auto-generated method stub
int color = Color.rgb(red.getProgress(), green.getProgress(), blue.getProgress());
tv.setBackgroundColor(color);
progress1.setText(String.valueOf(red.getProgress()));
progress2.setText(String.valueOf(green.getProgress()));
progress3.setText(String.valueOf(blue.getProgress()));
}
#Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
#Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}
}
Graphics Class to draw triangle
public class Graphics extends View
{
private Paint paint;
private int radius;
private int color;
public void setColor(int color)
{
this.color = color;
}
public Graphics(Context context) //creates custom view (constructor)
{
super(context);
paint = new Paint(); //create instance of paint
color = Color.CYAN;
paint.setStyle(Paint.Style.FILL); //draw filled shape
radius = 75;
}
#Override
protected void onDraw(Canvas canvas) //override onDraw method
{
super.onDraw(canvas);
paint.setColor(color);
paint.setStyle(Paint.Style.STROKE);
Path path = new Path();
path.moveTo(230, 200);
path.lineTo(330, 300);
path.lineTo(130, 300);
path.close();
canvas.drawPath(path, paint);
}
void setRadius(int radius)
{
this.radius = radius;
invalidate(); //just like repaint method
}
public int getRadius()
{
return radius;
}
}
If the top coordinate remains fixed, you can change the height of the triangle to shrink/enlarge it.
Lets say the triangle is equilateral - all 3 sides have the same length. In this case:
So if the top vertex coordinates are (x, y), the bottom coordinates will be:
(x - side / 2, y + h)
And:
(x + side / 2, y + h)
So your path code should be written as:
float side = Math.sqrt(3) / 2 * height;
Path path = new Path();
path.moveTo(x, y);
path.lineTo(x - side / 2, y + height);
path.lineTo(x + side / 2, y + height);
path.close();

Categories

Resources