在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接口