关于Android的自定义控件,之前也写了两个,一个是简单地继承View,另一个通过继承Layout实现一个省市联动控件。这篇,将通过继承ViewGroup来实现一个电话拨打小键盘。本人一贯风格,懒得罗里吧嗦讲一大堆,直接上图上代码,一切尽在注释中!
1、MyPhoneCard.java
1./**
2. *
3. * 自定义一个4*3的拨打电话的布局控件,
4. *
5. *
6. */
7.public class MyPhoneCard extends ViewGroup{ 8.
9. private static final int COLUMNS = 3; 10. private static final int ROWS = 4; 11. private static final int NUM_BUTTON = COLUMNS*ROWS; 12.
13. private View[] mButtons = new View[NUM_BUTTON]; 14.
15. private int mButtonWidth; 16. private int mButtonHeight; 17. private int mPaddingLeft; 18. private int mPaddingRight; 19. private int mPaddingTop; 20. private int mPaddingBottom; 21. private int mWidthInc; 22. private int mHeightInc; 23. private int mWidth; 24. private int mHeight; 25.
26. public MyPhoneCard(Context context) { 27. super(context); 28. }
29.
30. public MyPhoneCard(Context context, AttributeSet attrs){ 31. super(context,attrs); 32. }
33.
34. public MyPhoneCard(Context context, AttributeSet attrs, int defStyle){ 35. super(context,attrs,defStyle); 36. }
37.
38. /** 39. * 当从xml将所有的控件都调入内存后,触发的动作
40. * 在这里获取控件的大小,并计算整个ViewGroup需要的总的宽和高
41. */
42. @Override 43. protected void onFinishInflate(){ 44. super.onFinishInflate(); 45. final View[] btns = mButtons; 46.
47. for(int i=0; i<NUM_BUTTON; i++){ 48. btns[i] = this.getChildAt(i); 49. btns[i].measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
50. }
51.
52. //缓存大小 53. final View child = btns[0]; 54. mButtonWidth = child.getMeasuredWidth();
55. mButtonHeight = child.getMeasuredHeight();
56. mPaddingLeft = this.getPaddingLeft(); 57. mPaddingRight = this.getPaddingRight(); 58. mPaddingTop = this.getPaddingTop(); 59. mPaddingBottom = this.getPaddingBottom(); 60. mWidthInc = mButtonWidth + mPaddingLeft + mPaddingRight;
61. mHeightInc = mButtonHeight + mPaddingTop + mPaddingBottom;
62.
63. mWidth = mWidthInc*COLUMNS;
64. mHeight = mHeightInc*ROWS;
65.
66. Log.v("Finish Inflate:", "btnWidth="+mButtonWidth+",btnHeight="+mButtonHeight+",padding:"+mPaddingLeft+","+mPaddingTop+","+mPaddingRight+","+mPaddingBottom); 67.
68.
69.
70. }
71.
72. /** 73. * 这个方法在onFinishInflate之后,onLayout之前调用。这个方面调用两次
74. */
75. @Override 76. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec){ 77. super.onMeasure(widthMeasureSpec, heightMeasureSpec); 78. Log.v("ViewGroup SIZE:width=", mWidth+""); 79. Log.v("ViewGroup SIZE: height=",mHeight+""); 80. final int width = resolveSize(mWidth, widthMeasureSpec);//传入我们希望得到的宽度,得到测量后的宽度 81. final int height = resolveSize(mHeight,heightMeasureSpec);//传入我们希望得到的高度,得到测量后的高度 82. Log.v("ViewGroup Measured SIZE: width=", width+""); 83. Log.v("ViewGroup Measured SIZE: height=", height+""); 84. //重新计算后的结果,需要设置。下面这个方法必须调用 85. setMeasuredDimension(width, height);
86. }
87.
88. /** 89. * 这个方法在onMeasure之后执行,这个自定义控件中含有12个子控件(每个小键),所以,重写这个方法,
90. * 调用每个键的layout,将他们一个一个布局好
91. * 就是4*3的放置,很简单,一个嵌套循环搞定
92. */
93. @Override 94. protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 95. final View[] buttons = mButtons; 96. int i = 0; 97. Log.v("BOTTOM:", bottom+""); 98. Log.v("TOP", top+""); 99.
100. int y = (bottom - top) - mHeight + mPaddingTop;//这里其实bottom-top=mHeight,所以y=mPaddingTop 101. Log.v("Y=", y+""); 102. for(int row=0; row<ROWS; row++){ 103. int x = mPaddingLeft; 104. for(int col = 0; col < COLUMNS; col++){ 105. buttons[i].layout(x, y, x+mButtonWidth, y+mButtonHeight);
106. x = x + mWidthInc;
107. i++;
108. }
109. y = y + mHeightInc;
110. }
111. }
112.
113.}
2、布局文件:
1.<?xml version="1.0" encoding="utf-8"?>
2.<demo.phone.card.MyPhoneCard 3. xmlns:Android="http://schemas.android.com/apk/res/android" 4. Android:id = "@+id/dialpad" 5. Android:paddingLeft="7dp" 6. Android:paddingRight="7dp" 7. Android:paddingTop="6dp" 8. Android:paddingBottom="6dp" 9. Android:layout_gravity="center" 10. Android:layout_width="wrap_content" 11. Android:layout_height="wrap_content" 12. Android:layout_marginBottom="5dp"> 13.
14. <ImageButton Android:id="@+id/one" 15. Android:src="@drawable/dial_num_1_no_vm" 16. style="@style/dial_btn_style" 17. /> 18.
19. <ImageButton Android:id="@+id/two" 20. Android:src="@drawable/dial_num_2" 21. style="@style/dial_btn_style"/> 22.
23. <ImageButton Android:id="@+id/three" 24. Android:src="@drawable/dial_num_3" 25. style="@style/dial_btn_style"/> 26.
27. <ImageButton Android:id="@+id/four" 28. Android:src="@drawable/dial_num_4" 29. style="@style/dial_btn_style"/> 30.
31. <ImageButton Android:id="@+id/five" 32. Android:src="@drawable/dial_num_5" 33. style="@style/dial_btn_style"/> 34.
35. <ImageButton Android:id="@+id/six" 36. Android:src="@drawable/dial_num_6" 37. style="@style/dial_btn_style"/> 38.
39. <ImageButton Android:id="@+id/seven" 40. Android:src="@drawable/dial_num_7" 41. style="@style/dial_btn_style"/> 42.
43. <ImageButton Android:id="@+id/eight" 44. Android:src="@drawable/dial_num_8" 45. style="@style/dial_btn_style"/> 46.
47. <ImageButton Android:id="@+id/nine" 48. Android:src="@drawable/dial_num_9" 49. style="@style/dial_btn_style"/> 50.
51. <ImageButton Android:id="@+id/star" 52. Android:src="@drawable/dial_num_star" 53. style="@style/dial_btn_style"/> 54.
55. <ImageButton Android:id="@+id/zero" 56. Android:src="@drawable/dial_num_0" 57. style="@style/dial_btn_style"/> 58.
59. <ImageButton Android:id="@+id/pound" 60. Android:src="@drawable/dial_num_pound" 61. style="@style/dial_btn_style"/> 62.
63.</demo.phone.card.MyPhoneCard> 这样,就实现了上图的小键盘。这个例子参考Android自带电话应用的实现。可见,在开发中,灵活运用自定义的控件,可以实现独特而富有魅力的效果!
本篇文章来源于 Linux公社网站(www.linuxidc.com) 原文链接:http://www.linuxidc.com/Linux/2011-10/46090.htm