Android自定义控件之我的电话小键盘


关于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自带电话应用的实现。可见,在开发中,灵活运用自定义的控件,可以实现独特而富有魅力的效果!

相关内容