Android OnMeasure

http://stackoverflow.com/questions/13099652/custom-rotating-of-an-image-view

onMeasure() is your opportunity to tell Android how big you want your custom view to be dependent the layout constraints provided by the parent; it is also your custom view's opportunity to learn what those layout constraints are (in case you want to behave differently in a match_parent situation than a wrap_content situation). These constraints are packaged up into the MeasureSpec values that are passed into the method. Here is a rough correlation of the mode values:

  • EXACTLY means the layout_width or layout_height value was set to a specific value. You should probably make your view this size. This can also get triggered when match_parent is used, to set the size exactly to the parent view (this is layout dependent in the framework).
  • AT_MOST typically means the layout_width or layout_height value was set to match_parent or wrap_content where a maximum size is needed (this is layout dependent in the framework), and the size of the parent dimension is the value. You should not be any larger than this size.
  • UNSPECIFIED typically means the layout_width or layout_height value was set to wrap_content with no restrictions. You can be whatever size you would like. Some layouts also use this callback to figure out your desired size before determine what specs to actually pass you again in a second measure request.

The contract that exists with onMeasure() is that setMeasuredDimension() MUST be called at the end with the size you would like the view to be. This method is called by all the framework implementations, including the default implementation found in View, which is why it is safe to call super instead if that fits your use case.

Granted, because the framework does apply a default implementation, it may not be necessary for you to override this method, but you may see clipping in cases where the view space is smaller than your content if you do not, and if you lay out your custom view with wrap_content in both directions, your view may not show up at all because the framework doesn't know how large it is!

Generally, if you are overriding View and not another existing widget, it is probably a good idea to provide an implementation, even if it is as simple as something like this:

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

    int desiredWidth = 100;
    int desiredHeight = 100;

    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int width;
    int height;

    //Measure Width
    if (widthMode == MeasureSpec.EXACTLY) {
        //Must be this size
        width = widthSize;
    } else if (widthMode == MeasureSpec.AT_MOST) {
        //Can't be bigger than...
        width = Math.min(desiredWidth, widthSize);
    } else {
        //Be whatever you want
        width = desiredWidth;
    }

    //Measure Height
    if (heightMode == MeasureSpec.EXACTLY) {
        //Must be this size
        height = heightSize;
    } else if (heightMode == MeasureSpec.AT_MOST) {
        //Can't be bigger than...
        height = Math.min(desiredHeight, heightSize);
    } else {
        //Be whatever you want
        height = desiredHeight;
    }

    //MUST CALL THIS
    setMeasuredDimension(width, height);
}

Hope that Helps.

share edit flag
 
 
Hey @Devunwired nice explanation the best I read so far. Your explanation answered a lot of questions I had and cleared some doubts, but still one remains which is : If my custom view is inside a ViewGroup alongside with some others Views (doesn't matter which types) that ViewGroup will get all his children an for each one probe for their LayoutParams constraint and ask each child to measure it self accordingly to their constraints? –   pharaoh  Sep 14 '12 at 2:32
 
Yes, that is what the measureChildren() method of ViewGroup does during the measure/layout process. –   Devunwired  Sep 14 '12 at 14:58
 
Great explanation, thanks. Just a remark: you mistyped height = heightSize; for height = widthSize;. –   kaneda  Nov 22 '12 at 12:18
 
Ah! Thank you for that, updated. –   Devunwired  Nov 24 '12 at 4:23
9
 
Note that this code won't do if you override onMeasure of any ViewGroup subclass. Your subviews won't show up and will all have a size of 0x0. If you need to override onMeasure of a custom ViewGroup, change widthMode, widthSize, heightMode and heightSize, compile them back to measureSpecs using MeasureSpec.makeMeasureSpec and pass resulting integers to super.onMeasure. –   Alexey  Jul 19 '13 at 9:19
 
@Alexey Yes, if you are customizing a ViewGroup you are also responsible for measuring the child views. You could just call super, but you're more likely better off calling measureChildren() or measuring each child individually if that better fits the application. –   Devunwired  Jul 20 '13 at 0:29
 
Gave this a try and noticed that if you set your size of your customView to wrap_content, it does actually specify a value so it never hits the MeasureSpec.UNSPECIFIED –   jonney  Aug 9 '13 at 16:15
 
Indeed one should never think that there is hard link between layout params and MeasureSpec, but instead use the guides of "use this size", "no larger than", or "be what you want" instead. MayViewGroup types do not allow children to be any larger than themselves, but others do. In cases where the layout constrains the child, UNSPECIFIED by itself is uncommon. –   Devunwired  Aug 9 '13 at 18:35
 
this is Great answer –   Mohammed Subhi Sheikh Quroush  Nov 15 '13 at 16:34
4
 
Google should replace their documentation with this, thanks for the REALLY clear explanation –   S-K'  Feb 21 '14 at 20:19
 
Fantastic answer. Note that, as per Google's documentation, it's the View's responsibility to handle padding. –   jonstaff  Mar 6 '14 at 21:41
 
This is the best custom view explanation I've seen so far on the web. +1 –   Tiago  May 27 '14 at 23:05
 
Very nice explanation.. –   Mufazzal  Jun 26 '14 at 11:25

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值