首先来分析一下软键盘的基本属性
- 软键盘的实现
- 点击输入框从底部弹出软键盘
- 弹出软键盘后焦点在输入框
- 弹出软键盘不遮挡输入框
软键盘的实现
可以使用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)
{
}
});
}
}