我正在尝试为我的应用使用自定义ViewGroup。因为我使用以下xml在我的ViewGroup类中充气。
<?xml version="1.0" encoding="utf-8"?>
<!-- This layout is used wherever the pin entering screens used -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<TextView
android:id="@+id/textView1"
style="?attr/txtNormalStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background_normal"
android:ems="1"
android:inputType="numberPassword" />
<TextView
android:id="@+id/textView2"
style="?attr/txtNormalStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background_normal"
android:ems="1"
android:inputType="numberPassword" />
<TextView
android:id="@+id/textView3"
style="?attr/txtNormalStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background_normal"
android:ems="1"
android:inputType="numberPassword" />
<TextView
android:id="@+id/textView4"
style="?attr/txtNormalStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@android:drawable/editbox_background_normal"
android:ems="1"
android:inputType="numberPassword" />
<EditText
android:id="@+id/edtInvisible"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:inputType="text"
android:maxLength="4"
android:visibility="visible" />
</LinearLayout>
以下是我的扩展视图组类
public class View_Pin_Text extends LinearLayout implements
View.OnClickListener, TextWatcher, View.OnKeyListener {
private String strPin;
private TextView txtView1, txtView2, txtView3, txtView4;
private EditText edtText;
private boolean isInTextWatcher = false;
public View_Pin_Text(Context context, AttributeSet attrs) {
super(context, attrs);
// inflating the custom layout for the view group
LayoutInflater mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mInflater.inflate(R.layout.view_pin_enter, this, true);
// 4 text views for showing pin to user
txtView1 = (TextView) findViewById(R.id.textView1);
txtView2 = (TextView) findViewById(R.id.textView2);
txtView3 = (TextView) findViewById(R.id.textView3);
txtView4 = (TextView) findViewById(R.id.textView4);
// setting on click listener
txtView1.setOnClickListener(this);
txtView2.setOnClickListener(this);
txtView3.setOnClickListener(this);
txtView4.setOnClickListener(this);
// invisible edit text for invoking keyboard
edtText = (EditText) findViewById(R.id.edtInvisible);
// text change listener to update the input in text views
edtText.addTextChangedListener(this);
// key listener to handle backspace/del keys press
edtText.setOnKeyListener(this);
}
/**
* @return strPin
* <p>
* Gives the currently given pin by the user
* </p>
*/
public String getStrPin() {
return strPin;
}
/**
* @param strPin
* <p>
* Sets the pin to instance object and updates the proper
* characters in all text views
* </p>
*/
public void setStrPin(String strPin) {
if (strPin != null) {
int lenght = strPin.length();
if (lenght <= 4)
this.strPin = strPin;
Log.d("text", strPin);
switch (lenght) {
case 0:
txtView1.setText("");
txtView2.setText("");
txtView3.setText("");
txtView4.setText("");
break;
case 1:
txtView1.setText(String.valueOf(strPin.charAt(0)));
txtView2.setText("");
txtView3.setText("");
txtView4.setText("");
break;
case 2:
txtView1.setText(String.valueOf(strPin.charAt(0)));
txtView2.setText(String.valueOf(strPin.charAt(1)));
txtView3.setText("");
txtView4.setText("");
break;
case 3:
txtView1.setText(String.valueOf(strPin.charAt(0)));
txtView2.setText(String.valueOf(strPin.charAt(1)));
txtView3.setText(String.valueOf(strPin.charAt(2)));
txtView4.setText("");
break;
case 4:
txtView1.setText(String.valueOf(strPin.charAt(0)));
txtView2.setText(String.valueOf(strPin.charAt(1)));
txtView3.setText(String.valueOf(strPin.charAt(2)));
txtView4.setText(String.valueOf(strPin.charAt(3)));
((InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
edtText.getWindowToken(), 0);
break;
}
} else {
this.strPin = strPin;
}
}
@Override
public void onClick(View v) {
Toast.makeText(getContext(), "OnClick", Toast.LENGTH_SHORT).show();
((InputMethodManager) getContext().getSystemService(
Context.INPUT_METHOD_SERVICE)).showSoftInput(edtText,
InputMethodManager.SHOW_FORCED);
}
@Override
public void afterTextChanged(Editable s) {
if (isInTextWatcher)
return;
isInTextWatcher = true;
Log.d("text", "changed-" + s.toString());
if (getStrPin() == null) {
setStrPin(s.toString());
} else {
setStrPin(getStrPin() + "" + s.toString());
}
edtText.setText("");
isInTextWatcher = false;
}
@Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2,
int arg3) {
}
@Override
public void onTextChanged(CharSequence cs, int arg1, int arg2, int arg3) {
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL
&& event.getAction() != KeyEvent.ACTION_DOWN) {
if (getStrPin() != null) {
int length = getStrPin().length();
if (length > 0) {
setStrPin(getStrPin()
.substring(0, getStrPin().length() - 1));
}
}
}
return true;
}
}
在此课程中,当我的编辑文本设置为 android:inputType =&#34; number&#34; 时,我的文本观察器 afterTextChanged 不会被触发,并且可以完美地用于文本输入我的nexus 5(Kitkat 4.4.4)。但是,当我尝试使用三星Core(Jellybean 4.1.2)工作正常..那么问题是什么,应该如何解决?
答案 0 :(得分:2)
Android自带的软键盘(LatinIME)处理的数字输入与其他字符略有不同。这里发生了什么:
private void sendKeyCodePoint(final int code) {
....
....
// TODO: Remove this special handling of digit letters.
// For backward compatibility. See {@link InputMethodService#sendKeyChar(char)}.
if (code >= '0' && code <= '9') {
sendDownUpKeyEvent(code - '0' + KeyEvent.KEYCODE_0);
return;
}
if (Constants.CODE_ENTER == code && mAppWorkAroundsUtils.isBeforeJellyBean()) {
// Backward compatibility mode. Before Jelly bean, the keyboard would simulate
// a hardware keyboard event on pressing enter or delete. This is bad for many
// reasons (there are race conditions with commits) but some applications are
// relying on this behavior so we continue to support it for older apps.
sendDownUpKeyEvent(KeyEvent.KEYCODE_ENTER);
} else {
mConnection.commitText(StringUtils.newSingleCodePointString(code), 1);
}
}
所以,对于&#39; 0&#39; - &#39; 9&#39; (和在JellyBean之前的ENTER),发送KeyEvent
。问题是 - 您的OnKeyListener
消费每个 KeyEvent:
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL
&& event.getAction() != KeyEvent.ACTION_DOWN) {
if (getStrPin() != null) {
int length = getStrPin().length();
if (length > 0) {
setStrPin(getStrPin()
.substring(0, getStrPin().length() - 1));
}
}
}
// Returning `true` at this point means that you have handled whatever was sent
return true;
}
您似乎希望处理KeyEvent.KEYCODE_DEL
。在这种情况下,您的OnKeyListener
应如下所示:
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_DEL
&& event.getAction() != KeyEvent.ACTION_DOWN) {
if (getStrPin() != null) {
int length = getStrPin().length();
if (length > 0) {
setStrPin(getStrPin()
.substring(0, getStrPin().length() - 1));
// Handled
return true;
}
}
}
// Let everything other that KEYCODE_DEL be handled elsewhere
return false;
}
我不确定为什么你的代码适用于三星酷睿,但可能是因为三星对AOSP进行了很多改动。可能是他们没有为KeyEvent
发送0 - 9
。
另一个问题:您的OnKeyListener
仅适用于API&lt; 16.对于API&gt; = 16,KEYCODE_DEL
不会作为KeyEvent
发送。查看InputConnectionWrapper
(特别是deleteSurroundingText(...)
)以支持JellyBean上的类似功能。后面。