baloo
baloo

Reputation: 217

Custom views in android

I just started learning on how to make custom views .I created a drawable at the bottom of the screen and a small circle within it. The layout works perfectly fine but there is a small issue , the drawable in different resolution is cropped . Its works fine in S3 but in other devices the things are different. enter image description here

enter image description here

Here is my code :

 @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {


    int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
            MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY);
    int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
            MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.EXACTLY);


    setMeasuredDimension(childWidthMeasureSpec,childHeightMeasureSpec);


}


@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);

    Drawable outer_ring = getResources().getDrawable(R.drawable.outer_ring);

    System.out.println("Height now is : "+(canvas.getHeight()));

    Rect r1 = new Rect();
    r1.top = (canvas.getHeight()-outer_ring.getIntrinsicHeight());
    r1.bottom = canvas.getHeight();
    r1.left = (canvas.getWidth()-outer_ring.getIntrinsicWidth())/2;
    r1.right = canvas.getWidth()/2 +outer_ring.getIntrinsicWidth()/2;

    outer_ring.setBounds(r1);
    outer_ring.draw(canvas);

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    paint.setColor(Color.BLACK);
    paint.setStyle(Style.STROKE);
    paint.setStrokeWidth(10.0f);

    canvas.drawCircle(canvas.getWidth()/2, ((canvas.getHeight()-outer_ring.getIntrinsicHeight()/2)), 20, paint);
}

what should be the solution that this view appears same on all resolution

Here is my layout:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >



    <com.example.testing.CustomMenu
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/myView"
        />

    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:text="Button" />

</RelativeLayout>

Upvotes: 0

Views: 438

Answers (2)

Neil Townsend
Neil Townsend

Reputation: 6084

Edit

It turns out the the size of the canvas provided to onDraw isn't guaranteed to be the same size as the actual viewed size of the View. It is merely guaranteed to be sufficiently large. In your case, it is too big!

According to this question and answer, the key is to use the sizes returned in onSizeChanged as definitive for the current displayed size of the View. So you should retain the dimensions from onSizeChanged, and use them in onDraw to know the actual size you should draw to. ie,:

  • childWidthMeasureSpec and childHeightMeasureSpec should become class variables which are set in onSizeChanged.
  • In onDraw, use them instead of canvas.getWidth() and canvas.getHeight() respectively.

Whilst this behaviour seems a bit odd at first glance, it allows android to lower the number of canvas re-allocations it makes when sorting out sizes: If a View shrinks a bit (eg. with the appearance of a top bar) all it does it tell all concerned that the actual size is a bit smaller, rather than going through a canvas release and re-creation loop.

Probably less significant, in your java code, you request the dimensions of the View you are drawing. In the xml, you set those dimensions as wrap_content. This means that there is no explicit setting of the size of the View. A View like this should request the maximum size it can be, and the determine how large it wishes to be given that, and set that as its size. It's wiser to ensure that the dimesnions are fixed by setting the sizes of CustomMenu to match_patent, so that they are fixed.

However, in the absence of that, the parent View has given you some bounds. It appears that these bounds may, or may not, take account of the top bar, which is fair enough.

Upvotes: 2

Or B
Or B

Reputation: 1803

Try using this.getHeight() instead of canvas.getHeight() and this.getWidth() instead of canvas.getWidth().

(this relates to the View)

Upvotes: 0

Related Questions