Android 自定义软键盘遇到的问题

来源:互联网 发布:pmi指数知乎 编辑:程序博客网 时间:2024/06/10 15:18

首先来分析一下软键盘的基本属性
- 软键盘的实现
- 点击输入框从底部弹出软键盘
- 弹出软键盘后焦点在输入框
- 弹出软键盘不遮挡输入框

软键盘的实现
可以使用KeyboardView也可以自己写布局写点击事件(除特殊情况不推荐)
KeyboardView的简单实现方法
一、在res下新建xml文件夹,在xml文件夹中新建keyboard.xml文件

<?xml version="1.0" encoding="utf-8"?><Keyboard xmlns:android="http://schemas.android.com/apk/res/android"          android:keyWidth="33.3333%p" android:horizontalGap="0px"          android:verticalGap="0px" android:keyHeight="80dp">    <Row>        <Key android:codes="55" android:keyLabel="7" />        <Key android:codes="56" android:keyLabel="8" />        <Key android:codes="57" android:keyLabel="9" android:keyEdgeFlags="right"/>    </Row>    <Row>        <Key android:codes="52" android:keyLabel="4" />        <Key android:codes="53" android:keyLabel="5" />        <Key android:codes="54" android:keyLabel="6" android:keyEdgeFlags="right"/>    </Row>    <Row>        <Key android:codes="49" android:keyLabel="1" />        <Key android:codes="50" android:keyLabel="2" />        <Key android:codes="51" android:keyLabel="3" android:keyEdgeFlags="right"/>    </Row>    <Row>        <Key android:codes="46" android:keyLabel="." />        <Key android:codes="48" android:keyLabel="0" />        <Key android:codes="-3" android:keyEdgeFlags="right" android:keyLabel="OK"/>    </Row></Keyboard>

二、这个地方有的实现有点不一样,一般来说不应该在每一个布局里都加入KeyboardViw,比如我使用的在MainActivity,Main里面全是fragment所以就直接在布局里面了

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@drawable/img_bg">    <FrameLayout        android:id="@+id/frame"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:paddingTop="50dp">    </FrameLayout>    <android.inputmethodservice.KeyboardView        android:id="@+id/keyboardview"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:background="@color/write"        android:layout_alignParentBottom="true"        android:focusable="true"        android:usableInTouchMode="true"        android:visibility="invisible"/></RelativeLayout>

然后

import android.animation.Animator;import android.animation.AnimatorInflater;import android.animation.AnimatorSet;import android.animation.ObjectAnimator;import android.animation.ValueAnimator;import android.app.Activity;import android.content.Context;import android.inputmethodservice.InputMethodService;import android.inputmethodservice.Keyboard;import android.inputmethodservice.KeyboardView;import android.media.AudioManager;import android.text.Editable;import android.util.Log;import android.view.KeyEvent;import android.view.LayoutInflater;import android.view.View;import android.view.inputmethod.InputConnection;import android.widget.EditText;import com.kubu.terminal.R;import java.util.List;import static android.content.Context.AUDIO_SERVICE;/** * Created by steven on 2017/7/31. */public class KeyBoradUtil extends InputMethodService implements KeyboardView.OnKeyboardActionListener{    private Context mContext;//上下文对象    private KeyboardView mKeyboardView;    private Keyboard mKeyboard;    private EditText mEdit;    /**     * 必须activity作为上下文对像 *     *     * @param context     */    public KeyBoradUtil(Context context)    {        mContext = context;        //初始化键盘布局,下面在放进 KeyBoardView里面去。        mKeyboard = new Keyboard(mContext, R.xml.keyboard);        //配置keyBoardView        try        {            mKeyboardView = (KeyboardView) ((Activity)mContext).findViewById(R.id.keyboardview);            mKeyboardView.setKeyboard(mKeyboard); //设置键盘            mKeyboardView.setEnabled(true);            mKeyboardView.setPreviewEnabled(false);   //这个是,效果图按住是出来的预览图。            //设置监听,不设置的话会报错。监听放下面了。            mKeyboardView.setOnKeyboardActionListener(this);        } catch (Exception e)        {            Log.e("sun", "keyview初始化失败");        }    }    public void setEdit(EditText mEdit)    {        this.mEdit = mEdit;    }    @Override    public void onPress(int primaryCode)    {    }    @Override    public void onRelease(int primaryCode)    {    }    @Override    public void onKey(int primaryCode, int[] keyCodes)    {        Editable editable = mEdit.getText();        int start = mEdit.getSelectionStart();        if (primaryCode == Keyboard.KEYCODE_CANCEL)        {// 完成            hideKeyboard();        } else if (primaryCode == Keyboard.KEYCODE_DELETE)        {// 回退            if (editable != null && editable.length() > 0)            {                if (start > 0)                {                    editable.delete(start - 1, start);                }            }        } else if (primaryCode == 57419)        { // go left            if (start > 0)            {                mEdit.setSelection(start - 1);            }        } else if (primaryCode == 57421)        { // go right            if (start < mEdit.length())            {                mEdit.setSelection(start + 1);            }        } else        {            editable.insert(start, Character.toString((char) primaryCode));        }    }    @Override    public void onText(CharSequence text)    {    }    @Override    public void swipeLeft()    {    }    @Override    public void swipeRight()    {    }    @Override    public void swipeDown()    {    }    @Override    public void swipeUp()    {    }    //显示软键盘    public void showKeyboard()    {        int visibility = mKeyboardView.getVisibility();        if (visibility == View.GONE || visibility == View.INVISIBLE)        {            mKeyboardView.setVisibility(View.VISIBLE);            int hight = mKeyboardView.getHeight();            Log.d("TAG",hight+"");            ObjectAnimator bad = ObjectAnimator.ofFloat(mKeyboardView, "translationY", hight, 0);            bad.setDuration(300);            bad.start();        }    }    //关闭软键盘    public void hideKeyboard()    {        int visibility = mKeyboardView.getVisibility();        if (visibility == View.VISIBLE)        {            int hight = mKeyboardView.getHeight();            ObjectAnimator bad = ObjectAnimator.ofFloat(mKeyboardView, "translationY", 0, hight);            bad.setDuration(300);            bad.start();            bad.addListener(new Animator.AnimatorListener()            {                @Override                public void onAnimationStart(Animator animation)                {                }                @Override                public void onAnimationEnd(Animator animation)                {                    mKeyboardView.setVisibility(View.INVISIBLE);                }                @Override                public void onAnimationCancel(Animator animation)                {                }                @Override                public void onAnimationRepeat(Animator animation)                {                }            });        }    }}

注意在布局里KeyboardView的android:visibility=”invisible”不能为gone,否则getHeight()为空 ,然后初始化 mKeyBoard = new KeyBoradUtil(getActivity()),并在editText的setOnTouchListener里面显示软键盘。

    @Override    public boolean onTouch(View v, MotionEvent event)    {        switch (v.getId())        {            case R.id.et_phone:                //隐藏系统软键盘                setInputType(et_phone);                mKeyBoard.setEdit(et_phone);                break;            case R.id.et_password:                //隐藏系统软键盘                setInputType(et_password);                mKeyBoard.setEdit(et_password);                break;        }       mKeyBoard.showKeyboard();        return false;    }    private void setInputType(EditText editText)    {        if (android.os.Build.VERSION.SDK_INT <= 10)        {//4.0以下 danielinbiti            editText.setInputType(InputType.TYPE_NULL);        } else        {            getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);            try            {                Class<EditText> cls = EditText.class;                Method setShowSoftInputOnFocus = cls.getMethod("setShowSoftInputOnFocus", boolean.class);                setShowSoftInputOnFocus.setAccessible(true);                setShowSoftInputOnFocus.invoke(editText, false);            } catch (Exception e)            {                e.printStackTrace();            }        }    }

像我上面说的整个工程就一个Activity,初始化以及显示都在那一个Activity里面,那么如果不是这样的呢,额…,想过使用PopupWindows,但是PopupWindows弹出后,输入框的光标没有了(⊙﹏⊙),而且点返回按钮的时候只是仅仅关闭弹窗(跟实际软键盘效果不符,可能有其他处理方法,感觉没意义),然后又想到用addView的方式加进去,又发现不同布局可能最外层可能不一样,没法统一处理,目前没找到好的解决办法。

最后不遮挡输入框的做法,很简单,我们知道了软键盘的高度,那么通过一系列的计算通过view.scrollTo(0,editH-keyboardH+10);移动布局就行了,具体看代码

为了拿到View,我在KeyBoradUtil中加了个setView()

public void setView(View view){        this.view = view;}
 public void showKeyboard() {        //计算输入框底部到父布局顶部的距离,有50dp的padding        int editH = mEdit.getBottom()+DisplayUtil.dip2px(mContext,50);        //计算软键盘顶部到父布局顶部的距离        int keyboardH = mKeyboardView.getTop();        //移动布局        if (editH>keyboardH)        {            if (view != null)            {                //加了10的偏移,看个人爱好,可以不加                view.scrollTo(0,editH-keyboardH+10);            }        }        int visibility = mKeyboardView.getVisibility();        if (visibility == View.GONE || visibility == View.INVISIBLE)        {            mKeyboardView.setVisibility(View.VISIBLE);            int hight = mKeyboardView.getHeight();            Log.d("TAG",hight+"");            ObjectAnimator bad = ObjectAnimator.ofFloat(mKeyboardView, "translationY", hight, 0);            bad.setDuration(200);            bad.start();        } }
 public void hideKeyboard() {        int visibility = mKeyboardView.getVisibility();        if (visibility == View.VISIBLE)        {            if (view != null)            {                //布局恢复                view.scrollTo(0,0);            }            int hight = mKeyboardView.getHeight();            ObjectAnimator bad = ObjectAnimator.ofFloat(mKeyboardView, "translationY", 0, hight);            bad.setDuration(200);            bad.start();            bad.addListener(new Animator.AnimatorListener()            {                @Override                public void onAnimationStart(Animator animation)                {                }                @Override                public void onAnimationEnd(Animator animation)                {                    mKeyboardView.setVisibility(View.INVISIBLE);                }                @Override                public void onAnimationCancel(Animator animation)                {                }                @Override                public void onAnimationRepeat(Animator animation)                {                }            });        } }
原创粉丝点击