Customize view does not appear - android

When I comment out setContentView(boardView); in my Game.java my custom view in BoardView works fine and displays everything nicely... but onSizeChanged never gets called in BoardView.java... so I can't read the device width and height at runtime. If I leave setContentView uncommented onSizeChanged works... but the screen is blank!
I want to be able to read the screen width and height at runtime and set the sizes of my ImageViews at creation so they are the optimal size.
public class Game extends Activity implements OnClickListener{
private BoardView boardView;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
boardView = new BoardView(this);
setContentView(boardView); // when this line disabled, it looks ok
boardView.requestFocus();
}
public class BoardView extends View {
private final Game game;
private float width; // width of one unit
private float height; // height of one unit
public BoardView(Context context){
super(context);
this.game = (Game)context;
setFocusable(true);
setFocusableInTouchMode(true);
LinearLayout maincontainer = new LinearLayout(game);
maincontainer.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT));
maincontainer.setGravity(Gravity.CENTER);
maincontainer.setOrientation(LinearLayout.VERTICAL);
maincontainer.setBackgroundColor(Color.BLACK);
LinearLayout innercontainer = new LinearLayout(game);
innercontainer.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
innercontainer.setGravity(Gravity.CENTER);
innercontainer.setOrientation(LinearLayout.HORIZONTAL);
// declare a new table
TableLayout layout = new TableLayout(game);
layout.setLayoutParams(new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
// build a grid of ImageViews in a TableLayout
for (int f=1; f<=7; f++) {
TableRow tr = new TableRow(game);
for (int c=1; c<=7; c++) {
ImageView b = new ImageView(game);
b.setImageResource(R.drawable.neworb);
b.setOnClickListener(game);
tr.addView(b, 30,30); // I'd like to not use fixed values here
} // for
layout.addView(tr);
} // for
innercontainer.addView(layout);
maincontainer.addView(innercontainer);
game.setContentView(maincontainer);
}
#Override
protected void onSizeChanged(int w, int h, int oldw, int oldh){
width = w/9f;
height = width;
super.onSizeChanged(w, h, oldw, oldh);
}
}
}

Thought I solved my own problem. I was neglecting to place my my view building code withing the Overriden onDraw method. i.e.:
#Override
protected void onDraw(Canvas canvas)
{
LinearLayout maincontainer = new LinearLayout(this.game);
// etc..
I was just including it within the main class and not Overriding onDraw... which you gotta do when you extend View.

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?

Android: custom views get drawn at wrong x,y coordinates

I'm trying to create a custom view, inherit from view group, and layout custom sub-views inside this view group in a customized way. Basically I'm trying to create a calendar view similar to the one in outlook, where each event takes up screen height relative to its length.
I initialize an ArrayList of View in the ViewGroup's constructor, override onMeasure, onLayout and onDraw, and everything works well, except... the rendered views all render starting at (0,0), even though I set their left and right properties to other values. Their width and height come out ok, only their top and left are wrong.
This is the code, which I abbreviated for clarity and simplicity:
public class CalendarDayViewGroup extends ViewGroup {
private Context mContext;
private int mScreenWidth = 0;
private ArrayList<Event> mEvents;
private ArrayList<View> mEventViews;
// CalendarGridPainter is a class that draws the background grid.
// this one works fine so I didn't write its actual code here.
// it just takes a Canvas and draws lines on it.
// I also tried commenting out this class and got the same result,
// so this is DEFINITELY not the problem.
private CalendarGridPainter mCalendarGridPainter;
public CalendarDayViewGroup(Context context, Date date) {
super(context);
init(date, context);
}
//... other viewGroup constructors go here...
private void init(Date date, Context context) {
mContext = context;
// the following line loads events from a database
mEvents = AppointmentsRepository.getByDateRange(date, date);
// inflate all event views
mEventViews = new ArrayList<>();
LayoutInflater inflater = LayoutInflater.from(mContext);
for (int i = 0; i < mEvents.size(); i++) {
View view = getSingleEventView(mEvents.get(i), inflater);
mEventViews.add(view);
}
// set this flag so that the onDraw event is called
this.setWillNotDraw(false);
}
private View getSingleEventView(Event event, LayoutInflater inflater) {
View view = inflater.inflate(R.layout.single_event_view, null);
// [set some properties in the view's sub-views]
return view;
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec));
// get screen width and create a new GridPainter if needed
int screenWidth = MeasureSpec.getSize(widthMeasureSpec);
if (mScreenWidth != screenWidth)
{
mScreenWidth = screenWidth;
mCalendarGridPainter = new CalendarGridPainter(screenWidth);
}
int numChildren = mEvents.size();
for (int i = 0; i < numChildren; i++) {
View child = mEventViews.get(i);
Event event = mEvents.get(i);
// event width is the same as screen width
int specWidth = MeasureSpec.makeMeasureSpec(mScreenWidth, MeasureSpec.EXACTLY);
// event height is calculated by its length, the calculation was ommited here for simplicity
int eventHeight = 350; // actual calculation goes here...
int specHeight = MeasureSpec.makeMeasureSpec(eventHeight, MeasureSpec.EXACTLY);
child.measure(specWidth, specHeight);
}
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int numChildren = mEvents.size();
for (int i = 0; i < numChildren; i++) {
View child = mEventViews.get(i);
Event event = mEvents.get(i);
int eventLeft = 0;
int eventTop = (i + 1) * 200; // test code, make each event start 200 pixels after the previous one
int eventWidth = eventLeft + child.getMeasuredWidth();
int eventHeight = eventTop + child.getMeasuredHeight();
child.layout(eventLeft, eventTop, eventWidth, eventHeight);
}
}
#Override
protected void onDraw(Canvas canvas) {
// draw background grid
mCalendarGridPainter.paint(canvas);
// draw events
for (View view : mEventViews) {
view.draw(canvas);
}
super.onDraw(canvas);
}
}
For some reason, it seems like the way children are drawn with ViewGroups is that the ViewGroup translates the canvas to child's position then draws the child at 0,0.
But as it turns out, ViewGroup will handle all the drawing of children for you. I think if you simplify your onDraw() method you should be all set:
#Override
protected void onDraw(Canvas canvas) {
// draw background grid
mCalendarGridPainter.paint(canvas);
// draw events
super.onDraw(canvas);
}
Now that I'm looking at your code further, I noticed you are inflating your child views within the code for your ViewGroup. It would be best to do all that outside your ViewGroup, add those views using addView(), then use getChildCount() and getChildAt() to access the child views during onLayout().

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().

Why are View animations sometimes clipped?

I have a FrameLayout containing a subclassed SurfaceView and an ImageView. I want to do a TranslateAnimation on the ImageView. The only way I can make it work is to add a vacuous View to the FrameLayout. Otherwise, the ImageView gets clipped (to the bounds of the ImageView's position at the start of the animation) during the animation.
I'm curious as to why the empty sibling View allows the ImageView to animate correctly. The line that makes it work is marked with a comment in the code below.
public class Test5 extends Activity {
private static final String TAG = "Test5";
private MySurfaceView mMSV;
private ImageView mRectView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mMSV = new MySurfaceView(this);
mRectView = new ImageView(this);
ShapeDrawable sd = new ShapeDrawable(new RectShape());
sd.getPaint().setColor(Color.RED);
sd.setIntrinsicWidth(300);
sd.setIntrinsicHeight(100);
mRectView.setImageDrawable(sd);
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.addView(mMSV);
frameLayout.addView(mRectView, new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.WRAP_CONTENT,
FrameLayout.LayoutParams.WRAP_CONTENT));
// I don't know why the following line prevents clipping during
// animation. It simply adds a vacuous View.
frameLayout.addView(new View(this));
setContentView(frameLayout);
} // onCreate
public class MySurfaceView extends SurfaceView implements
SurfaceHolder.Callback {
public MySurfaceView(Context context) {
super(context);
getHolder().addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
Canvas can = mMSV.getHolder().lockCanvas();
can.drawColor(Color.GRAY);
mMSV.getHolder().unlockCanvasAndPost(can);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
Log.v(TAG, String.format("ACTION_UP, w=%d, h=%d", mRectView
.getWidth(), mRectView.getHeight()));
Animation an = new TranslateAnimation(0f, 200f, 0f, 200f);
// Animation an = new RotateAnimation(0f, 90f);
an.setStartOffset(200);
an.setDuration(1000);
mRectView.startAnimation(an);
}
return true;
}
} // MySurfaceView
} // Test5
This is interesting... I guess that the size of the FrameLayout is changed when a vacuous view is added. Your frame layout does not fill the parent, I wonder if you change the layout params to fill parent, what would happen?
I simplified your code to this:
FrameLayout frameLayout = new FrameLayout(this);
frameLayout.addView(mMSV);
frameLayout.addView(mRectView, 50, 50);
frameLayout.addView(new View(this)); //expands frame layout
It seems that the FrameLayout size itself equal to the last added child view. If you set addView(new View(this)) before adding a rectangle then it reduces to 50 x 50 and animation is clipped. I assume that addView(new View(this)); expands FrameLayout to the full screen.
I don't know how you figured that out, but it seemed to work for me, too. I had just switched to using a SurfaceView, and noticed that the animations were getting clipped. Adding an empty View stopped the clipping.
the trick was setting setClipChildren to the
layout that enclosed the view.

Categories

Resources