为了便于用户快捷的输入车牌号码便需要自定义个车牌键盘,而不是使用系统的键盘输入,上效果图:
一、首先我们要来分析一下需要做哪些东西
- 默认展示车牌的省份简称
- 特殊车牌(使、领、警、港、澳)
- 删除键
- 切换为数字和字母按键
车牌号中是没有I、O
字母的(容易与1、0)分混淆,故不需要这两个按键
I、O
这两个按键的位置正好使用学、挂
来填充
二、根据效果图可以看出键盘就是个网格列表,所以很容易就想到使用RecyclerView
来实现即简单又高效
- 创建个
LicensePlateView
类继承自LinearLayout
- 我们需要定义我们的按键资源
在string.xml
文件中定义我们的资源
<array name="province">
<item>京item>
<item>沪item>
<item>浙item>
<item>苏item>
<item>粤item>
<item>鲁item>
<item>晋item>
<item>冀item>
<item>豫item>
<item>川item>
<item>渝item>
<item>辽item>
<item>吉item>
<item>黑item>
<item>皖item>
<item>鄂item>
<item>湘item>
<item>赣item>
<item>闽item>
<item>陕item>
<item>甘item>
<item>宁item>
<item>蒙item>
<item>津item>
<item>贵item>
<item>云item>
<item>桂item>
<item>琼item>
<item>青item>
<item>Delitem>
<item>item>
<item>新item>
<item>藏item>
<item>使item>
<item>领item>
<item>警item>
<item>港item>
<item>澳item>
<item>ABC\n123item>
array>
<array name="nums">
<item>"0"item>
<item>"1"item>
<item>"2"item>
<item>"3"item>
<item>"4"item>
<item>"5"item>
<item>"6"item>
<item>"7"item>
<item>"8"item>
<item>"9"item>
<item>Qitem>
<item>Witem>
<item>Eitem>
<item>Ritem>
<item>Titem>
<item>Yitem>
<item>Uitem>
<item>学item>
<item>挂item>
<item>Pitem>
<item>Aitem>
<item>Sitem>
<item>Ditem>
<item>Fitem>
<item>Gitem>
<item>Hitem>
<item>Jitem>
<item>Kitem>
<item>Litem>
<item>Delitem>
<item>item>
<item>Zitem>
<item>Xitem>
<item>Citem>
<item>Vitem>
<item>Bitem>
<item>Nitem>
<item>Mitem>
<item>省item>
array>
这里需要特别注意,定义数字的时候需要给它加上" ",否则代码获取的为null
- 键盘的最后一行第一个是需要空开来的,所以直接使用个空字符串占位即可。
三、 编写每个按键的布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="35dp"
android:background="@drawable/sel_white_radius_2"
android:gravity="center">
<TextView
android:id="@+id/tv_key"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:gravity="center"
android:lineSpacingMultiplier="0.8"
android:text="京"
android:textColor="#333333"
android:textSize="16sp" />
LinearLayout>
四、通过代码动态创建一个RecyclerView
public class LicensePlateView extends LinearLayout implements View.OnClickListener {
private List<String> provinceList = new ArrayList<>();
private List<String> numList = new ArrayList<>();
private final int backgroundColor = Color.parseColor("#e9e9e9");
private final int keyTextColor = Color.parseColor("#333333");
private final int spanCount = 10;
private final int keyButtonMargin = 15;
private final int keyboardPadding = 10;
private OnKeyClickListener onKeyClickListener;
private KeyAdapter keyAdapter;
public LicensePlateView(Context context) {
super(context);
init(context);
}
public LicensePlateView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context);
}
private void init(Context context) {
setOrientation(LinearLayout.VERTICAL);
setBackgroundColor(backgroundColor);
initKeys();
RecyclerView recyclerView = new RecyclerView(context);
recyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
recyclerView.setLayoutManager(new GridLayoutManager(context, spanCount));
recyclerView.addItemDecoration(new RecycleGridDivider(keyButtonMargin));
int padding = dip2px(context, keyboardPadding);
recyclerView.setPadding(padding, padding, padding, padding);
addView(recyclerView);
keyAdapter = new KeyAdapter(this);
recyclerView.setAdapter(keyAdapter);
keyAdapter.setNewData(provinceList);
}
private void initKeys() {
String[] province = getResources().getStringArray(R.array.province);
String[] num = getResources().getStringArray(R.array.nums);
Collections.addAll(provinceList, province);
Collections.addAll(numList, num);
}
@Override
public void onClick(View v) {
TextView tvKey = v.findViewById(R.id.tv_key);
String key = tvKey.getText().toString();
if (key.equals("ABC\n123")) {
keyAdapter.setNewData(numList);
return;
} else if (key.equals("省")) {
keyAdapter.setNewData(provinceList);
return;
}
if (onKeyClickListener != null) {
onKeyClickListener.onKeyClick(key);
}
}
private class KeyAdapter extends RecyclerView.Adapter<KeyAdapter.KeyViewHolder> {
private List<String> list = new ArrayList<>();
private OnClickListener listener;
public KeyAdapter(OnClickListener listener) {
this.listener = listener;
}
@NonNull
@Override
public KeyAdapter.KeyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_key, parent, false);
return new KeyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull KeyAdapter.KeyViewHolder holder, int position) {
String key = list.get(position);
holder.tvKey.setText(key);
holder.itemView.setOnClickListener(listener);
if (TextUtils.isEmpty(key)) {
holder.itemView.setBackgroundResource(0);
} else if (key.equals("ABC\n123") || key.equals("省")) {
holder.tvKey.setTextSize(10);
holder.itemView.setBackgroundResource(R.drawable.sel_blue_radius_2);
holder.tvKey.setTextColor(Color.WHITE);
} else {
holder.tvKey.setTextSize(12);
holder.itemView.setBackgroundResource(R.drawable.sel_white_radius_2);
holder.tvKey.setTextColor(keyTextColor);
}
}
@Override
public int getItemCount() {
return list.size();
}
public void setNewData(List<String> list) {
this.list.clear();
this.list.addAll(list);
notifyDataSetChanged();
}
private class KeyViewHolder extends RecyclerView.ViewHolder {
private TextView tvKey;
public KeyViewHolder(@NonNull View itemView) {
super(itemView);
tvKey = itemView.findViewById(R.id.tv_key);
}
}
}
public class RecycleGridDivider extends RecyclerView.ItemDecoration {
private int space;
public RecycleGridDivider(int space) {
this.space = space;
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager();
int span = manager.getSpanCount();
int offset = space / 2;
int childPosition = parent.getChildAdapterPosition(view);
if (childPosition < span) {
if (childPosition % span == 0) {
outRect.set(0, 0, offset, 0);
} else if (childPosition % span == span - 1) {
outRect.set(offset, 0, 0, 0);
} else {
outRect.set(offset, 0, offset, 0);
}
} else {
if (childPosition % span == 0) {
outRect.set(0, space, offset, 0);
} else if (childPosition % span == span - 1) {
outRect.set(offset, space, 0, 0);
} else {
outRect.set(offset, space, offset, 0);
}
}
}
}
public void setOnKeyClickListener(OnKeyClickListener listener) {
this.onKeyClickListener = listener;
}
public interface OnKeyClickListener {
void onKeyClick(String key);
}
public static int dip2px(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
}
四、对于我们需要输入车牌的EditText
,需要它禁止弹出系统键盘;设置如下:
etPlate.setInputType(InputType.TYPE_NULL);
etPlate.setKeyListener(null);
五、封装好后使用就很简单了
LicensePlateView plateView = findViewById(R.id.plate_view);
plateView.setOnKeyClickListener(new LicensePlateView.OnKeyClickListener() {
@Override
public void onKeyClick(String key) {
Editable editable = etPlate.getText();
int start = etPlate.getSelectionStart();
if (key.equalsIgnoreCase("Del")) {
if (editable.length() > 0 && start > 0) {
editable.delete(start - 1, start);
}
return;
}
editable.insert(start, key);
}
});
总体来说这个View还是很简单的Demo下载地址