IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 验证码输入框效果实现 焦点自动后移 -> 正文阅读

[移动开发]Android 验证码输入框效果实现 焦点自动后移

来吧 先看效果
需求是输入一位后 将其设置为
也就是加密展示,并将焦点自动转移到下一个框中 当输入至最后一个框时 执行一定逻辑
*

原理: 我们写一个recyclerView 并在recyclerView上面放一个EditText ,这里要注意: 要让EditText覆盖recyclerView ,当我们进行输入时 ,时刻监听EditText内容变化, 一有变化时 ,将当前输入的字符设置给recyclerView的适配器 , 刷新就好
在此 我将这个逻辑代码写成了自定义属性格式 ,扩展性比较高, 使用的话也是非常简单 ,一起来看下吧!
在这里插入图片描述

package com.example.text_1.utils;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.GridLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.example.text_1.R;
import java.util.ArrayList;
import java.util.List;

public class CustomEditText extends FrameLayout {
    /**
     * 输入是否明文显示
     */
    private boolean showEncryptionText;
    /**
     * 框数量
     */
    private int num;
    /**
     * 当前输入的是否加粗边框
     */
    private boolean sel_show_frame;
    /**
     * 输入至最后一个元素时是否执行跳转等行为
     */
    private boolean input_ok_jump;
    /**
     * 框的背景图  长度为2   0为默认  1为选中
     */
    private List<Integer> input_back = new ArrayList<>();
    /**
     * 监听输入到末尾时的监听
     */
    public endJumpCLick endJumpCLick;
    /**
     * 框的样式(不设置就使用默认样式)
     */
    private int input_adapter_layout = R.layout.input_adapter_layout;
    /**
     * 框的内容集合
     */
    private List<InputBean> textList = new ArrayList<>();
    /**
     * 框适配器
     */
    private InputAdapter inputAdapter = new InputAdapter(textList);

    public void setEndJumpCLick(CustomEditText.endJumpCLick endJumpCLick) {
        this.endJumpCLick = endJumpCLick;
    }

    public CustomEditText(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init(attrs);
    }

    private void init(AttributeSet attrs) {
        TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.CustomEditText);
        showEncryptionText = typedArray.getBoolean(R.styleable.CustomEditText_ce_show_encryption_Text, true);
        num = typedArray.getInteger(R.styleable.CustomEditText_ce_Num, 6);
        sel_show_frame = typedArray.getBoolean(R.styleable.CustomEditText_ce_sel_show_frame, true);
        input_ok_jump = typedArray.getBoolean(R.styleable.CustomEditText_ce_input_ok_jump, true);
        typedArray.recycle();

        LayoutParams params = new LayoutParams(GridLayout.LayoutParams.MATCH_PARENT, GridLayout.LayoutParams.MATCH_PARENT);
        RecyclerView recyclerView = new RecyclerView(getContext());
        recyclerView.setLayoutParams(params);
        addView(recyclerView);
        EditText editText = new EditText(getContext());
        editText.setBackground(null);
        editText.setMaxLines(num);
        editText.setCursorVisible(false);
        editText.setKeyListener(new DigitsKeyListener(false, false));
        editText.setTextColor(Color.WHITE);
        editText.setTextSize(1);
        editText.setLayoutParams(params);
        addView(editText);
        initAdapter(recyclerView);
        et_custom_editTextListener(editText);
    }

    private void et_custom_editTextListener(EditText et_custom_editText) {
        et_custom_editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                for (int i = 0; i < textList.size(); i++) {
                    textList.get(i).text = i < s.length() ? showEncryptionText ? String.valueOf(s.charAt(i)) : "*" : "";
                    textList.get(i).isSelect = false;
                }
                if (s.length() < num) textList.get(s.length()).isSelect = true;
                if (input_ok_jump && s.length() == num && endJumpCLick != null) {
                    endJumpCLick.onJumpClick(s.toString());
                }
                inputAdapter.notifyDataSetChanged();
            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });
    }

    private void initAdapter(RecyclerView rv_custom_editText) {
        textList.clear();
        for (int i = 0; i < num; i++) textList.add(new InputBean("", i == 0 ? true : false));
        rv_custom_editText.setLayoutManager(new GridLayoutManager(getContext(), textList.size()));
        rv_custom_editText.setAdapter(inputAdapter);
        inputAdapter.notifyDataSetChanged();
    }

    public CustomEditText setInput_backList(List<Integer> data) {
        if (sel_show_frame) {
            if (data.size() == 2) {
                input_back.clear();
                input_back.add(data.get(0));
                input_back.add(data.get(1));
            } else {
                Toast.makeText(getContext(), "数量不符, 添加失败!", Toast.LENGTH_SHORT).show();
            }
        }
        return this;
    }

    public CustomEditText setInputAdapterLayout(int layoutId) {
        input_adapter_layout = layoutId;
        return this;
    }

    class InputBean {
        public String text;
        public boolean isSelect;

        public InputBean(String text, boolean isSelect) {
            this.text = text;
            this.isSelect = isSelect;
        }
    }

    class InputAdapter extends RecyclerView.Adapter {
        public List<InputBean> list;

        public InputAdapter(List<InputBean> list) {
            this.list = list;
        }

        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new ViewHolder(LayoutInflater.from(parent.getContext()).inflate(input_adapter_layout, parent, false));
        }

        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
            ViewHolder holder1 = (ViewHolder) holder;
            if (sel_show_frame && input_back.size() == 2) {
                holder1.textView.setBackgroundResource(list.get(position).isSelect ? input_back.get(0) : input_back.get(1));
            }
            holder1.textView.setText(list.get(position).text);
        }

        @Override
        public int getItemCount() {
            return list.size();
        }

        class ViewHolder extends RecyclerView.ViewHolder {
            public TextView textView;

            public ViewHolder(View itemView) {
                super(itemView);
                textView = itemView.findViewById(R.id.itemEdit);
            }
        }
    }

    public interface endJumpCLick {
        void onJumpClick(String s);
    }
}

属性如下:

  <declare-styleable name="CustomEditText">
  		//输入是否明文显示
        <attr name="ce_show_encryption_Text" format="boolean" />
        //框的数量
        <attr name="ce_Num" format="integer" />
        //当前输入的框是否有加粗效果
        <attr name="ce_sel_show_frame" format="boolean" />
        //当输入至最后一位时 ,是否执行逻辑  比如调接口等等
        <attr name="ce_input_ok_jump" format="boolean" />
    </declare-styleable>

框的背景样式布局 默认为此样式布局 如果需要更改 则替换布局即可

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="60dp">

    <TextView
        android:id="@+id/itemEdit"
        android:layout_width="50dp"
        android:layout_height="match_parent"
        android:background="@drawable/input_default_back_view"
        android:gravity="center"
        android:textColor="#000000"
        android:textSize="24sp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

具体用法: 在activity中:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".DemoActivity">

    <com.example.text_1.utils.CustomEditText
        android:id="@+id/ce_input"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:ce_sel_show_frame="false"
        app:ce_Num="4"
        app:ce_show_encryption_Text="true"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>

此外如果设置了加粗边框 则需要在代码中动态设置背景样式 以数组格式进行设置 下标0为当前存在焦点的样式 1为失去焦点的样式 不可以多传或少传 数组长度只能为2
加粗边框/不加粗xml如下:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="2dp"
        android:color="@color/black_tran30" />
    <corners android:radius="3dp" />
</shape>


<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <stroke
        android:width="0.5dp"
        android:color="#A3A3A3" />
    <corners android:radius="3dp" />
</shape>
package com.example.text_1;

import com.example.text_1.utils.BaseActivity;
import com.example.text_1.utils.CustomEditText;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView;

public class DemoActivity extends BaseActivity {
    @BindView(R.id.ce_input)
    CustomEditText ceInput;

    @Override
    public void initView() {
        ceInput.setInput_backList(inputListData());
        ceInput.setEndJumpCLick(s -> showToast(s));
    }

    /**
     * 背景框
     *
     * @return 返回集合
     */
    private List<Integer> inputListData() {
        ArrayList<Integer> integers = new ArrayList<>();
        integers.add(R.drawable.edit_shape_focus);
        integers.add(R.drawable.edit_shape_not_focus);
        return integers;
    }

    @Override
    public int getLayout() {
        return R.layout.activity_demo;
    }
}

最终 效果如下:
在这里插入图片描述
希望对你有所帮助

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-08-04 11:19:40  更:2021-08-04 11:19:58 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/5 20:15:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码