How do I specify height/width of a custom view using onDraw? - android

I am implementing a custom view. I want to add a bunch of circles to a FrameLayout when a user touches a point in the ImageView hosted inside of the FrameLayout. Right now, I am drawing inside the onDraw method with a radius of 20. But, when I put it into the FrameLayout, it just shows a tiny corner. How can I tell the custom view that it should have a width/height of 20 as well? Is this something I should do within my custom view, or in the activity where I call addView once I instantiate the custom view?
public class MyCircle extends View {
Paint paint;
private static final int RADIUS = 20;
public MyCircle(Context context) {
super(context);
paint = new Paint();
paint.setColor(Color.WHITE);
setLayoutParams(new ViewGroup.LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
// LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams( RADIUS * 2 , RADIUS * 2 );
// setLayoutParams(layoutParams);
}
#Override
public void onDraw( Canvas canvas ) {
canvas.drawCircle(0, 0, RADIUS, paint );
}
}
The activity code is basically this (called from within a onTouch handler with X/Y coordinates):
MyCircle circle;
circle = new MyCircle(this);
circle.setX( x );
circle.setY( y );
FrameLayout root = (FrameLayout)findViewById(R.id.image_review_frame);
root.addView( circle );

Override onMeasure()
#Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
float density = context.getResources().getDisplayMetrics().density;
setMeasuredDimension (RADIUS * density,RADIUS * density);
return;
}
the code re:density is to convert dp to pixels (e.g. xhdpi displays will have density 2.0)

Related

Change a SeekBar position inside its container

Whenever extending the class, the bar will be drawn in the vertical center of its container. I need to place text above the bar and increasing the height (I am setting an arbitrary height on the view) causes a bunch of blank space beneath the bar. I've been googling for quite some time now but all I find is regarding the thumb mostly, and I need to draw the bar on the bottom of its container.
This is what I'm trying to achieve as a single view (notice how the bar's position in not centered):
The only "useful" code I could find was this:
Window window = ((Activity) getContext()).getWindow();
window.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams wmlp = window.getAttributes();
wmlp.y = getHeight() / 4;
window.setAttributes(wmlp);
But it has no effect whatsoever.
My custom class, nothing out of the ordinary:
public class RateSeekbar extends AppCompatSeekBar {
private Paint lettersPaint;
private Paint numberPaint;
// constructors and call to init()
private void init() {
lettersPaint = new Paint();
numberPaint = new Paint();
... // style the two different paints
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
... // get a couple of strings from resources and measure them
int middleHor = getWidth() / 2;
canvas.drawText(text1, getPaddingLeft(), 40, lettersPaint);
canvas.drawText(text2, getWidth() - text2Size - getPaddingRight(), 40, lettersPaint);
canvas.drawText(String.valueOf(getProgress()), middleHor - (text3Size / 2), 50, numberPaint);
}
}
Any ideas?

Android library overlay rectangle disappears

I have a library that shows a camera preview. I want to add a rectangle overlay on top of the preview. I tried 2 different approaches. But both of them display the rectangle shortly then disappear.
approach (using view.getOverlay)
mPreview.setZOrderMediaOverlay(true);
mPreview.setZOrderOnTop(true);
ViewGroup rootView = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.addView(mPreview);
final ViewOverlay overlay = mPreview.getOverlay();
final Bracket bracket = new Bracket();
mPreview.post(new Runnable() {
#Override
public void run() {
bracket.setBounds(0, 0, mPreview.getWidth(), mPreview.getHeight());
overlay.add(bracket);
}
});
approach (overriding draw function in surfaceview)
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(10);
//center
int x0 = canvas.getWidth()/2;
int y0 = canvas.getHeight()/2;
int dx = canvas.getHeight()/3;
int dy = canvas.getHeight()/3;
//draw guide box
canvas.drawRect(x0-dx, y0-dy, x0+dx, y0+dy, paint);
}
mPreview extends SurfaceView
Bracket extends Drawable
UPDATE
If I use setContentView instead of rootView.addView it works as expected. But in this case I can not remove the view.
I used a new Activity and setContentView. That solved the problem.
To remove the view I finished the action.

Marker position is changing based on the device screen width

In my application,I am setting an image in my imageview. I just need to place a marker on that imageview. I am doing it with onDraw function in my custom image view class.The problem is,for example if I take x position and y position as 40 respectively.The marker position shown above image in my mobile is different when compared with running same application on tablet.
I want a solution such that when I give coordinates then the position of marker on image in mobile and tablet appears same.
Here is the code my main activity:
public class PointOnImageActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_point_on_image);
CustomImag ev= new CustomImag(this);
ev.setBackgroundResource(R.drawable.stad);// set background
setContentView(ev);
}
}
Here is the code of my custom imageview class:
public class CustomImag extends ImageView
{
public CustomImag(Context context)
{
super(context);
}
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint mPaint = new Paint();
mPaint.setColor(Color.RED);
canvas.drawCircle(40,40,10,mPaint);
}
}
that's because 40 is pixel value, you actually need 40dp instead. so you can convert 40dp to px value dynamically, like this:
int pxValue1 = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, context.getResources()
.getDisplayMetrics());
int pxValue2 = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, context.getResources()
.getDisplayMetrics());
canvas.drawCircle(pxValue,pxValue,pxValue2,mPaint);
You have to position your custom View according to the screen dimensions. This way, no matter what size screen displays your app, your positioning will be relative.
In your onDraw(Canvas) method, you can get the screen dimensions and draw the circle using them. In the following example(which is mostly your code), I place the red circle at screen_width / 4 and screen_height / 4:
public class MyCustomImageViewActivity extends Activity{
CustomImag ev;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ev = new CustomImag(this);
ev.setBackgroundResource(R.drawable.stad);// set background
setContentView(ev);
}
public class CustomImag extends ImageView {
Paint mPaint;
public CustomImag(Context context) {
super(context);
mPaint = new Paint();
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
mPaint.setColor(Color.RED);
canvas.drawCircle(point.x / 4, point.y / 4, 10, mPaint);
}
}
}

Can you put/restrict a canvas to a layout

I'm quite new to Android programming and I'm stuck on how to get this right.
My situation is I want to draw a rectangle inside a RelatativeLayout and be able to change the shape of the rectangle dynamically relative to the size of the RelativeLayout which does not encompass the whole screen.
My problem is when I try to implement this, the size of the rectangle is still relative to the screen size
Is there a way where I can restrict the canvas size to the RelativeLayout size or is there a better way?
Here is part of my code from the maim activity
RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
blueView = new Bar(this);
blueView.setLayoutParams(rl);
blueLayout.addView(blueView);
And I also have a Bar class that extends View
public class Bar extends View{
Rect theBar;
public Bar(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
theBar = new Rect();
theBar.set(0, 0, canvas.getWidth(), canvas.getHeight()/2);
Paint blue = new Paint();
blue.setColor(Color.BLACK);
blue.setStyle(Paint.Style.FILL);
canvas.drawRect(theBar, blue);
}
}

Getting the width/height of a layout in Android

I'm wondering how to measure the dimensions of a view. In my case it is aan Absolute Layout. I've read the answers concerning those questions but I still don't get it.
This is my code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
AbsoluteLayout layoutbase = (AbsoluteLayout) findViewById(R.id.layoutbase);
drawOval();
}
public void drawOval(){ //, int screenWidth, int screenHeight){
AbsoluteLayout layoutbase = (AbsoluteLayout) findViewById(R.id.layoutbase);
int screenWidth = layoutbase.getWidth();
int screenHeight = layoutbase.getHeight();
Log.i("MyActivity", "screenWidth: " + screenWidth + ", screenHeight: " +screenHeight);
Coordinates c = new Coordinates(BUTTONSIZE,screenWidth,screenHeight);
...some code ...
((ViewGroup) layoutbase ).addView(mybutton, new AbsoluteLayout.LayoutParams(BUTTONSIZE, BUTTONSIZE, c.mX, c.mY));
mybutton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
showText(mybutton);
}
});
}
public void showText(View button){
int x = findViewById(LAYOUT).getWidth();
int y = findViewById(LAYOUT).getHeight();
Toast message = Toast.makeText(this, "x: " + x , Toast.LENGTH_SHORT);
message.show();
}
The getWidth() command works great in showText() but it does not in drawOval(). I know it looks a bit different there but I also used the int x = findViewById(LAYOUT).getWidth(); version in drawOval(), and x/y are always 0. I don't really understand why there seems to be no width/height at that earlier point. Even if I actually draw a Button on the Absolute Layout, getWidth() returns 0. Oviously I want to measure the sizes in drawOval().
I think will help you.
LinearLayout headerLayout = (LinearLayout)findviewbyid(R.id.headerLayout);
ViewTreeObserver observer = headerLayout .getViewTreeObserver();
observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// TODO Auto-generated method stub
int headerLayoutHeight= headerLayout.getHeight();
int headerLayoutWidth = headerLayout.getWidth();
headerLayout .getViewTreeObserver().removeGlobalOnLayoutListener(
this);
}
});
}
getWidth() is giving you 0 because onCreate is called before layout actually happens. Due to views being able to have dynamic positions and sizes based on attributes or other elements (fill_parent for example) there's not a fixed size for any given view or layout. At runtime there is a point in time (actually it can happen repeatedly depending on many factors) where everything is actually measured and laid out. If you really need the height and width, you'll have to get them later as you've discovered.
This specially deal with Dimensions so
Display display = getWindowManager().getDefaultDisplay();
int width = display.getWidth();
int height = display.getHeight();
This may help you in managing dimensions.
Note: This returns the display dimensions in pixels - as expected. But the getWidth() and getHeight() methods are deprecated. Instead you can use:
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
as also Martin Koubek suggested.
If your goal is to simply draw an oval on the screen, then consider creating your own custom View rather than messing around with AbsoluteLayout. Your custom View must override onDraw(android.graphics.Canvas), which will be called when the view should render its content.
Here is some extremely simple sample code that might help get you started:
public class MainActivity extends Activity {
private final Paint mPaint = new Paint();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new SampleView(this));
}
// create a nested custom view class that can draw an oval. if the
// "SampleView" is not specific to the Activity, put the class in
// a new file called "SampleView.java" and make the class public
// and non-static so that other Activities can use it.
private static class SampleView extends View {
public SampleView(Context context) {
super(context);
setFocusable(true);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.CYAN);
// smoothen edges
mPaint.setAntiAlias(true);
mPaint.setColor(Color.RED);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(4.5f);
// set alpha value (opacity)
mPaint.setAlpha(0x80);
// draw oval on canvas
canvas.drawOval(new RectF(50, 50, 20, 40), mPaint);
}
}
}
This give you screen resolution:
WindowManager wm = (WindowManager)context.getSystemService(context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
Point outSize = new Point();
display.getSize(outSize);
kabuko's answer is correct, but could be a little more clear, so let me clarify.
getWidth() and getHeight() are (correctly) giving you 0 because they have not been drawn in the layout when you call them. try calling the two methods on the button after addView() (after the view has been drawn and is present in the layout) and see if that gives you the expected result.
See this post for more information.

Categories

Resources