因为android原生键盘很大,当键盘显示的时候,会遮住大部分的界面,有时候还会使界面移动(当Edittext在界面偏底部的时候),所以项目需要使用自定义键盘,看了系统源码,发现android原生键盘使用的是dialog构建键盘,所以决定用dialog,思路是这样:
1.建一个键盘的layout(keyboard.xml),自定义一个单例模式的dialog(keyboard.java),使用R.layout.keyboard作为layout,设置dialog不获取焦点:
getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
keyboard.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:localdefine = "http://schemas.android.com/apk/res-auto" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@drawable/compoment_sharp_grey_grey1" android:padding="10px" > <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="密码输入" android:textColor="@color/clr_black" android:id="@+id/id_title" android:visibility="gone" android:gravity="center"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="范围(无)" android:textSize="20sp" android:textColor="@color/clr_black" android:id="@+id/id_range" android:gravity="center"/> <LinearLayout android:layout_marginTop="10px" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal"> <Button style="@style/keypad_fun" android:text="@string/common_clear" android:id = "@+id/id_clear" android:background="@drawable/button_style_light"/> <Button style="@style/keypad_fun" android:text="@string/common_close" android:id = "@+id/id_close" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10px" android:orientation="horizontal"> <Button style="@style/keypad_num" android:text="7" android:id = "@+id/id_seven" /> <Button style="@style/keypad_num" android:text="8" android:id = "@+id/id_eight" android:layout_marginLeft="10px" /> <Button style="@style/keypad_num" android:text="9" android:id = "@+id/id_nigh" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> <com.tomra.trsort.ui.view.LocalButton style="@style/keypad_num" android:layout_marginLeft="10px" android:id = "@+id/id_delete" localdefine:drawableUp="@drawable/back_delete" android:background="@drawable/button_style_light"/> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="10px" android:orientation="horizontal"> <Button style="@style/keypad_num" android:text="4" android:id = "@+id/id_four" android:background="@drawable/button_style_light"/> <Button style="@style/keypad_num" android:text="5" android:id = "@+id/id_five" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> <Button style="@style/keypad_num" android:text="6" android:id = "@+id/id_six" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> <Button style="@style/keypad_num" android:text="." android:id = "@+id/id_dot" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> </LinearLayout> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10px" android:orientation="horizontal"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button style="@style/keypad_num" android:text="1" android:id = "@+id/id_one" android:background="@drawable/button_style_light"/> <Button style="@style/keypad_num" android:text="2" android:id = "@+id/id_two" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> <Button style="@style/keypad_num" android:text="3" android:id = "@+id/id_three" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> </LinearLayout> <Button style="@style/keypad_num1" android:text="0" android:id = "@+id/id_zero" android:layout_marginTop ="10px" android:background="@drawable/button_style_light"/> </LinearLayout> <Button style="@style/keypad_fun1" android:text="@string/dialog_open_btn_open" android:id = "@+id/id_ok" android:layout_marginLeft="10px" android:background="@drawable/button_style_light"/> </LinearLayout> </LinearLayout>
自定义dialog代码:
public class Keyboard extends Dialog implements View.OnClickListener{ private static KeyboardEditText mClientView; private Context mContext; private View mView; private float mX,mY; private static Keyboard mKeyboard; private TextView mTvTitle; private String mTitle = "Input"; private Button mBtnClose; private boolean mIsClose = true; private TextView mTvRange; public static Keyboard getInstance(Context context,KeyboardEditText view) { if(mKeyboard == null) { mKeyboard = new Keyboard(context,view); } if(mClientView != null) mClientView.setSelected(false); mClientView = view; mClientView.setSelected(true); return mKeyboard; } public void setView(KeyboardEditText view) { if(mClientView != null) mClientView.setSelected(false); mClientView = view; mClientView.setSelected(true); KeyboardEditText next = mClientView.getNextEditText(true); if(mBtnClose != null) { if (next != null) { mBtnClose.setText(getContext().getString(R.string.common_next)); mIsClose = false; } else { mBtnClose.setText(getContext().getString(R.string.common_close)); mIsClose = true; } int[] rang = new int[2]; if(mClientView.getRange(rang)) { StringBuilder sb = new StringBuilder(); sb.append(Integer.toString(rang[0])); sb.append("~"); sb.append(rang[1]); LogManager.LogEWithTag("KEYKEY", "show rang 0 = "+ rang[0]+" rang 1 = "+rang[1]+ "sb ="+sb.toString()); mTvRange.setText(String.format(getContext().getString(R.string.common_range),sb.toString())); } else mTvRange.setText(String.format(getContext().getString(R.string.common_range),getContext().getString(R.string.common_none))); } } public Keyboard(Context context,EditText view) { this(context); } public Keyboard(Context context) { super(context,R.style.Dialog); } public Keyboard(Context context, int theme) { super(context, theme); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); mView = LayoutInflater.from(getContext()).inflate(R.layout.keyboard,null); setContentView(mView); setCanceledOnTouchOutside(false); mBtnClose = ((Button)findViewById(R.id.id_close)); mBtnClose.setOnClickListener(this); getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); ((Button)findViewById(R.id.id_clear)).setOnClickListener(this); ((Button)findViewById(R.id.id_zero)).setOnClickListener(this); ((Button)findViewById(R.id.id_one)).setOnClickListener(this); ((Button)findViewById(R.id.id_two)).setOnClickListener(this); ((Button)findViewById(R.id.id_three)).setOnClickListener(this); ((Button)findViewById(R.id.id_four)).setOnClickListener(this); ((Button)findViewById(R.id.id_five)).setOnClickListener(this); ((Button)findViewById(R.id.id_six)).setOnClickListener(this); ((Button)findViewById(R.id.id_seven)).setOnClickListener(this); ((Button)findViewById(R.id.id_eight)).setOnClickListener(this); ((Button)findViewById(R.id.id_nigh)).setOnClickListener(this); ((Button)findViewById(R.id.id_dot)).setOnClickListener(this); ((Button)findViewById(R.id.id_ok)).setOnClickListener(this); ((Button)findViewById(R.id.id_delete)).setOnClickListener(this); mTvTitle = (TextView)findViewById(R.id.id_title); mTvTitle.setText(mTitle); mTvRange = (TextView)findViewById(R.id.id_range); mTvRange.setText(getContext().getString(R.string.common_range)); //LogManager.LogEWithTag("KEYKEY", "onCreate keypadWidth = "+ mView.getWidth()+" keypadHeight = "+mView.getHeight()); mView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { //LogManager.LogEWithTag("KEYKEY", "onGlobalLayout keypadWidth = "+ mView.getWidth()+" keypadHeight = "+mView.getHeight()); } }); KeyboardEditText next = mClientView.getNextEditText(false); if(mBtnClose != null) { if (next != null) { mBtnClose.setText(getContext().getString(R.string.common_next)); mIsClose = false; } else { mBtnClose.setText(getContext().getString(R.string.common_close)); mIsClose = true; } } int[] rang = new int[2]; if(mClientView != null) { if (mClientView.getRange(rang)) { StringBuilder sb = new StringBuilder(); sb.append(Integer.toString(rang[0])); sb.append("~"); sb.append(rang[1]); LogManager.LogEWithTag("KEYKEY", "show rang 0 = "+ rang[0]+" rang 1 = "+rang[1]+ "sb ="+sb.toString()); mTvRange.setText(String.format(getContext().getString(R.string.common_range), sb.toString())); } else mTvRange.setText(String.format(getContext().getString(R.string.common_range), getContext().getString(R.string.common_none))); } } private void reSize() { Window window = getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.gravity = Gravity.TOP | Gravity.LEFT; int[] location = new int[2]; mClientView.getLocationOnScreen(location); // lp.x = location[0]; // lp.y = location[1]; // window.setAttributes(lp); int[] screenSize = CommonUtil.getScreenSize(getContext()); int clientViewX = location[0]; int clientViewY = location[1]; int clientViewWidth = this.mClientView.getWidth(); int clientViewHeight = this.mClientView.getHeight(); int keypadWidth = 290; int keypadHeight = 389; if(clientViewY + clientViewHeight + keypadHeight <= screenSize[1]) { if(clientViewX + keypadWidth > screenSize[0]) lp.x = screenSize[0] - keypadWidth; else lp.x = clientViewX; lp.y = clientViewY + clientViewHeight; } else if(clientViewY >= keypadHeight) { if(clientViewX + keypadWidth > screenSize[0]) lp.x = screenSize[0] - keypadWidth; else lp.x = clientViewX; lp.y = clientViewY - keypadHeight; } else if(clientViewX + clientViewWidth + keypadWidth <= screenSize[0]) { lp.x = clientViewX + clientViewWidth; int delta = Math.abs((clientViewHeight - keypadHeight)/2); if(clientViewHeight > keypadHeight) { lp.y = clientViewY + delta; } else { lp.y = clientViewY - delta; } } else { lp.x = (screenSize[0] - keypadWidth)/2; lp.y = (screenSize[1] - keypadHeight)/2; } window.setAttributes(lp); } @Override public void show() { super.show(); reSize(); mClientView.setSelected(true); } public void setTitle(String str) { if(this.mTvTitle != null) { this.mTvTitle.setText(str); } this.mTitle = str; } @Override public void dismiss() { super.dismiss(); mClientView.setSelected(false); } @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); Window window = getWindow(); WindowManager.LayoutParams lp = window.getAttributes(); lp.x = (int)mClientView.getX(); lp.y = (int)mClientView.getY(); window.setAttributes(lp); } @Override public boolean onTouchEvent(MotionEvent event) { if(event.getAction() == MotionEvent.ACTION_DOWN) { mX = event.getRawX(); mY = event.getRawY(); if(mX < 0f || mY < 0) { WindowManager.LayoutParams ll = getWindow().getAttributes(); ll.x += (int)mX; ll.y += (int)mY; getWindow().setAttributes(ll); } } else if(event.getAction() == MotionEvent.ACTION_MOVE) { float deltaX = event.getRawX() - mX; float deltaY = event.getRawY() - mY; mX = event.getRawX(); mY = event.getRawY(); WindowManager.LayoutParams ll = getWindow().getAttributes(); ll.x += (int)deltaX; ll.y += (int)deltaY; getWindow().setAttributes(ll); } return super.onTouchEvent(event); } @Override public void onClick(View view) { switch(view.getId()) { case R.id.id_close: if(mIsClose) dismiss(); else setView(mClientView.getNextEditText(false)); break; case R.id.id_clear: this.mClientView.setText(""); break; case R.id.id_one: this.mClientView.selectAll(); this.mClientView.setText(this.mClientView.getText().toString()+"1"); break; case R.id.id_two: this.mClientView.setText(this.mClientView.getText().toString()+"2"); break; case R.id.id_three: this.mClientView.setText(this.mClientView.getText().toString()+"3"); break; case R.id.id_four: this.mClientView.setText(this.mClientView.getText().toString()+"4"); break; case R.id.id_five: this.mClientView.setText(this.mClientView.getText().toString()+"5"); break; case R.id.id_six: this.mClientView.setText(this.mClientView.getText().toString()+"6"); break; case R.id.id_seven: this.mClientView.setText(this.mClientView.getText().toString()+"7"); break; case R.id.id_eight: this.mClientView.setText(this.mClientView.getText().toString()+"8"); break; case R.id.id_nigh: this.mClientView.setText(this.mClientView.getText().toString()+"9"); break; case R.id.id_zero: this.mClientView.setText(this.mClientView.getText().toString()+"0"); break; case R.id.id_dot: if(mClientView.getInputType() == EditorInfo.TYPE_CLASS_NUMBER ) break; this.mClientView.setText(this.mClientView.getText().toString()+"."); break; case R.id.id_delete: String str = this.mClientView.getText().toString(); if(str == null || str.equals("")) break; int lengh = str.length(); String newStr = str.substring(0,lengh - 1); this.mClientView.setText(newStr); break; case R.id.id_ok: dismiss(); break; } } }
2.自定义Edittext,设置为InputType.
TYPE_NULL类型,不使用系统键盘。
3.重写Edittext的onTouchEvent方法,收到MotionEvent.ACTION_UP的时候,获取自定义键盘单例,显示,把对应的Edittext传给键盘,以便操作的时候更新:
@Override
public boolean onTouchEvent(MotionEvent event) {
if(!this.isEnabled())
return super.onTouchEvent(event);
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
LogManager.LogEWithTag("KEYKEY", "ACTION_DOWN = ");
requestFocus();
requestFocusFromTouch();
break;
case MotionEvent.ACTION_UP:
mKeyboard = Keyboard.getInstance(getContext(),this); mKeyboard.setView(this); if(!mKeyboard.isShowing()) { mKeyboard.show(); } break; } return super.onTouchEvent(event); }