在pjsip视频通信开发(上层应用)之EditText重写中我制作了一个显示输入内容的EditText,这里将制作一个数字键盘,其实跟计算器一样,最多的就是用TableLayout来实现,内部通过权重(weight)来实现布局的统一,上层实现按键事件触发回调实现内容的输出。
键盘布局:
[] 
<?xml version="1.0" encoding="utf-8"?>  
  
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"  
    android:layout_width="match_parent"  
    android:layout_height="match_parent" >  
  
    <TableRow  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="1" >  
  
        <ImageButton  
            android:id="@+id/button1"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_one"  
            android:src="@drawable/dial_num_1" />  
  
        <ImageButton  
            android:id="@+id/button2"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_two"  
            android:src="@drawable/dial_num_2" />  
  
        <ImageButton  
            android:id="@+id/button3"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_three"  
            android:src="@drawable/dial_num_3" />  
    </TableRow>  
  
    <TableRow  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="1" >  
  
        <ImageButton  
            android:id="@+id/button4"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_four"  
            android:src="@drawable/dial_num_4" />  
  
        <ImageButton  
            android:id="@+id/button5"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_five"  
            android:src="@drawable/dial_num_5" />  
  
        <ImageButton  
            android:id="@+id/button6"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_six"  
            android:src="@drawable/dial_num_6" />  
    </TableRow>  
  
    <TableRow  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="1" >  
  
        <ImageButton  
            android:id="@+id/button7"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_seven"  
            android:src="@drawable/dial_num_7" />  
  
        <ImageButton  
            android:id="@+id/button8"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_eight"  
            android:src="@drawable/dial_num_8" />  
  
        <ImageButton  
            android:id="@+id/button9"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_nine"  
            android:src="@drawable/dial_num_9" />  
    </TableRow>  
  
    <TableRow  
        android:layout_width="match_parent"  
        android:layout_height="wrap_content"  
        android:layout_weight="1" >  
  
        <ImageButton  
            android:id="@+id/buttonstar"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_star"  
            android:src="@drawable/dial_num_star" />  
  
        <ImageButton  
            android:id="@+id/button0"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_zero"  
            android:src="@drawable/dial_num_0" />  
  
        <ImageButton  
            android:id="@+id/buttonpound"  
            style="@style/DialtactsDialpadButtonStyle"  
            android:contentDescription="@string/description_image_button_pound"  
            android:src="@drawable/dial_num_pound" />  
    </TableRow>  
  
</TableLayout>  
 
显示效果如下:
布局设置好之后,我们就要调用布局,设置监听实现回调。
[java]  
package com.jwzhangjie.pjsip.widgets;  
  
import java.util.HashMap;  
import java.util.Map;  
  
import com.jwzhangjie.pjsip.R;  
  
import android.annotation.SuppressLint;  
import android.content.Context;  
import android.media.ToneGenerator;  
import android.util.AttributeSet;  
import android.util.SparseArray;  
import android.view.View;  
import android.view.View.OnClickListener;  
import android.view.KeyEvent;  
import android.view.LayoutInflater;  
import android.widget.FrameLayout;  
import android.widget.ImageButton;  
  
public class Dialpad extends FrameLayout implements OnClickListener {  
  
    private OnDialKeyListener onDialKeyListener;  
  
    public Dialpad(Context context) {  
        super(context);  
        initLayout(context);  
    }  
  
    public Dialpad(Context context, AttributeSet attrs) {  
        super(context, attrs);  
        initLayout(context);  
    }  
  
    private void initLayout(Context context) {  
        LayoutInflater inflater = LayoutInflater.from(context);  
        inflater.inflate(R.layout.dialpad, this, true);  
    }  
  
//   Here we need a map to quickly find if the clicked button id is in the map  
//   keys,之所以这里不用SparseArrays,因为下面取值的方便  
    @SuppressLint("UseSparseArrays")  
    private static final Map<Integer, int[]> DIGITS_BTNS = new HashMap<Integer, int[]>();  
    static {  
        DIGITS_BTNS.put(R.id.button0, new int[] { ToneGenerator.TONE_DTMF_0,  
                KeyEvent.KEYCODE_0 });  
        DIGITS_BTNS.put(R.id.button1, new int[] { ToneGenerator.TONE_DTMF_1,  
                KeyEvent.KEYCODE_1 });  
        DIGITS_BTNS.put(R.id.button2, new int[] { ToneGenerator.TONE_DTMF_2,  
                KeyEvent.KEYCODE_2 });  
        DIGITS_BTNS.put(R.id.button3, new int[] { ToneGenerator.TONE_DTMF_3,  
                KeyEvent.KEYCODE_3 });  
        DIGITS_BTNS.put(R.id.button4, new int[] { ToneGenerator.TONE_DTMF_4,  
                KeyEvent.KEYCODE_4 });  
        DIGITS_BTNS.put(R.id.button5, new int[] { ToneGenerator.TONE_DTMF_5,  
                KeyEvent.KEYCODE_5 });  
        DIGITS_BTNS.put(R.id.button6, new int[] { ToneGenerator.TONE_DTMF_6,  
                KeyEvent.KEYCODE_6 });  
        DIGITS_BTNS.put(R.id.button7, new int[] { ToneGenerator.TONE_DTMF_7,  
                KeyEvent.KEYCODE_7 });  
        DIGITS_BTNS.put(R.id.button8, new int[] { ToneGenerator.TONE_DTMF_8,  
                KeyEvent.KEYCODE_8 });  
        DIGITS_BTNS.put(R.id.button9, new int[] { ToneGenerator.TONE_DTMF_9,  
                KeyEvent.KEYCODE_9 });  
        DIGITS_BTNS.put(R.id.buttonpound, new int[] {  
                ToneGenerator.TONE_DTMF_P, KeyEvent.KEYCODE_POUND });  
        DIGITS_BTNS.put(R.id.buttonstar, new int[] { ToneGenerator.TONE_DTMF_S,  
                KeyEvent.KEYCODE_STAR });  
    };  
  
    /** 
     * SparseArray这个是android提供的,可以替换HashMap,来提高效率 
     */  
    private static final SparseArray<String> DIGITS_NAMES = new SparseArray<String>();  
  
    static {  
        DIGITS_NAMES.put(R.id.button0, "0");  
        DIGITS_NAMES.put(R.id.button1, "1");  
        DIGITS_NAMES.put(R.id.button2, "2");  
        DIGITS_NAMES.put(R.id.button3, "3");  
        DIGITS_NAMES.put(R.id.button4, "4");  
        DIGITS_NAMES.put(R.id.button5, "5");  
        DIGITS_NAMES.put(R.id.button6, "6");  
        DIGITS_NAMES.put(R.id.button7, "7");  
        DIGITS_NAMES.put(R.id.button8, "8");  
        DIGITS_NAMES.put(R.id.button9, "9");  
        DIGITS_NAMES.put(R.id.buttonpound, "pound");  
        DIGITS_NAMES.put(R.id.buttonstar, "star");  
    };  
  
    public interface OnDialKeyListener {  
  
        /** 
         * Called when the user make an action 
         *  
         * @param keyCode 
         *            keyCode pressed 
         * @param dialTone 
         *            corresponding dialtone 
         */  
        void onTrigger(int keyCode, int dialTone);  
    }  
  
    @Override  
    protected void onFinishInflate() {  
        super.onFinishInflate();  
  
        for (int buttonId : DIGITS_BTNS.keySet()) {  
            ImageButton button = (ImageButton) findViewById(buttonId);  
            if (button != null) {  
                button.setOnClickListener(this);  
            }  
        }  
    }  
  
    /** 
     * Registers a callback to be invoked when the user triggers an event. 
     *  
     * @param listener 
     *            the OnTriggerListener to attach to this view 
     */  
    public void setOnDialKeyListener(OnDialKeyListener listener) {  
        onDialKeyListener = listener;  
    }  
  
    private void dispatchDialKeyEvent(int buttonId) {  
        if (onDialKeyListener != null && DIGITS_BTNS.containsKey(buttonId)) {  
            int[] datas = DIGITS_BTNS.get(buttonId);  
            onDialKeyListener.onTrigger(datas[1], datas[0]);  
        }  
    }  
  
    @Override  
    public void onClick(View v) {  
        dispatchDialKeyEvent(v.getId());  
    }  
}  
 
 
我们看看上面的代码:
1、initLayout来解析布局之后
2、onFinishInflate来设置按钮的点击事件
3、onClick处理点击事件,通过dispatchDialKeyEvent来实现分发事件
4、dispatchDialKeyEvent来根据不同的id,来设置回调onDialKeyListener.onTrigger,所以在实现Dialpad后,要实现OnDialKeyListener接口