I have been trying to add two views with canvases to my activity programmatically, but it looks like only the first one is being added (I can tell by looking at the console output). What am I doing wrong?
Here is my code:
package app.com.example.android.drawtwoviews;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
DrawView drawView;
DrawView2 drawView2;
private LinearLayout root;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
drawView = new DrawView(this);
drawView.setBackgroundColor(Color.WHITE);
root.addView(drawView);
drawView2 = new DrawView2(this);
drawView2.setBackgroundColor(Color.WHITE);
root.addView(drawView2);
setContentView(root);
}
public class DrawView extends View {
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
System.out.println("DrawView1");
paint.setColor(Color.BLACK);
//paint.setStrokeWidth(3);
canvas.drawRect(30, 30, 80, 80, paint);
}
}
public class DrawView2 extends View {
Paint paint = new Paint();
public DrawView2(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
System.out.println("DrawView2");
paint.setColor(Color.BLUE);
paint.setStrokeWidth(3);
canvas.drawRect(300, 300, 400, 400, paint);
}
}
}
You are adding your views to the root without specifying layout parameters. That means they both get the default layout parameters of LinearLayout, which, for a vertical layout, is (MATCH_PARENT, WRAP_CONTENT).
Neither of your custom views overrides onMeasure(), which means both measure to their default suggested minimum size of 0×0.
This means that your LinearLayout is layouting two views with a requested size of 0×0 and a layout spec of (MATCH_PARENT, WRAP_CONTENT). The way this works out is a bit tricky, but your first child takes up the full screen height and your second child is 0px tall. Both children are full screen width. You can easily see this in the Hierarchy Viewer.
To fix the problem, you need to either specify layout params:
// in onCreate()
int width = LinearLayout.LayoutParams.MATCH_PARENT;
int height = 0;
int weight = 1;
LinearLayout.LayoutParams params =
new LinearLayout.LayoutParams(width, height, weight);
drawView = new DrawView(this);
drawView.setBackgroundColor(Color.WHITE);
root.addView(drawView, params); // note the extra argument
drawView2 = new DrawView2(this);
drawView2.setBackgroundColor(Color.WHITE);
root.addView(drawView2, params); // note the extra argument
Or you can modify the DrawViews so that they measure to some minimum size:
public class DrawView extends View {
// paint
// constructor
// onDraw
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
setMeasuredDimension(80, 80);
}
}
public class DrawView2 extends View {
// paint
// constructor
// onDraw
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
setMeasuredDimension(400, 400);
}
}
Try setting this flag in your view's contructor:
public DrawView(Context context) {
super(context);
setWillNotDraw(false);
}
This is needed because your view doesn't know that you wanna do custom drawing and onDraw() never gets called since there's nothing to draw.
Related
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?
I have a relative layout inside a scrollview, then i created a new view with this code:
public class DrawView extends View {
Paint paint = new Paint();
public DrawView(Context context) {
super(context);
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.BLACK);
paint.setStrokeWidth(2);
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(5, 5, 140, 140, paint);
}
}
Then i try to use layout.addView(DrawView) to add the new view to the relative layout, so it can be scrollable with the rest of the content, but is doesn't work, nothing shows up..
Am i missing something ?
Edit:
DrawView formas;
GifMovieView gif;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
final RelativeLayout layout = new RelativeLayout(this);
final ScrollView scrollView = new ScrollView(this);
//gif = new GifMovieView(this, t_img);
formas = new DrawView(this);
layout.addView(formas);
scrollView.addView(layout);
this.setContentView(scrollView);
inicializar();
load(layout);
}
You will probably want to override onMeasure() in your DrawView. Otherwise your view will have size of 0x0 pixels.
You can start with something as simple as
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(200, 200);
}
just to prove it works, but you will need to do some more meaningful, based on what are contents of your view.
Start from this article to see help on overriding onDraw() and onMeasure()
I want to draw a line between two views how it could possible using canvas
Its simple Take one linearLayout for it between two views
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="1dp"
android:background="#285A8C" > //Give Color As u want
</LinearLayout>
Thanks every one i got the following solution for this I am using three layouts the middle layout i used for canvas and draw points in that canvas on button on click event
DrawView.java
package demo.example;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
float [][] points;
public DrawView(Context context, float[][] points2, int k) {
super(context);
paint.setColor(Color.BLUE);
paint.setStrokeWidth(5);
this.points=points2;
}
#Override
public void onDraw(Canvas canvas) {
for(int i=0;i<points.length;i++)
{
canvas.drawLine(points[i][0],points[i][1],points[i][2],points[i][3], paint);
}
}
}
get points using following click listener
public class listener implements OnClickListener
{
int i;
listener(int k)
{
this.i=k;
}
public void onClick(View v)
{
for(int k=0;k<match1.length;k++)
{
if(match1[k].isClickable()==false)
{
if(match1[k].getId()==match2[i].getId())
{
points[k][0]=match1[k].getLeft();
points[k]1]=match1[k].getTop()+30+linearLayout2.getTop(); points[k][2]=200;
points[k][3]=match2[i].getTop()+30+linearLayout2.getTop();
match1[k].setCompoundDrawablesWithIntrinsicBounds(null, null,null,null);
match2[i].setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.bubble), null,null, null);
Toast.makeText(getBaseContext(),points[0]+"-"+points[1]+"-"+points[2]+"-"+points[3],Toast.LENGTH_SHORT).show();
ViewGroup.LayoutParams lp = new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
drawView = new DrawView(getBaseContext(),points,k);
linearLayout2.addView(drawView);
}
}
}
}
}
I ran into a mysterious ANR with my application which uses Pictures to record drawing command (paths, clips, text, etc.) and then draws these Pictures into Views held by a ScrollView. I was able to reproduce the issue with the below activity. In this activity, scrolling down in the ScrollView will produce an ANR as soon the bottom of the square is reached. Has anyone else ran into this? Any suggestions on how to avoid it?
public class AnrTest extends Activity
{
public void onCreate(Bundle saveInstBundle)
{
super.onCreate(saveInstBundle);
ScrollView sc = new ScrollView(this);
MyView view = new MyView(this);
sc.addView(view);
setContentView(sc);
}
class MyView extends View
{
Picture mPic;
public MyView(Context context)
{
super(context);
mPic = new Picture();
Canvas picCanvas = mPic.beginRecording(300, 900);
Paint p = new Paint();
p.setColor(Color.RED);
picCanvas.drawRect(20, 20, 100, 100, p);
picCanvas.clipRect(0, 0, 100, 100);
mPic.endRecording();
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//set a height larger than the screen, so that we can scroll.
setMeasuredDimension(300, 900);
}
protected void onDraw(Canvas canvas)
{
canvas.drawPicture(mPic);
}
}
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//set a height larger than the screen, so that we can scroll.
setMeasuredDimension(300, 900);
requestLayout();
}
You made the child larger than it's parent. requestLayout() will resolve your issue.
Having a problem with Android Custom components. Trying to draw an oval shape but nothing happening.
I have this line in layout xml file
<android.project.realtimedata.DemoView android:id="#+id/demoView"
android:layout_width="fill_parent" android:layout_height="wrap_content" />
Here is the code for my custom component class.
package android.project.realtimedata;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.view.View;
public class DemoView extends View{
ShapeDrawable thisGauge = null;
public DemoView(Context context){
super(context);
init();
}
public DemoView(Context context, AttributeSet attrs)
{
super(context, attrs);
init();
}
private void init(){
int x = 10;
int y = 10;
int width = 300;
int height = 50;
thisGauge = new ShapeDrawable(new OvalShape());
thisGauge.getPaint().setColor(0xff74AC23);
thisGauge.setBounds(x, y, x + width, y + height);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
thisGauge.draw(canvas);
}
}
I also have this line in onCreate method of Activity
demoView = (DemoView) findViewById(R.id.demoView);
Whenever I launch the application the custom component is not there.
I tried looking at it from LogCat and it definitely gets created.
What am I missing here?
Thanks in advance.
Make sure that you calling findViewById(R.id.demoView) after calling setContentView(...). To ensure that your view is being inflated, you can call Log.d("DemoView", "Created") from inside your DemoView constructor.