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>
baloo
  • 217
  • 1
  • 8
  • can you log the r1.bottom values on both devices? are they same with device's height? – Onur A. Aug 17 '13 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 – baloo Aug 17 '13 at 10:23
  • can you put your complete onDraw(), there is missing part – Onur A. Aug 17 '13 at 10:31
  • I have added the code please check now – baloo Aug 17 '13 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 – Onur A. Aug 17 '13 at 10:50
  • No help . showing this error when using getHeight() "The method getHeight() is undefined for the type Drawable" – baloo Aug 17 '13 at 10:56
  • I tried changing drawable to bitmapdrawable and get the height but then too its showing the same. moreover I check the value using getHeight and getIntrinsicHeight, they appears to be same. I know the difference but not able to figure it out – baloo Aug 17 '13 at 11:06
  • hımm do you have to draw it at bottom? center works too ? – Onur A. Aug 17 '13 at 11:25
  • ya i can do that but i was trying to make menu item similar to that in catch application. I already implemented their jar and got success but I thought of making one on my own . – baloo Aug 17 '13 at 11:28
  • hımm, if you dont have to; try to make the drawable also circle with gradient, – Onur A. Aug 17 '13 at 11:59
  • What happens if you don't override `onMeasure`? – Neil Townsend Aug 19 '13 at 19:27
  • I didn't tried that Neil but I will make the changes and let you know – baloo Aug 20 '13 at 09:48
  • @NeilTownsend I tried that but no change . Still the bitmap is cropped from bottom . – baloo Aug 26 '13 at 06:46
  • @NeilTownsend IF I am using Windows.Feature_No_title and this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN); The display will be correct can you justify this – baloo Aug 26 '13 at 06:50
  • Could you post the layout xml please? That might clarify something in my thinking. It's an interesting issue! – Neil Townsend Aug 26 '13 at 09:10
  • @NeilTownsend I have added the layout xml please check now. – baloo Sep 02 '13 at 06:07
  • I've put an answer below, did it help? – Neil Townsend Sep 03 '13 at 21:09
  • @NeilTownsend Ya i tried to implement your answer but the result was same... I got busy wd something so not able to do more R & D but I will give it another shot today... hope i am able to solve it... If i get the answer I will share it here...Its a strange behavior BTW – baloo Sep 04 '13 at 03:56
  • Fair point, I've done some more research and updated the answer. – Neil Townsend Sep 04 '13 at 07:44

2 Answers2

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.

Community
  • 1
  • 1
Neil Townsend
  • 6,024
  • 5
  • 35
  • 52
  • Thanks for your time and solution. That was really helpful and solved my problem. All the effort you put in was fruitful finally. – baloo Sep 05 '13 at 07:41
0

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

(this relates to the View)

Or B
  • 1,675
  • 5
  • 20
  • 41
  • I will try your selotion too but see Neils comment and solution. That solved my problem – baloo Sep 05 '13 at 07:43