1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > android 自定义数字软键盘 (笔记)Android自定义数字键盘

android 自定义数字软键盘 (笔记)Android自定义数字键盘

时间:2023-11-25 03:40:21

相关推荐

android 自定义数字软键盘 (笔记)Android自定义数字键盘

前言

最近Android开发中用到了自定义数字键盘,网上找的demo不能满足我的需求,比如删除和插入的时候只能在最后删除和插入,不能通过滑动键盘来移动光标。所以现在完成后把它总结写出来。

概述

主要实现以下功能:

(1)只有数字键,包括没有标点符号。

(2)可以在任意点插入和删除数字。

(3)可以通过手指左右滑动键盘来改变光标位置。

(4)输入框右边删除图标和按钮可随着内容有无变化。

(5)每三个数字空一格,输入框最多输入13个字符(包括空格)。

先上运行效果(请忽略UI -_-):

keyboard.gif

步骤:

1、新建一个KeyboardView.java文件。用来自定义所需要的键盘。

首先初始化绑定布局文件。

private void init(Context context, AttributeSet attrs, int defStyleAttr) {

LayoutInflater.from(context).inflate(R.layout.layout_key_board, this);

recyclerView = (RecyclerView) findViewById(R.id.recycler_view);

rl_back=findViewById(R.id.rl_back);

rl_back.setOnClickListener(new OnClickListener() {

@Override

public void onClick(View view) { // 点击关闭键盘

dismiss();

}

});

initData();

initView();

initAnimation();

}

填充数据(如果需要标点符号,则在i==9中填充即可)

private void initData() {

keyboardWords = new ArrayList<>();

for (int i = 0; i < 12; i++) {

if (i < 9) {

keyboardWords.add(String.valueOf(i + 1));

} else if (i == 9) {

keyboardWords.add("");

} else if (i == 10) {

keyboardWords.add("0");

} else {

keyboardWords.add("");

}

}

}

设置适配器

private void initView() {

int spanCount = 12;

recyclerView.setLayoutManager(new GridLayoutManager(getContext(), 3));

recyclerView.setNestedScrollingEnabled(false);

recyclerView.addItemDecoration(new SpaceItemDecoration(spanCount));

adapter = new KeyboardAdapter(getContext(), keyboardWords);

recyclerView.setAdapter(adapter);

}

对键盘的操作

//判断软键盘的状态

public boolean isVisible() {

if (getVisibility() == VISIBLE) {

return true;

}

return false;

}

//弹出软键盘

public void show() {

startAnimation(animationIn);

setVisibility(VISIBLE);

}

//关闭软键盘

public void dismiss() {

if (isVisible()) {

startAnimation(animationOut);

setVisibility(GONE);

}

}

2、Adapter操作。

private Context context;

private List datas;

private OnKeyboardClickListener listener;

public KeyboardAdapter(Context context, List datas) {

this.context = context;

this.datas = datas;

}

@Override

public KeyboardHolder onCreateViewHolder(ViewGroup parent, int viewType) {

View view = LayoutInflater.from(context).inflate(R.layout.item_key_board, parent, false);

KeyboardHolder holder = new KeyboardHolder(view);

setListener(holder);

return holder;

}

private void setListener(final KeyboardHolder holder) {

holder.tvKey.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

if (listener != null) {

if (holder.getAdapterPosition() != 9) {

listener.onKeyClick(view, holder, holder.getAdapterPosition());

}

}

}

});

holder.rlDel.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

if (listener != null) {

listener.onDeleteClick(view, holder, holder.getAdapterPosition());

}

}

});

}

@Override

public void onBindViewHolder(KeyboardHolder holder, int position) {

if (position == 9) {

holder.setVisibility(false);

} else if (position == 11) {

holder.rlDel.setVisibility(View.VISIBLE);

holder.tvKey.setVisibility(View.GONE);

} else {

holder.tvKey.setText(datas.get(position));

}

}

@Override

public int getItemCount() {

return datas == null ? 0 : datas.size();

}

class KeyboardHolder extends RecyclerView.ViewHolder {

public TextView tvKey;

public RelativeLayout rlDel;

private View convertView;

public KeyboardHolder(View itemView) {

super(itemView);

convertView = itemView;

tvKey = itemView.findViewById(R.id.tv_key);

rlDel = itemView.findViewById(R.id.rl_del);

}

public View getconvertView() {

return convertView;

}

public void setVisibility(boolean b) {

RecyclerView.LayoutParams param = (RecyclerView.LayoutParams) itemView.getLayoutParams();

if (b) {

param.height = LinearLayout.LayoutParams.WRAP_CONTENT;

param.width = LinearLayout.LayoutParams.MATCH_PARENT;

itemView.setVisibility(View.VISIBLE);

} else {

itemView.setVisibility(View.GONE);

param.height = 0;

param.width = 0;

}

itemView.setLayoutParams(param);

}

}

public interface OnKeyboardClickListener {

void onKeyClick(View view, RecyclerView.ViewHolder holder, int position);

void onDeleteClick(View view, RecyclerView.ViewHolder holder, int position);

}

public void setOnKeyboardClickListener(OnKeyboardClickListener listener) {

this.listener = listener;

}

}

3、在Activity中的运用。

关闭系统键盘

private void enableSystemKeyboard() {

getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);

try {

Class cls = EditText.class;

Method setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);

setShowSoftInputOnFocus.setAccessible(true);

setShowSoftInputOnFocus.invoke(videoIdEt, false);

} catch (Exception e) {

e.printStackTrace();

}

}

键盘数字按钮的点击事件,并且获取输入当前光标位置

@SuppressLint("SetTextI18n")

@Override

public void onKeyClick(View view, RecyclerView.ViewHolder holder, int position) {

String editText = videoIdEt.getText().toString();

switch (position) {

case 9:

break;

default:

//获取当前光标位置

int index = videoIdEt.getSelectionStart();

if (index != videoIdEt.getText().length()) {

//在光标处插入数字

String inputEditText = keyboardNumbers.get(position);

Log.d(TAG, "inputEditText:" + inputEditText);

videoIdEt.getText().insert(index, inputEditText);

} else {

videoIdEt.setText(videoIdEt.getText().toString().trim() + keyboardNumbers.get(position));

videoIdEt.setSelection(videoIdEt.getText().length());

}

if (videoIdEt.getText().length() > 0) {

findViewById(R.id.ai_long_tv_confirm).setBackgroundResource(R.drawable.bg_determine_text);

Drawable drawable = getResources().getDrawable(R.drawable.ic_delete1);

//设置 ClickableEditText中只显示左边图标,删除图标可见

videoIdEt.setCompoundDrawablesWithIntrinsicBounds(mDrawable, null, drawable,null);

}

break;

}

}

手指触摸事件:获取手指按下和滑动停止的位置。将结果传给手势监听。

private View.OnTouchListener onTouchListener = new View.OnTouchListener() {

@RequiresApi(api = Build.VERSION_CODES.ECLAIR)

@SuppressLint("ClickableViewAccessibility")

@Override

public boolean onTouch(View view, MotionEvent motionEvent) {

if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {

Log.d(TAG, "MotionEvent.ACTION_DOWN");

}

if (motionEvent.getAction() == MotionEvent.ACTION_UP) {

Log.d(TAG, "MotionEvent.ACTION_UP");

refreshStartPoint = true;

}

if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {

if (refreshStartPoint) {

startPointEvent = motionEvent.getX(0);

curatorIndex = videoIdEt.getSelectionStart();

}

refreshStartPoint = false;

stopPointEvent = motionEvent.getX();

Log.d(TAG, "MotionEvent.ACTION_MOVE");

}

return mDetector.onTouchEvent(motionEvent);

}

};

用户手势的监测。计算开始和停止滑动距离的大小(滑动前和滑动后的距离),通过计算滑动距离来计算光标移动多少,并通过距离的正负来判断滑动的方向,从而达到在键盘上滑动来控制光标移动的目的。

@RequiresApi(api = Build.VERSION_CODES.CUPCAKE)

private void initGestureDetector() {

mDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {

@Override

public boolean onDown(MotionEvent motionEvent) {

Log.d(TAG, "onDown");

return true;

}

@Override

public void onShowPress(MotionEvent motionEvent) {

Log.d(TAG, "onShowPress");

}

@Override

public boolean onSingleTapUp(MotionEvent motionEvent) {

Log.d(TAG, "onShowPress");

return false;

}

@Override

public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {

DisplayMetrics displayMetrics = getResources().getDisplayMetrics();

mScreenWidth = displayMetrics.widthPixels;

float x = stopPointEvent - startPointEvent;

float newPercent = Math.abs(x) / mScreenWidth;

int range = (int) ((videoIdEt.getText().length()) * newPercent);

int newIndex;

if (x > 0) {

newIndex = curatorIndex + range;

if (curatorIndex == videoIdEt.getText().length()) {

videoIdEt.setSelection(curatorIndex);

}

if (newIndex > videoIdEt.getText().length()) {

videoIdEt.setSelection(videoIdEt.getText().length());

} else {

videoIdEt.setSelection(newIndex);

}

} else {

newIndex = curatorIndex - range;

if (curatorIndex == 0) {

videoIdEt.setSelection(curatorIndex);

}

if (newIndex < 0) {

videoIdEt.setSelection(0);

} else {

videoIdEt.setSelection(newIndex);

}

}

return false;

}

@Override

public void onLongPress(MotionEvent motionEvent) {

Log.d(TAG, "onLongPress");

}

@Override

public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {

// startPointEvent=motionEvent1;

Log.d(TAG, "onFling: " + "motionEvent:" + motionEvent + "motionEvent1" + motionEvent1);

return false;

}

});

}

接着我们实现每三个数字输入一个空格。通过对ClickableEditText的监听来达到这一目的。

private TextWatcher watcher = new TextWatcher() {

@Override

public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {

}

@Override

public void onTextChanged(CharSequence charSequence, int start, int before, int i2) {

if (isTextChanging) {

isTextChanging = false;

return;

}

isTextChanging = true;

String result = "";

String newStr = charSequence.toString();

newStr = newStr.replace(" ", "");

int index = 0;

while ((index + 3) < newStr.length()) {

result += (newStr.substring(index, index + 3) + " ");

index += 3;

}

result += (newStr.substring(index, newStr.length()));

int i = videoIdEt.getSelectionStart();

videoIdEt.setText(result);

try {

if (i % 4 == 0 && before == 0) {

if (i + 1 <= result.length()) {

videoIdEt.setSelection(i + 1);

} else {

videoIdEt.setSelection(result.length());

}

} else if (before == 1 && i < result.length()) {

videoIdEt.setSelection(i);

} else if (before == 0 && i < result.length()) {

videoIdEt.setSelection(i);

} else {

videoIdEt.setSelection(result.length());

}

} catch (Exception e) {

e.printStackTrace();

}

}

@Override

public void afterTextChanged(Editable editable) {

}

};

对右下角删除按钮的监听,只能删除一个一个删除,不能一下删除所输入的内容

@Override

public void onDeleteClick(View view, RecyclerView.ViewHolder holder, int position) {

int currentIndex = videoIdEt.getSelectionStart();

if (currentIndex > 0) {

videoIdEt.getText().delete(currentIndex - 1, currentIndex);

if (videoIdEt.getText().length() == 0) {

//设置 ClickableEditText中只显示左边图标,删除图标不可见

videoIdEt.setCompoundDrawablesWithIntrinsicBounds(mDrawable, null, null,null);

findViewById(R.id.ai_long_tv_confirm).setBackgroundResource(R.drawable.bg_determine_disable);

}

}

}

输入框右边删除按钮的点击事件,点击可消除所有输入的内容。

@Override

public void onDrawableRightClick(View view) {

switch (view.getId()) {

case R.id.ai_long_et_video_code:

videoIdEt.getText().clear();

//设置 ClickableEditText中只显示左边图标,删除图标不可见

videoIdEt.setCompoundDrawablesWithIntrinsicBounds(mDrawable, null, null,null);

findViewById(R.id.ai_long_tv_confirm).setBackgroundResource(R.drawable.bg_determine_disable);

break;

default:

break;

}

}

结论

以上就是整个项目的实现过程,注意一点,ClickableEditText是自定义的一个EditText,由于使用ConstraintLayout,在输入框的前后两端加按钮,是为了可以点击右边删除按钮能删除所有输入的内容所写。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。