这个我从 CsipSimple 项目中获得灵感并实现了我自己的
这是相同的代码 Create a Custom NumberPad here is mine 拨号盘的布局只是从 1 到 9 的按钮和 * 和 #
package com.xyz.custom;
import java.util.HashMap;
import java.util.Map;
import com.xyz.payphone.R;
import android.annotation.SuppressLint;
import android.content.Context;
import android.media.ToneGenerator;
import android.util.AttributeSet;
import android.util.SparseArray;
import android.widget.ImageButton;
import android.widget.TableLayout;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
public class DialpadNovanet extends TableLayout implements OnClickListener {
private OnDialKeyListener onDialKeyListener;
@SuppressLint("UseSparseArrays")
private static final Map<Integer, int[]> DIGITS_BTNS = new HashMap<Integer, int[]>();
private static final String tag = "Dialpad";
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 });
};
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 DialpadNovanet(Context context) {
super(context);
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.dialpad_novanet, this, true);
}
public DialpadNovanet(Context context, AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = LayoutInflater.from(context);
inflater.inflate(R.layout.dialpad_novanet, this, true);
}
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());
}
public void setOnDialKeyListener(OnDialKeyListener listener) {
onDialKeyListener = listener;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
for (int buttonId : DIGITS_BTNS.keySet()) {
ImageButton button = (ImageButton) findViewById(buttonId);
if (button != null) {
button.setOnClickListener(this);
}
}
}
public interface OnDialKeyListener {
/**
* Called when the user make an action
*
* @param keyCode
* keyCode pressed
* @param dialTone
* corresponding dialtone
*/
void onTrigger(int keyCode, int dialTone);
}
boolean mForceWidth = false;
public void setForceWidth(boolean forceWidth) {
mForceWidth = forceWidth;
}
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mForceWidth) {
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
getMeasuredHeight());
}
};
/*
* public void applyTheme(Theme t) {
*
* Log.d(tag, "Theming in progress"); for(int buttonId :
* DIGITS_BTNS.keySet()) {
*
* ImageButton b = (ImageButton) findViewById(buttonId); // We need to use
* state list as reused t.applyBackgroundStateListDrawable(b, "btn_dial");
*
* // Src of button Drawable src =
* t.getDrawableResource("dial_num_"+DIGITS_NAMES.get(buttonId)); if(src !=
* null) { b.setImageDrawable(src); }
*
* // Padding of button t.applyLayoutMargin(b, "dialpad_btn_margin"); }
*
* }
*/
}
现在创建自定义 EditText
public class DialerEditText extends EditText {
private static final String tag="DialerEditText";
private Boolean isDigit=null;
private Method showSoftInputOnFocus=null;
public DialerEditText(Context context, AttributeSet attrs) {
super(context, attrs);
setIsDigit(true, false);
}
public synchronized void setIsDigit(boolean isDigit, boolean autofocus) {
if(this.isDigit == null || this.isDigit != isDigit) {
this.isDigit = isDigit;
reflexSetShowSoftInputOnFocus(!isDigit);
if (isDigit) {
setRawInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
setTextSize(TypedValue.COMPLEX_UNIT_PX, getContext().getResources().getDimension(R.dimen.dialpad_digits_text_size));
} else {
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS
| InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
}
}
applyKeyboardShowHide(autofocus);
}
@Override
protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if(focused) {
applyKeyboardShowHide(false);
}else {
final InputMethodManager imm = ((InputMethodManager) getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE));
if(imm != null && imm.isActive(this)) {
imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
final boolean ret = super.onTouchEvent(event);
// Must be done after super.onTouchEvent()
applyKeyboardShowHide(false);
return ret;
}
/*
@Override
public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
boolean ret = false;
if(!isDigit) {
ret = super.requestFocus(direction, previouslyFocusedRect);
}
applyKeyboardShowHide(false);
return ret;
}
*/
private void applyKeyboardShowHide(boolean autofocus) {
final InputMethodManager imm = ((InputMethodManager) getContext()
.getSystemService(Context.INPUT_METHOD_SERVICE));
if (imm != null) {
if(isDigit) {
if(imm.isActive(this)) {
imm.hideSoftInputFromWindow(getApplicationWindowToken(), 0);
}
}else if(autofocus) {
imm.showSoftInput(this, 0);
}
}
}
@Override
public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED) {
// Since we're replacing the text every time we add or remove a
// character, only read the difference. (issue 5337550)
final int added = event.getAddedCount();
final int removed = event.getRemovedCount();
final int length = event.getBeforeText().length();
if (added > removed) {
event.setRemovedCount(0);
event.setAddedCount(1);
event.setFromIndex(length);
} else if (removed > added) {
event.setRemovedCount(1);
event.setAddedCount(0);
event.setFromIndex(length - 1);
} else {
return;
}
} else if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
// The parent EditText class lets tts read "edit box" when this View
// has a focus, which
// confuses users on app launch (issue 5275935).
return;
}
super.sendAccessibilityEventUnchecked(event);
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
// Here we ensure that we hide the keyboard
// Since this will be fired when virtual keyboard this will probably
// blink but for now no better way were found to hide keyboard for sure
applyKeyboardShowHide(false);
}
private void reflexSetShowSoftInputOnFocus(boolean show) {
if(showSoftInputOnFocus != null) {
UtilityWrapper.safelyInvokeMethod(showSoftInputOnFocus, this, show);
}
}
}
现在您可以将其用作 xml 避免填充和内容,因为那是我的应用程序特定的
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.novanet.custom.DialerEditText
android:id="@+id/edtDialer"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="70" />
<com.novanet.custom.DialpadNovanet
android:id="@+id/dial_pad"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical"
android:layout_weight="65"
android:paddingBottom="10dip"
android:paddingLeft="5dip"
android:paddingRight="5dip" />
</LinearLayout>
现在在你的活动中你可以做到这一点
edtText=(DialerEditText)findViewById(R.id.edtDialer);
dialPad=(DialpadNovanet)findViewById(R.id.dial_pad);
dialPad.setOnDialKeyListener(new OnDialKeyListener() {
@Override
public void onTrigger(int keyCode, int dialTone) {
Log.v(tag,"Key "+keyCode);
KeyEvent event=new KeyEvent(KeyEvent.ACTION_DOWN, keyCode);
edtText.onKeyDown(keyCode, event);
}
});