我正在开发一个使用键盘进行输入的游戏,但是当用户触摸输入字段时,我只想显示字母字符,没有数字或特殊符号。现在,当键盘打开时,应用程序如下所示:
当“键入一些字母”EditText 具有焦点时,如何用自定义键盘替换软键盘?
我正在开发一个使用键盘进行输入的游戏,但是当用户触摸输入字段时,我只想显示字母字符,没有数字或特殊符号。现在,当键盘打开时,应用程序如下所示:
当“键入一些字母”EditText 具有焦点时,如何用自定义键盘替换软键盘?
I ended up creating a layout of the keyboard I wanted and then I disabled the focus for the EditText:
<EditText
android:id="@+id/typed_word"
android:focusable="false"
android:maxLength="10"
android:inputType="text"
android:textCursorDrawable="@drawable/custom_cursor"
android:enabled="false"
android:layout_below="@+id/word_list"
android:digits="abcdefghijklmnopqrstuvwxyz"
android:textSize="25sp"
android:textColor="@color/colorPrimaryDark"
android:layout_margin="10dp"
android:hint="@string/type_hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
By disabling the focus, I was able to prevent the standard keyboard from being displayed.
在你的xml中使用android:inputType
和。android:digits
EditText
<EditText
android:id="@+id/plain_text_input"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:inputType="text"
android:digits="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ "/>
这将只允许插入字母字符和空格
您还可以检查用户是否尝试输入数字或其他非字母字符,然后向他显示警告。然后,你用任何东西替换它regex
[^\p{L}\p{Nd}]+
- 这匹配所有既不是字母也不是数字的字符。
EditText text = (EditText) findViewById(R.id.plain_text_input);
text.addTextChangedListener(new TextWatcher() {
public void afterTextChanged(Editable s) {
if(s.matches(".*\\d.*")){ // contains a number
text.setError("Sorry, numbers are not allowed");
text.replaceAll("[^\\p{L}\\p{Nd}]+", "");
}
}
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
public void onTextChanged(CharSequence s, int start, int before, int count) {}
});
或者,您可以创建自己的 InputFilter 来过滤掉任何非字母字符。
InputFilter input = new InputFilter() {
public CharSequence filter
(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
String filtered = "";
for (int i = start; i < end; i++) {
char character = source.charAt(i);
if (!Character.isWhitespace(character) && Character.isLetter(character)) {
filtered += character;
}
}
return filtered;
}
};
text.setFilters(new InputFilter[]{input});
我希望这对您有所帮助。^ - ^
由于他们弃用KeyboardView
了 api 29 中的其他相关类,因此请忽略我对该类的最后评论,因为他们将来会删除它。
创建自定义键盘的最佳方法是使用InputMethodService
该类,创建您自己的自定义xml
布局。
但是,当您正在开发使用更简单输入法的游戏时,这对游戏之外的任何地方的用户都没有用(例如消息应用程序),请考虑这一点。
请记住,此解决方案不会重现用户通常使用键盘执行的所有操作。您可以轻松修改它以满足您的需求。
1、创建keyboard.xml
布局。如果需要,您可以修改此示例。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/keyboard_parent"
android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content"
android:focusable="true" android:clickable="true"
android:background="@android:color/white"
android:visibility="gone">
<LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="50dp">
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_q"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_w"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_e"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_r"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_t"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_y"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_u"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_i"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_o"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_p"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="50dp"
android:paddingStart="8dp" android:paddingEnd="8dp">
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_a"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_s"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_d"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_f"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_g"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_h"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_j"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_k"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_l"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_ç"/>
</LinearLayout>
<LinearLayout android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="50dp">
<ImageView
style="@style/action"
android:layout_weight="1"
android:id="@+id/keyboard_action_all_caps"
android:tint="@android:color/darker_gray"
app:srcCompat="@android:drawable/ic_menu_upload"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_z"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_x"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_c"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_v"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_b"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_n"/>
<TextView style="@style/alpha" android:id="@+id/keyboard_abc_m"/>
<ImageView
style="@style/action"
android:layout_weight="1"
android:id="@+id/keyboard_action_delete"
android:tint="@android:color/darker_gray"
app:srcCompat="@android:drawable/ic_input_delete"/>
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="60dp">
<ImageView
style="@style/action"
android:id="@+id/keyboard_action_something"
android:layout_width="56dp"
android:layout_height="match_parent"
app:srcCompat="@android:drawable/ic_menu_sort_alphabetically"/>
<Button
android:id="@+id/keyboard_action_space"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="40dp"
android:layout_gravity="center_vertical"
app:backgroundTint="@android:color/black"/>
<ImageView
style="@style/action"
android:layout_width="56dp"
android:layout_height="match_parent"
android:id="@+id/keyboard_action_send"
app:srcCompat="@android:drawable/ic_menu_send"/>
</LinearLayout>
</LinearLayout>
地点@style/alpha
和地点@style/action
<style name="alpha">
<item name="android:layout_weight">1</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">match_parent</item>
<item name="android:text">"A"</item>
<item name="android:textSize">8pt</item>
<item name="android:textColor">@android:color/black</item>
<item name="android:gravity">center</item>
<item name="android:layout_gravity">center_vertical</item>
</style>
<style name="action">
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:layout_gravity">center_vertical</item>
<item name="android:scaleType">center</item>
<item name="android:padding">4dp</item>
<item name="android:tint">@android:color/black</item>
</style>
第二为您的键盘创建一个构造函数。
public class MyKeyboard {
private Context context;
private boolean is_all_caps_single = false;
private boolean is_all_caps_double = false;
public MyKeyboard(Context c, View container, boolean is_reference) {
this.context = c;
if (is_reference) {
keyboard = container.findViewById(R.id.keyboard_parent);
initializeComponents();
} else {
keyboard = View.inflate(context, R.layout.keyboard, null);
initializeComponents();
((ViewGroup) container).removeAllViews();
((ViewGroup) container).addView(keyboard);
}
}
private View keyboard;
private TextView[] characters;
private ImageView all_caps;
@SuppressLint("ClickableViewAccessibility")
private void initializeComponents() {
int[] ids = {
R.id.keyboard_abc_q, R.id.keyboard_abc_w, R.id.keyboard_abc_e, R.id.keyboard_abc_r, R.id.keyboard_abc_t, R.id.keyboard_abc_y, R.id.keyboard_abc_u, R.id.keyboard_abc_i, R.id.keyboard_abc_o, R.id.keyboard_abc_p,
R.id.keyboard_abc_a, R.id.keyboard_abc_s, R.id.keyboard_abc_d, R.id.keyboard_abc_f, R.id.keyboard_abc_g, R.id.keyboard_abc_h, R.id.keyboard_abc_j, R.id.keyboard_abc_k, R.id.keyboard_abc_l, R.id.keyboard_abc_ç,
R.id.keyboard_abc_z, R.id.keyboard_abc_x, R.id.keyboard_abc_c, R.id.keyboard_abc_v, R.id.keyboard_abc_b, R.id.keyboard_abc_n, R.id.keyboard_abc_m
};
String[] chrs =
{
"q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
"a", "s", "d", "f", "g", "h", "j", "k", "l", "ç",
"z", "x", "c", "v", "b", "n", "m"
};
characters = new TextView[ids.length];
for (int i = 0; i < ids.length; i++) {
characters[i] = keyboard.findViewById(ids[i]);
characters[i].setText(chrs[i]);
}
all_caps = keyboard.findViewById(R.id.keyboard_action_all_caps);
final GestureDetector all_caps_gesture = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
is_all_caps_double = false;
is_all_caps_single = !is_all_caps_single;
for (TextView tw: characters) {
tw.setAllCaps(is_all_caps_single);
}
setForegroundColor(all_caps, is_all_caps_single ? Color.BLACK : Color.GRAY);
return super.onSingleTapConfirmed(e);
}
@Override
public boolean onDoubleTap(MotionEvent e) {
is_all_caps_single = true;
is_all_caps_double = !is_all_caps_double;
for (TextView tw: characters) {
tw.setAllCaps(is_all_caps_double);
}
setForegroundColor(all_caps, Color.BLUE);
return super.onDoubleTap(e);
}
});
all_caps.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
all_caps_gesture.onTouchEvent(event);
return true;
}
});
for (int i = 0; i < ids.length; i++) {
final int finalI = i;
characters[i].setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String ss = characters[finalI].getText().toString();
if (is_all_caps_double) {
ss = ss.toUpperCase();
} else if (is_all_caps_single) {
is_all_caps_single = false;
ss = ss.toUpperCase();
for (TextView tw: characters) {
tw.setAllCaps(false);
}
setForegroundColor(all_caps, Color.BLACK);
} else {
ss = ss.toLowerCase();
}
popup(characters[finalI], ss);
edittext.getText().insert(edittext.getSelectionStart(), ss);
}
});
}
keyboard.findViewById(R.id.keyboard_action_space).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
edittext.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_SPACE));
}
});
final GestureDetector del_gesture = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
@Override
public void onLongPress(MotionEvent e) {
is_fast_delete = true;
fastDelete(edittext);
super.onLongPress(e);
}
});
keyboard.findViewById(R.id.keyboard_action_delete).setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
is_fast_delete = false;
delete();
}
del_gesture.onTouchEvent(event);
return true;
}
});
keyboard.findViewById(R.id.keyboard_action_send).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
edittext.getText().insert(edittext.getSelectionStart(), "\n");
}
});
keyboard.findViewById(R.id.keyboard_action_something).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e("log", "Make something here");
}
});
}
private EditText edittext;
public void show(EditText focus) {
this.edittext = focus;
keyboard.animate().y(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
keyboard.setVisibility(View.VISIBLE);
}
});
}
public void hide() {
if (isVisible()) {
edittext.clearFocus();
keyboard.animate().y(keyboard.getHeight()).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
keyboard.setVisibility(View.GONE);
}
});
}
}
public boolean isVisible() {
return keyboard.getVisibility() == View.VISIBLE;
}
// show popup when typing
private void popup(View vw, String s) {
final PopupWindow popup = new PopupWindow(context);
RelativeLayout layout = new RelativeLayout(context);
layout.setBackgroundColor(Color.BLACK);
TextView tw = new TextView(context);
tw.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT));
tw.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
tw.setTextSize(24);
tw.setTextColor(Color.WHITE);
tw.setText(s);
layout.removeAllViews();
layout.addView(tw);
popup.setContentView(layout);
popup.setHeight(120);
popup.setWidth(72);
popup.setOutsideTouchable(false);
popup.setFocusable(false);
layout.animate().alpha(1 f).setDuration(0).setStartDelay(100).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
popup.dismiss();
}
});
popup.showAsDropDown(vw, 0, -180);
}
// change color of an icon
private void setForegroundColor(ImageView v, int color) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
v.getDrawable().setColorFilter(new BlendModeColorFilter(color, BlendMode.SRC_ATOP));
} else {
v.getDrawable().setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
}
}
private void delete() {
edittext.dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL));
}
private void fastDelete(final View vw) {
final AlphaAnimation n = new AlphaAnimation(1 f, 1 f);
n.setRepeatCount(1000);
n.setDuration(200);
n.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
}
@Override
public void onAnimationRepeat(Animation animation) {
repeat_count = repeat_count + 1;
if (is_fast_delete) {
if (repeat_count == 5) {
n.setDuration(100);
} else if (repeat_count >= 10) {
n.setDuration(5);
}
delete();
} else {
n.cancel();
vw.getAnimation().cancel();
vw.clearAnimation();
n.setAnimationListener(null);
repeat_count = 0;
}
}
});
vw.startAnimation(n);
}
private boolean is_fast_delete = false;
private int repeat_count = 0;
}
3rd初始化您的键盘并手动处理您的活动的生命周期。
public class YourActivity extends AppCompatActivity {
private MyKeyboard keyboard;
private EditText edittext;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.one);
keyboard = new MyKeyboard(this, findViewById(R.id.keyboard_container), true);
//if true, the layout must include the keyboard.xml manually
//else, the constructor will include keyboard.xml programatically
edittext = findViewById(R.id.edittext);
edittext.setShowSoftInputOnFocus(false); // not show system keyboard
edittext.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) { keyboard.show(edittext); }
else { keyboard.hide(); }
}
});
}
@Override
public void onBackPressed() {
if (keyboard.isVisible()) {
keyboard.hide();
} else {
super.onBackPressed();
}
}
}
最后,您的主要活动布局应如下所示
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:animateLayoutChanges="true"
android:focusableInTouchMode="true"
android:focusable="true"
android:clickable="true">
<EditText
android:id="@+id/edittext"
android:padding="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="2dp"
android:layout_above="@+id/keyboard_container"
android:inputType="text|textNoSuggestions"
android:background="@android:color/white"
android:hint="@string/app_name"/>
<RelativeLayout
android:id="@+id/keyboard_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="@android:color/white">
<include
layout="@layout/keyboard"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
</RelativeLayout>
每当您希望关闭键盘时,添加focusableInTouchMode="true"
focusable="true"
和到用户交互的所有视图。clickable="true"
每当 Edittext 失去焦点时就会发生这种情况
最终结果是没有数字和特殊字符的键盘。
我使用标准的 android 图标作为示例,您可以将它们替换为其他图标。
正如我在本版开头所说,此解决方案不会重现用户通常使用键盘执行的所有操作,您可以以最佳方式对其进行改进。
我希望这对您有所帮助。^-^