0

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>
19
  • can you log the r1.bottom values on both devices? are they same with device's height? Commented Aug 17, 2013 at 10:14
  • Ya i did that . In S3 its little less then the device height : 1134 then the actual 1280. In other device which has a resolution of 480 x 854 its showing exact value Commented Aug 17, 2013 at 10:23
  • can you put your complete onDraw(), there is missing part Commented Aug 17, 2013 at 10:31
  • I have added the code please check now Commented Aug 17, 2013 at 10:46
  • the problem is with getIntrinsicHeight() method, it just returns the unmodified height of ring, e.g if its height is 200px then it will return 200 both on s3 and on other devices as well. use getWidth() instead Commented Aug 17, 2013 at 10:50

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for your time and solution. That was really helpful and solved my problem. All the effort you put in was fruitful finally.
0

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

(this relates to the View)

1 Comment

I will try your selotion too but see Neils comment and solution. That solved my problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.