Android自定义输入车牌号键盘、车牌简称,数字 ,字母键盘

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

本文来自阿钟的投稿,全文阅读大约十分钟


为了便于用户快捷的输入车牌号码便需要自定义个车牌键盘,而不是使用系统的键盘输入,上效果图:

横屏效果

图片

竖屏效果

图片

一、首先我们要来分析一下需要做哪些东西

  • 默认展示车牌的省份简称

  • 特殊车牌(使、领、警、港、澳)

  • 删除键

  • 切换为数字和字母按键

  • 车牌号中是没有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技术无法得到明显的提升,感叹没有一帮好的学习伙伴及道友,那么我的知识星球可能就是一片净土,好的学习气氛,更好的技术资源与文章,自由且高效率,快来吧。

图片


评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值