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

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

  • 横屏效果
    Android自定义输入车牌号键盘、车牌简称 | 数字 | 字母键盘_第1张图片Android自定义输入车牌号键盘、车牌简称 | 数字 | 字母键盘_第2张图片

  • 竖屏效果
    Android自定义输入车牌号键盘、车牌简称 | 数字 | 字母键盘_第3张图片

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

  • 默认展示车牌的省份简称
  • 特殊车牌(使、领、警、港、澳)
  • 删除键
  • 切换为数字和字母按键
  • 车牌号中是没有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

  • LicensePlateView
public class LicensePlateView extends LinearLayout implements View.OnClickListener {

    /**
     * 车牌简称
     */
    private List<String> provinceList = new ArrayList<>();
    /**
     * 0~9,A~Z(车牌里没有I、O字母)
     */
    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();
            //为了Item大小均匀,将设定分割线平均分给左右两边Item各一半
            int offset = space / 2;
            //得到View的位置
            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);
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    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下载地址

你可能感兴趣的:(自定义键盘,车牌号输入键盘,Android自定义View)