在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>
显示效果如下:
布局设置好之后,我们就要调用布局,设置监听实现回调。
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接口