自定义键盘(二)[通俗易懂]

自定义键盘(二)[通俗易懂]自定义键盘(二)

大家好,又见面了,我是你们的朋友全栈君。

一引言

上一篇文章只是自定义了一个键盘的样式,并未和任何的输入框进行关联。只有和输入框进行关联才能是一个有用的键盘。不知道你有没有注意到应用市场上有这样一类app:第三方输入法app,比如讯飞输入法,搜狗输入法;

第三方输入法app:设置完成之后,手机上所有的输入框都会弹出第三方键盘。它们实现都是通过系统的InputMethodManager类去做的扩展。安装第三方输入法的手机,可以在设置–高级设置-语言和输入法中找到。—-系统级别的输入法

那么有没有app级别的输入法扩展呢?

如果有的话会让关于键盘的开发变得更加容易,于是,笔者就去下载一些炒股app,它们都是实现了类似app级别的键盘,发现设置中并未找到他们关于键盘的定义。笔者也没有google到关于app级别的键盘。笔者认定炒股app中的自定义键盘的实现思路应该也是封装然后关联输入框。

二需求

我们如何能封装一个没有耦合性的自定义键盘,笔者能想到的需求如下:

  • 动态添加到任何布局中
  • 解决和系统键盘显示冲突
  • 动态绑定系统输入框
  • 有show和hide动画,让键盘显示更加优雅
  • 没有耦合,使用方便,尽可能让原生属性有效
  • 键盘特殊按钮监听
  • 解决键盘覆盖输入框的问题
  • 点击非键盘,非输入框区域,让键盘消失。

三实现需求

3.1动态添加到任何布局中

android中每个页面布局都有一个DecorView包裹着,我们可以获取这个DecorView,然后把我们的键盘布局文件添加到这个跟布局下:

(activity.getWindow().getDecorView().findViewById(android.R.id.content));复制代码

但是这样会有一个问题,假如有这样一种布局,页面嵌套ViewPager,ViewPager中嵌套多个Fragment,而他们共同拥有一个DecorView。如果把键盘挂载到这样一个布局中,势必会造成页面之间互相影响。于是,笔者就提供方法让挂载键盘的根布局通过外部传入,至于你是传递DecorView还是传递一个fragment的根布局,由外部决定。

3.2解决和系统键盘显示冲突

这就需要我们把页面中所有的EditText传递到封装的工具类中,调用这个方法隐藏系统键盘

/**
 * 隐藏系统键盘
 *
 * @param editText
 */
public static void hideSystemSoftKeyboard(EditText editText) {
    int sdkInt = Build.VERSION.SDK_INT;
    if (sdkInt >= 11) {
        try {
            Class<EditText> cls = EditText.class;
            Method setShowSoftInputOnFocus;
            setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);
            setShowSoftInputOnFocus.setAccessible(true);
            setShowSoftInputOnFocus.invoke(editText, false);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    } else {
        editText.setInputType(InputType.TYPE_NULL);
    }
}复制代码

然后对应的页面清单文件设置

android:windowSoftInputMode="stateHidden|stateUnchanged"复制代码

让系统键盘不弹出来

3.3动态绑定输入框

系统的输入框是当EditText获取焦点的时候会弹出来,所以这里我们要给传递进来的EditText设置焦点改变监听,通过焦点改变来显示键盘。

key.setOnFocusChangeListener(new View.OnFocusChangeListener() {
    @Override
    public void onFocusChange(View view, boolean b) {
        if (b) {
            currentEditText = (EditText) view;
            showSoftKeyboard();
        }
    }
});复制代码

里有一点需要注意,我们点击确定按钮的时候,当前获取焦点的EditText仍然在获取焦点,再次点击这个EditText,键盘并未弹出。因为焦点没有改变。这就需要我们在我们传递过来的布局文件中添加一个宽高是0的EditText。让用户点击完成的时候,这个EditText获取焦点。

FrameLayout.LayoutParams params2 = new FrameLayout.LayoutParams(0, 0, Gravity.BOTTOM);
rootView.addView(frameLayout, params);
focusReplace = new EditText(context);
rootView.addView(focusReplace, params2);复制代码

3.4有show和hide动画,让键盘显示更加优雅

这无非是系统的View动画,实现起来比较简单

3.5没有耦合,使用方便,尽可能让原生属性有效

这就需要我们用EditText,获取他的属性,然后根据属性去设置键盘的变换

3.6键盘特殊按钮监听

我们写一个外部回调方法即可实现这个需求。

3.7键盘遮挡

这里就需要首先判断是否已经被遮挡,如果被遮挡,需要算出来整个布局需要移动多少,当然键盘布局不能移动。移动方式可以通过属性动画或者scrollBy方法。这里我选择属性动画。

在键盘show出的时候:

//获取传递过来的跟布局的宽高
Rect rect = new Rect();
frameLayout.getWindowVisibleDisplayFrame(rect);
//计算当前获取焦点的输入框在屏幕中的位置
int[] vLocation = new int[2];
currentEditText.getLocationOnScreen(vLocation);
int keyboardTop = vLocation[1] + currentEditText.getHeight() / 2 + currentEditText.getPaddingBottom() + currentEditText.getPaddingTop();
//输入框或基线View的到屏幕的距离 + 键盘高度 如果 超出了屏幕的承载范围, 就需要移动.
int moveHeight = rect.bottom - keyboardTop - keyboardView.getHeight();
moveHeight = moveHeight > 0 ? 0 : moveHeight;
if (moveHeight != 0) {
    rootView.setTag("move");
    //遍历所有的子View,让其向上移动改移动的高度
    for (int i = 0; i < rootView.getChildCount(); i++) {
        if (rootView.getChildAt(i) != frameLayout) {
            rootView.getChildAt(i).setTranslationY(moveHeight);
            ObjectAnimator.ofFloat(rootView.getChildAt(i), "translationY", 0, moveHeight).setDuration(400).start();
        }
    }
}复制代码

在键盘隐藏的时候:

Object tag = rootView.getTag();
if (tag != null) {
    //遍历所有的子View,让其向上移动改移动的高度
    for (int i = 0; i < rootView.getChildCount(); i++) {
        if (rootView.getChildAt(i) != frameLayout) {
            ObjectAnimator.ofFloat(rootView.getChildAt(i), "translationY", 0).setDuration(400).start();
        }
    }
}复制代码

基本使用:

keyboardViewManager = KeyboardViewManager
        .builder()
        .bindEditText(edit1, edit2, edit3)//需要使用自定义键盘的控件
        .showSystemKeyboard(edit4)//需要使用系统键盘的控件
        .bindEditTextCallBack(edit1, new KeyboardViewManager.onSureClickListener() {
            @Override
            public void onSureClick() {

            }
        })//自定义键盘确定回调
        .bindEditTextCallBack(edit2, new KeyboardViewManager.onSureClickListener() {
            @Override
            public void onSureClick() {

            }
        })//自定义键盘确定回调
        .build(this)
        .addKeyboardView(rootView);//需要传入的跟布局复制代码

四.细节使用

4.1键盘默认情况下弹出,我们可以设置输入框的父布局添加一下属性:

android:focusable="true"
android:focusableInTouchMode="true"复制代码

4.2我们可以设置这个输入框只输入数字。模式是输入英文字母

android:inputType="number" 复制代码

4.3点击非键盘和焦点区域,让键盘消失

重写activity的方法,然后调用隐藏键盘方法

@Override
public boolean onTouchEvent(MotionEvent event) {
    keyboardViewManager.hideSoftKeyboard();
    return super.onTouchEvent(event);
}复制代码

假如在Fragment中,在Fragment的onCreateView方法中调用Activity中的onTouchEvent方法:

public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.frag_home_tab, container, false);
    //点击空白区域系统软键盘消失 
    view.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            getActivity().onTouchEvent(motionEvent);
            return false;
        }
    });
    return view;
}复制代码

到此,关于自定义键盘的算是结束,

最后奉上源码

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107292.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 连接失败连接区间变量

    连接失败连接区间变量

    2022年1月12日
    48
  • java算法是什么_什么是java算法

    java算法是什么_什么是java算法什么是java算法算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,java算法就是采用Java语言来实现解决某一问题的清晰指令。算法的特征:输入性:有零个或多个外部量作为算法的输入输出性:算法产生至少一个量作为输出确定性:算法中每条指令清晰,无歧义有穷性:算法中每条指令的执行次数有限,执行每条指令是时间也有限可行性:算法原则上能够精确的运行,而且人们用纸和笔做有限次运算后即可完成程…

    2022年7月9日
    20
  • CentOs6.5安装Docker中:No package docker-io available[通俗易懂]

    CentOs6.5安装Docker中:No package docker-io available[通俗易懂]在Centos中安装docker时出现:No package docker-io available 说是yum没有找到docker这个包,

    2022年6月13日
    29
  • 银行家算法 C语言实现

    银行家算法 C语言实现C语言实现银行家算法这几天老师要求使用C语言实现银行家算法,数据可以自定义。想来想去还是照着书现成的数据来模拟一下。教材使用的是西安电子科大出版社的《计算机操作系统》汤小丹第四版。模拟数据使用的是P121页第4题的数据。听到老师布置题目的第一时间我还是有点懵,看了下书更懵了,这条条框框的判断条件怎么这么多。。沉下心来慢慢看,其实还是挺简单的算法。/*Author:Cnkizy…

    2022年6月10日
    30
  • x201换风扇_x201i拆机风扇清理怎么办【图文】

    x201换风扇_x201i拆机风扇清理怎么办【图文】总所周知,笔记本室友大大小小的配置组装而成的,而笔记本同样的,有时也会存在着或多或少的故障,又或者有时由于好奇心的趋势,让我们相对笔记本内部的相关配置做更深一步的了解,这个时候,我们会选择对笔记本进行拆机,从而对风扇进行清理,但是我们又怕盲目的拆机有可能会对笔记本造成损坏,那么,x201i拆机风扇清理应该怎么办呢?下面,就让我们来认识一下,x201i拆机风扇清理应该怎么办?笔记本散热风扇使用时间长…

    2022年6月27日
    19
  • 微信小程序WebSocket实现聊天对话功能完整源码

    微信小程序WebSocket实现聊天对话功能完整源码微信小程序开发交流qq群173683895承接微信小程序开发。扫码加微信。正文:jsvarapp=getApp();varsocketOpen=false;varframeBuffer_Data,session,SocketTask;varurl=’ws://请填写您的长链接接口地址’;varupload_url=’请填写您的图片上…

    2022年6月18日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号