自定义view android获取宽高,自定义View获取宽高

自定义View的时候经常少不了获取View的宽高信息,当然不一定是自定义View的时候才会需要获取宽高信息,其他情况下我们也会有这样的需求,获取方式和获取的时机也十分讲究.下面分别从这几个api讲起:

1.构造方法

2.onFinishInflate

3.onSizeChanged

4.onMeasure

5.onWindowFocusChanged

6.onLayout

7.View.getViewTreeObserver().addOnGlobalLayoutListener

以上几种方式获取的时机各有不同,且回调次数和条件也不相同.先来看看demo,下面是一个自定义的FrameLayout的子类,包含2个TextView控件.

布局如下:

1. <?xml version="1.0" encoding="utf-8"?>

2.

3. xmlns:android="http://schemas.android.com/apk/res/android"

4. xmlns:tools="http://schemas.android.com/tools"

5. android:layout_width="match_parent"

6. android:layout_height="match_parent"

7. >

8.

9. android:layout_width="match_parent"

10. android:layout_height="300dp"

11. android:background="#f00"

12. android:gravity="center"

13. android:text="First Part"

14. android:textSize="30sp"/>

16.

17. android:layout_width="match_parent"

18. android:layout_height="match_parent"

19. android:layout_marginTop="300dp"

20. android:background="#00f"

21. android:gravity="center"

22. android:text="Second Part"

23. android:textSize="30sp"/>

24.

代码:

1. /**

2. * Created by mChenys on 2015/12/23.

3. */

4. public class TestLayout extends FrameLayout {

5. private View mFistPart, mSecondPart;

6. private int mFistHeight, mSecondHeight;

8. public TestLayout(Context context) {

9. this(context, null);

10. }

12. public TestLayout(Context context, AttributeSet attrs) {

13. this(context, attrs, 0);

14. }

16. public TestLayout(Context context, AttributeSet attrs, int defStyleAttr) {

17. super(context, attrs, defStyleAttr);

18. System.out.println("----------Constructor-------------");

19. mFistPart = getChildAt(0);

20. mSecondPart = getChildAt(1);

21. System.out.println("mFistPart:" + mFistPart + " mSecondPart:" + mSecondPart);

22. }

24. @Override

25. protected void onFinishInflate() {

26. super.onFinishInflate();

27. mFistPart = getChildAt(0);

28. mSecondPart = getChildAt(1);

29. mFistHeight = mFistPart.getMeasuredHeight();

30. mSecondHeight = mSecondPart.getMeasuredHeight();

31. System.out.println("----------onFinishInflate-------------");

32. System.out.println("mFistPart:" + mFistPart + " mSecondPart:" + mSecondPart);

33. System.out.println("mFistPart.getMeasuredHeight():" + mFistHeight + " mSecondPart.getMeasuredHeight():" + mSecondHeight);

34. System.out.println("mFistPart.getHeight():" + mFistPart.getHeight() + " mSecondPart.getHeight():" + mSecondPart.getHeight());

35. mFistPart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

36. @TargetApi(Build.VERSION_CODES.JELLY_BEAN)

37. @Override

38. public void onGlobalLayout() {

39. System.out.println("----------addOnGlobalLayoutListener-------------");

40. mFistPart.getViewTreeObserver().removeOnGlobalLayoutListener(this);

41. System.out.println("mFistPart.getMeasuredHeight():" + mFistPart.getMeasuredHeight() + "mFistPart.getHeight():" + mFistPart.getMeasuredHeight());

42. }

43. });

44. mSecondPart.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {

45. @TargetApi(Build.VERSION_CODES.JELLY_BEAN)

46. @Override

47. public void onGlobalLayout() {

48. System.out.println("----------addOnGlobalLayoutListener-------------");

49. mSecondPart.getViewTreeObserver().removeOnGlobalLayoutListener(this);

50. System.out.println("mFistPart.getMeasuredHeight():" + mSecondPart.getMeasuredHeight() + "mFistPart.getHeight():" + mSecondPart.getMeasuredHeight());

51. }

52. });

53. }

55. @Override

56. protected void onSizeChanged(int w, int h, int oldw, int oldh) {

57. super.onSizeChanged(w, h, oldw, oldh);

58. mFistHeight = mFistPart.getMeasuredHeight();

59. mSecondHeight = mSecondPart.getMeasuredHeight();

60. System.out.println("----------onSizeChanged-------------");

61. System.out.println("mFistPart:" + mFistPart + " mSecondPart:" + mSecondPart);

62. System.out.println("mFistPart.getMeasuredHeight():" + mFistHeight + " mSecondPart.getMeasuredHeight():" + mSecondHeight);

63. System.out.println("mFistPart.getHeight():" + mFistPart.getHeight() + " mSecondPart.getHeight():" + mSecondPart.getHeight());

64. }

66. @Override

67. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

68. super.onMeasure(widthMeasureSpec, heightMeasureSpec);

69. mFistHeight = mFistPart.getMeasuredHeight();

70. mSecondHeight = mSecondPart.getMeasuredHeight();

71. System.out.println("----------onMeasure-------------");

72. System.out.println("mFistPart:" + mFistPart + " mSecondPart:" + mSecondPart);

73. System.out.println("mFistPart.getMeasuredHeight():" + mFistHeight + " mSecondPart.getMeasuredHeight():" + mSecondHeight);

74. System.out.println("mFistPart.getHeight():" + mFistPart.getHeight() + " mSecondPart.getHeight():" + mSecondPart.getHeight());

75. }

77. @Override

78. public void onWindowFocusChanged(boolean hasWindowFocus) {

79. super.onWindowFocusChanged(hasWindowFocus);

80. mFistHeight = mFistPart.getMeasuredHeight();

81. mSecondHeight = mSecondPart.getMeasuredHeight();

82. System.out.println("----------onWindowFocusChanged-------------");

83. System.out.println("mFistPart:" + mFistPart + " mSecondPart:" + mSecondPart + " hasWindowFocus:" + hasWindowFocus);

84. System.out.println("mFistPart.getMeasuredHeight():" + mFistHeight + " mSecondPart.getMeasuredHeight():" + mSecondHeight);

85. System.out.println("mFistPart.getHeight():" + mFistPart.getHeight() + " mSecondPart.getHeight():" + mSecondPart.getHeight());

86. }

88. @Override

89. protected void onLayout(boolean changed, int left, int top, int right, int bottom) {

90. super.onLayout(changed, left, top, right, bottom);

91. mFistHeight = mFistPart.getMeasuredHeight();

92. mSecondHeight = mSecondPart.getMeasuredHeight();

93. System.out.println("----------onLayout-------------");

94. System.out.println("mFistPart:" + mFistPart + " mSecondPart:" + mSecondPart);

95. System.out.println("mFistPart.getMeasuredHeight():" + mFistHeight + " mSecondPart.getMeasuredHeight():" + mSecondHeight);

96. System.out.println("mFistPart.getHeight():" + mFistPart.getHeight() + " mSecondPart.getHeight():" + mSecondPart.getHeight());

97. }

98. }

上面每一种方法都分别打印了该自定义控件的2个子控件引用,2个子控件的getMeasuredHeight和2个子控件的getHeight,来看下log:

**[html]** [view plain](http://blog.csdn.net/mchenys/article/details/50408819# "view plain") [copy](http://blog.csdn.net/mchenys/article/details/50408819# "copy")

1. System.out: ----------Constructor-------------

2. System.out: mFistPart:null mSecondPart:null

3. System.out: ----------onFinishInflate-------------

4. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-0,0} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,0-0,0}

5. System.out: mFistPart.getMeasuredHeight():0 mSecondPart.getMeasuredHeight():0

6. System.out: mFistPart.getHeight():0 mSecondPart.getHeight():0

7. System.out: ----------onMeasure-------------

8. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-0,0} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,0-0,0}

9. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():328

10. System.out: mFistPart.getHeight():0 mSecondPart.getHeight():0

12. System.out: ----------onMeasure-------------

13. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-0,0} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,0-0,0}

14. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():424

15. System.out: mFistPart.getHeight():0 mSecondPart.getHeight():0

16. System.out: ----------onSizeChanged-------------

17. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-0,0} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,0-0,0}

18. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():424

19. System.out: mFistPart.getHeight():0 mSecondPart.getHeight():0

20. System.out: ----------onLayout-------------

21. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-720,600} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,600-720,1024}

22. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():424

23. System.out: mFistPart.getHeight():600 mSecondPart.getHeight():424

24. System.out: ----------addOnGlobalLayoutListener-------------

25. System.out: mFistPart.getMeasuredHeight():600mFistPart.getHeight():600

26. System.out: ----------addOnGlobalLayoutListener-------------

27. System.out: mFistPart.getMeasuredHeight():424mFistPart.getHeight():424

28. System.out: ----------onWindowFocusChanged-------------

29. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-720,600} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,600-720,1024} hasWindowFocus:true

30. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():424

31. System.out: mFistPart.getHeight():600 mSecondPart.getHeight():424

32. System.out: ----------onMeasure-------------

33. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-720,600} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,600-720,1024}

34. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():424

35. System.out: mFistPart.getHeight():600 mSecondPart.getHeight():424

36. System.out: ----------onLayout-------------

37. System.out: mFistPart:android.support.v7.widget.AppCompatTextView{fb4034c V.ED..... ......ID 0,0-720,600} mSecondPart:android.support.v7.widget.AppCompatTextView{16ebf95 V.ED..... ......ID 0,600-720,1024}

38. System.out: mFistPart.getMeasuredHeight():600 mSecondPart.getMeasuredHeight():424

39. System.out: mFistPart.getHeight():600 mSecondPart.getHeight():424

总结:

1.从执行顺序分析

Constructor->onFinishInflate->onMeasure->onSizeChanged->onLayout->addOnGlobalLayoutListener->onWindowFocusChanged->onMeasure->onLayout

由上可知,onMeasure和onLayout会被多次调用.

2.从api上分析

1)Constructor:构造方法,View初始化的时候调用,在这里是无法获取其子控件的引用的.更加无法获取宽高了.

2)onFinishInflate:当布局初始化完毕后回调,在这里可以获取所有直接子View的引用,但是无法获取宽高.

3)onMeasure:当测量控件宽高时回调,当调用了requestLayout()也会回调onMeasure.在这里一定可以通过getMeasuredHeight()和getMeasuredWidth()来获取控件的高和宽,但不一定可以通过getHeight()和getWidth()来获取控件宽高,因为getHeight()和getWidth()必须要等onLayout方法回调之后才能确定.

4)onSizeChanged:当控件的宽高发生变化时回调,和onMeasure一样,一定可以通过getMeasuredHeight()和getMeasuredWidth()来获取控件的高和宽,因为它是在onMeasure方法执行之后和onLayout方法之前回调的.

5)onLayout:当确定控件的位置时回调,当调用了requestLayout()也会回调onLayout.在这里一定可以通过getHeight()和getWidth()获取控件的宽高,同时由于onMeasure方法比onLayout方法先执行,所以在这里也可以通过getMeasuredHeight()和getMeasuredWidth()来获取控件的高和宽.

6)addOnGlobalLayoutListener:当View的位置确定完后会回调改监听方法,它是紧接着onLayout方法执行而执行的,只要onLayout方法调用了,那么addOnGlobalLayoutListener的监听器就会监听到.在这里getMeasuredHeight()和getMeasuredWidth()和getHeight()和getWidth()都可以获取到宽高.

7)onWindowFocusChanged:当View的焦点发送改变时回调,在这里getMeasuredHeight()和getMeasuredWidth()和getHeight()和getWidth()都可以获取到宽高.Activity也可以通过重写该方法来判断当前的焦点是否发送改变了;需要注意的是这里View获取焦点和失去焦点都会回调.

那么,上面分析了那么多方法来获取控件的宽高,那到底用哪一种呢?

具体要用哪一种,是需要根据View的宽高是否会发生变化来决定:

1.如果自定义的View在使用的过程中宽高信息是不会改变的,那么上面方式3~方式7都可以使用.

2.如果自定义的View在使用过程中宽高信息都会发生改变的,而且又需要获取一开始时的宽高信息,那么建议使用View.getViewTreeObserver().addOnGlobalLayoutListener(OnGlobalLayoutListener listener)的方式,因为这种方式有getViewTreeObserver().removeOnGlobalLayoutListener(this);来避免回调函数因宽高信息的变化而多次调用,如果使用其他方式的话,就要借助额外的变量来保证获取到的宽高是View的初始高度.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值