本文来自阿钟的投稿,全文阅读大约十分钟
为了便于用户快捷的输入车牌号码便需要自定义个车牌键盘,而不是使用系统的键盘输入,上效果图:
横屏效果

竖屏效果

一、首先我们要来分析一下需要做哪些东西
默认展示车牌的省份简称
特殊车牌(使、领、警、港、澳)
删除键
切换为数字和字母按键
车牌号中是没有I、O字母的(容易与1、0)分混淆,故不需要这两个按键I、O这两个按键的位置正好使用学、挂来填充
二、根据效果图可以看出键盘就是个网格列表,所以很容易就想到使用`RecyclerView`来实现即简单又高效
创建个
LicensePlateView类继承自LinearLayout我们需要定义我们的按键资源
在`string.xml`文件中定义我们的资源
简称
1<array name="province">
2 <item>京</item>
3 <item>沪</item>
4 <item>浙</item>
5 <item>苏</item>
6 <item>粤</item>
7 <item>鲁</item>
8 <item>晋</item>
9 <item>冀</item>
10 <item>豫</item>
11 <item>川</item>
12 <item>渝</item>
13 <item>辽</item>
14 <item>吉</item>
15 <item>黑</item>
16 <item>皖</item>
17 <item>鄂</item>
18 <item>湘</item>
19 <item>赣</item>
20 <item>闽</item>
21 <item>陕</item>
22 <item>甘</item>
23 <item>宁</item>
24 <item>蒙</item>
25 <item>津</item>
26 <item>贵</item>
27 <item>云</item>
28 <item>桂</item>
29 <item>琼</item>
30 <item>青</item>
31 <item>Del</item>
32 <item></item>
33 <item>新</item>
34 <item>藏</item>
35 <item>使</item>
36 <item>领</item>
37 <item>警</item>
38 <item>港</item>
39 <item>澳</item>
40 <item>ABC\n123</item>
41</array>
数字、字母
1<array name="nums">
2 <item>"0"</item>
3 <item>"1"</item>
4 <item>"2"</item>
5 <item>"3"</item>
6 <item>"4"</item>
7 <item>"5"</item>
8 <item>"6"</item>
9 <item>"7"</item>
10 <item>"8"</item>
11 <item>"9"</item>
12 <item>Q</item>
13 <item>W</item>
14 <item>E</item>
15 <item>R</item>
16 <item>T</item>
17 <item>Y</item>
18 <item>U</item>
19 <item>学</item>
20 <item>挂</item>
21 <item>P</item>
22 <item>A</item>
23 <item>S</item>
24 <item>D</item>
25 <item>F</item>
26 <item>G</item>
27 <item>H</item>
28 <item>J</item>
29 <item>K</item>
30 <item>L</item>
31 <item>Del</item>
32 <item></item>
33 <item>Z</item>
34 <item>X</item>
35 <item>C</item>
36 <item>V</item>
37 <item>B</item>
38 <item>N</item>
39 <item>M</item>
40 <item>省</item>
41</array>
`这里需要特别注意,定义数字的时候需要给它加上" ",否则代码获取的为null`
键盘的最后一行第一个是需要空开来的,所以直接使用个空字符串占位即可。
三、 编写每个按键的布局
1<?xml version="1.0" encoding="utf-8"?>
2<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="35dp"
5 android:background="@drawable/sel_white_radius_2"
6 android:gravity="center">
7 <TextView
8 android:id="@+id/tv_key"
9 android:layout_width="wrap_content"
10 android:layout_height="match_parent"
11 android:gravity="center"
12 android:lineSpacingMultiplier="0.8"
13 android:text="京"
14 android:textColor="#333333"
15 android:textSize="16sp" />
16</LinearLayout>
四、通过代码动态创建一个`RecyclerView`
LicensePlateView
1public class LicensePlateView extends LinearLayout implements View.OnClickListener {
2 /**
3 * 车牌简称
4 */
5 private List<String> provinceList = new ArrayList<>();
6 /**
7 * 0~9,A~Z(车牌里没有I、O字母)
8 */
9 private List<String> numList = new ArrayList<>();
10 /**
11 * 键盘的背景颜色
12 */
13 private final int backgroundColor = Color.parseColor("#e9e9e9");
14 /**
15 * 键盘文字颜色
16 */
17 private final int keyTextColor = Color.parseColor("#333333");
18 /**
19 * 键盘列数
20 */
21 private final int spanCount = 10;
22 /**
23 * 键盘 键的间隔
24 */
25 private final int keyButtonMargin = 15;
26 /**
27 * 键盘上下左右的边距
28 */
29 private final int keyboardPadding = 10;
30 /**
31 * 按键点击回调
32 */
33 private OnKeyClickListener onKeyClickListener;
34 private KeyAdapter keyAdapter;
35 public LicensePlateView(Context context) {
36 super(context);
37 init(context);
38 }
39
40 public LicensePlateView(Context context, @Nullable AttributeSet attrs) {
41 super(context, attrs);
42 init(context);
43 }
44 private void init(Context context) {
45 setOrientation(LinearLayout.VERTICAL);
46 setBackgroundColor(backgroundColor);
47 initKeys();
48 RecyclerView recyclerView = new RecyclerView(context);
49 recyclerView.setOverScrollMode(OVER_SCROLL_NEVER);
50 recyclerView.setLayoutManager(new GridLayoutManager(context, spanCount));
51 recyclerView.addItemDecoration(new RecycleGridDivider(keyButtonMargin));
52 int padding = dip2px(context, keyboardPadding);
53 recyclerView.setPadding(padding, padding, padding, padding);
54 addView(recyclerView);
55 keyAdapter = new KeyAdapter(this);
56 recyclerView.setAdapter(keyAdapter);
57 keyAdapter.setNewData(provinceList);
58 }
59 /**
60 * 初始化按键
61 */
62 private void initKeys() {
63 String[] province = getResources().getStringArray(R.array.province);
64 String[] num = getResources().getStringArray(R.array.nums);
65 Collections.addAll(provinceList, province);
66 Collections.addAll(numList, num);
67 }
68 /**
69 * 按键点击事件
70 */
71 @Override
72 public void onClick(View v) {
73 TextView tvKey = v.findViewById(R.id.tv_key);
74 String key = tvKey.getText().toString();
75 if (key.equals("ABC\n123")) {
76 //键盘切换
77 keyAdapter.setNewData(numList);
78 return;
79 } else if (key.equals("省")) {
80 keyAdapter.setNewData(provinceList);
81 return;
82 }
83 if (onKeyClickListener != null) {
84 onKeyClickListener.onKeyClick(key);
85 }
86 }
87 private class KeyAdapter extends RecyclerView.Adapter<KeyAdapter.KeyViewHolder> {
88 private List<String> list = new ArrayList<>();
89 private OnClickListener listener;
90 public KeyAdapter(OnClickListener listener) {
91 this.listener = listener;
92 }
93 @NonNull
94 @Override
95 public KeyAdapter.KeyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
96 View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_key, parent, false);
97 return new KeyViewHolder(view);
98 }
99
100 @Override
101 public void onBindViewHolder(@NonNull KeyAdapter.KeyViewHolder holder, int position) {
102 String key = list.get(position);
103 holder.tvKey.setText(key);
104 holder.itemView.setOnClickListener(listener);
105 if (TextUtils.isEmpty(key)) {
106 holder.itemView.setBackgroundResource(0);
107 //键盘类型切换按键
108 } else if (key.equals("ABC\n123") || key.equals("省")) {
109 holder.tvKey.setTextSize(10);
110 holder.itemView.setBackgroundResource(R.drawable.sel_blue_radius_2);
111 holder.tvKey.setTextColor(Color.WHITE);
112 } else {
113 holder.tvKey.setTextSize(12);
114 holder.itemView.setBackgroundResource(R.drawable.sel_white_radius_2);
115 holder.tvKey.setTextColor(keyTextColor);
116 }
117 }
118 @Override
119 public int getItemCount() {
120 return list.size();
121 }
122 public void setNewData(List<String> list) {
123 this.list.clear();
124 this.list.addAll(list);
125 notifyDataSetChanged();
126 }
127 private class KeyViewHolder extends RecyclerView.ViewHolder {
128 private TextView tvKey;
129 public KeyViewHolder(@NonNull View itemView) {
130 super(itemView);
131 tvKey = itemView.findViewById(R.id.tv_key);
132 }
133 }
134 }
135 public class RecycleGridDivider extends RecyclerView.ItemDecoration {
136 /**
137 * 分割线宽度
138 */
139 private int space;
140
141 public RecycleGridDivider(int space) {
142 this.space = space;
143 }
144 @Override
145 public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
146 GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager();
147 int span = manager.getSpanCount();
148 //为了Item大小均匀,将设定分割线平均分给左右两边Item各一半
149 int offset = space / 2;
150 //得到View的位置
151 int childPosition = parent.getChildAdapterPosition(view);
152 //第一排,顶部不画
153 if (childPosition < span) {
154 //最左边的,左边不画
155 if (childPosition % span == 0) {
156 outRect.set(0, 0, offset, 0);
157 //最右边,右边不画
158 } else if (childPosition % span == span - 1) {
159 outRect.set(offset, 0, 0, 0);
160 } else {
161 outRect.set(offset, 0, offset, 0);
162 }
163 } else {
164 //上下的分割线,就从第二排开始,每个区域的顶部直接添加设定大小,不用再均分了
165 if (childPosition % span == 0) {
166 outRect.set(0, space, offset, 0);
167 } else if (childPosition % span == span - 1) {
168 outRect.set(offset, space, 0, 0);
169 } else {
170 outRect.set(offset, space, offset, 0);
171 }
172 }
173 }
174 }
175 /**
176 * 设置按键点击事件
177 */
178 public void setOnKeyClickListener(OnKeyClickListener listener) {
179 this.onKeyClickListener = listener;
180 }
181 public interface OnKeyClickListener {
182 void onKeyClick(String key);
183 }
184 /**
185 * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
186 */
187 public static int dip2px(Context context, float dpValue) {
188 final float scale = context.getResources().getDisplayMetrics().density;
189 return (int) (dpValue * scale + 0.5f);
190 }
191}
四、对于我们需要输入车牌的`EditText`,需要它禁止弹出系统键盘;设置如下:
1//禁止输入框弹出键盘
2etPlate.setInputType(InputType.TYPE_NULL);
3etPlate.setKeyListener(null);
五、封装好后使用就很简单了
1LicensePlateView plateView = findViewById(R.id.plate_view);
2plateView.setOnKeyClickListener(new LicensePlateView.OnKeyClickListener() {
3 @Override
4 public void onKeyClick(String key) {
5 Editable editable = etPlate.getText();
6 int start = etPlate.getSelectionStart();
7 if (key.equalsIgnoreCase("Del")) {
8 if (editable.length() > 0 && start > 0) {
9 editable.delete(start - 1, start);
10 }
11 return;
12 }
13 editable.insert(start, key);
14 }
15});
总体来说这个View还是很简单的
Demo下载地址:
https://download.youkuaiyun.com/download/a_zhon/11646110
推荐我的慕课网Android实战课程,助你暴力提升Android技术。
https://coding.imooc.com/class/390.html
我创建了一个关于Android的交流群,有兴趣可以加我微信我拉你

如果感觉现在的网络技术文章质量不高,苦于自己的Android技术无法得到明显的提升,感叹没有一帮好的学习伙伴及道友,那么我的知识星球可能就是一片净土,好的学习气氛,更好的技术资源与文章,自由且高效率,快来吧。


本文介绍了如何为Android应用创建一个自定义的车牌输入键盘,包括省份简称、特殊车牌、删除键以及数字字母切换功能。使用`RecyclerView`实现键盘布局,并提供注意事项和代码示例。
4869

被折叠的 条评论
为什么被折叠?



