基本介绍
软键盘的显示原理 软键盘其实是一个Dialog。InputMethodService为我们的输入法创建了一个Dialog,并且对某些参数进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统会对当前的主窗口进行调整,以便留出相应的空间来显示该Dialog在底部,或者全屏。
控制活动主窗口调整方式 Android定义了一个属性windowSoftInputMode,用它可以让程序控制活动主窗口调整的方式。我们可以在配置文件AndroidManifet.xml中对Activity进行设置。这个属性的设置将会影响两件事情: 1>软键盘的状态——隐藏或显示。 2>活动的主窗口调整——是否减少活动主窗口大小以便腾出空间放软键盘或是否当活动窗口的部分被软键盘覆盖时它的内容的当前焦点是可见的。 该属性的设置必须是下面列表中的一个值,或一个“state…”值加一个“adjust…”值的组合。
- "stateUnspecified": 软键盘的状态(隐藏或可见)没有被指定。系统将选择一个合适的状态,或依赖于主题的设置。这个是软键盘行为的默认设置。
- "stateUnchanged":软键盘被保持上次的状态。当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示。
- "stateHidden":当用户选择该Activity时,软键盘被隐藏。
- "stateAlwaysHidden": 软键盘总是被隐藏的,即使当该Activity主窗口获取焦点时。
- "stateVisible": 软键盘是可见的。
- "stateAlwaysVisible": 当用户选择这个Activity时,软键盘是可见的。
- "adjustUnspecified":这个是主窗口默认的行为设置,系统自动决定是采用平移模式还是压缩模式,决定因素在于内容是否可以滚动。
- "adjustResize":压缩模式, 当软键盘弹出时,该Activity总是调整屏幕的大小以便留出软键盘的空间。
- "adjustPan":平移模式,当输入框不会被遮挡时,该模式没有对布局进行调整;然而当输入框将要被遮挡时,窗口就会进行平移。也就是说,该模式始终是保持输入框为可见。该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间,相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。
InputMethodManager 输入法管理器
一、常用方法: 获取输入法管理器 InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE); 显示输入法 imm.showSoftInput(View, InputMethodManager.SHOW_FORCED); 如此控件有需要,则显式要求软键盘区域向用户显示 切换输入法 imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED); 如果输入法在窗口上已经显示,则隐藏;如果隐藏,则显示输入法到窗口上 隐藏系统默认的输入法 imm.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS); 获取输入法打开的状态 boolean isOpen=imm.isActive();
二、让EditText默认不弹出软件键盘
- 方法一:在AndroidMainfest.xml中设置此Activity的android:windowSoftInputMode="adjustUnspecified|stateHidden";或代码中设置getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN)。
- 方法二:使用EditText的clearFocus方法让EditText失去焦点。
- 方法三:强制隐藏Android输入法窗口 imm.hideSoftInputFromWindow(et.getWindowToken(),0)。
- 方法四:让EditText始终不弹出软键盘 et.setInputType(InputType.TYPE_NULL);或imm.hideSoftInputFromWindow(et.getApplicationWindowToken(), 0)。
系统API
常量值
- HIDE_IMPLICIT_ONLY hideSoftInputFromWindow(IBinder, int)中的标志,表示如果用户未显式地显示软键盘窗口,则隐藏窗口。
- HIDE_NOT_ALWAYS hideSoftInputFromWindow(IBinder, int)中的标志,表示软键盘窗口总是隐藏,除非开始时以SHOW_FORCED显示。
- RESULT_HIDDEN showSoftInput(View, int, ResultReceiver)和hideSoftInputFromWindow(IBinder, int, ResultReceiver)中ResultReceiver结果代码标志:软键盘窗口从显示切换到隐藏时的状态。
- RESULT_SHOWN showSoftInput(View, int, ResultReceiver)和hideSoftInputFromWindow(IBinder, int, ResultReceiver)中ResultReceiver结果代码标志:软键盘窗口从隐藏切换到显示时的状态。
- RESULT_UNCHANGED_HIDDEN showSoftInput(View, int, ResultReceiver)和hideSoftInputFromWindow(IBinder, int, ResultReceiver)中ResultReceiver结果代码标志:软键盘窗口不变保持隐藏时的状态。
- RESULT_UNCHANGED_SHOWN showSoftInput(View, int, ResultReceiver)和hideSoftInputFromWindow(IBinder, int, ResultReceiver)中ResultReceiver结果代码标志:软键盘窗口不变保持显示时的状态。
- SHOW_FORCED showSoftInput(View, int)中的标志,表示用户强制打开输入法(如长按菜单键),一直保持打开直至只有显式关闭。
- SHOW_IMPLICIT showSoftInput(View, int)中的标志,表示隐式显示输入窗口,非用户直接要求。窗口可能不显示。
公共方法
- public void displayCompletions (View view, CompletionInfo[] completions) 输入法自动完成
- public InputMethodSubtype getCurrentInputMethodSubtype () 获取当前输入法类型
- public List<InputMethodInfo> getEnabledInputMethodList () 获取已启用输入法列表
- public List<InputMethodSubtype> getEnabledInputMethodSubtypeList (InputMethodInfo imi, boolean allowsImplicitlySelectedSubtypes)
- public List<InputMethodInfo> getInputMethodList () 获取输入法列表
- public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes ()
- public void hideSoftInputFromInputMethod (IBinder token, int flags) 关闭/隐藏输入法软键盘区域,用户不再看到或与其交互。只能由当前激活输入法调用,因需令牌(token)验证。参数,token 在输入法启动时提供令牌验证,验证后可对其进行操作。flags 提供额外的操作标志。当前可以为0或 HIDE_IMPLICIT_ONLY, HIDE_NOT_ALWAYS等位设置。
- public boolean hideSoftInputFromWindow (IBinder windowToken, int flags), hideSoftInputFromWindow(IBinder, int, ResultReceiver)的无返回值版:从窗口上下文中确定当前接收输入的窗口,隐藏其输入法窗口。参数,windowToken 由窗口请求View.getWindowToken()返回得到的令牌(token)。flags 提供额外的操作标志。当前可以为0或 HIDE_IMPLICIT_ONLY位设置。
- public boolean hideSoftInputFromWindow (IBinder windowToken, int flags, ResultReceiver resultReceiver),从窗口上下文中确定当前接收输入的窗口,要求隐藏其软键盘窗口。它可由用户调用并得到结果而不仅仅是显式要求输入法窗口隐藏。参数,windowToken 由窗口请求View.getWindowToken()返回得到的令牌(token)。flags 提供额外的操作标志。当前可以为0或 HIDE_IMPLICIT_ONLY位设置。resultReceiver 如不为空,当IME处理请求告诉你完成时调用。你收到的结果码可以是RESULT_UNCHANGED_SHOWN, RESULT_UNCHANGED_HIDDEN, RESULT_SHOWN, 或RESULT_HIDDEN。
- public void hideStatusIcon (IBinder imeToken) 隐藏状态栏图标
- public boolean isAcceptingText () 当前服务视图接受全文编辑返回真。没有输入法联接为false,这时其只能处理原始按键事件。
- public boolean isActive (View view) 视图为当前输入的激活视图时返回真。
- public boolean isActive () 输入法中的任意视图激活时返回真。
- public boolean isFullscreenMode () 判断相关输入法是否以全屏模式运行。全屏时,完全覆盖你的UI时,返回真,否则返回假。
- public boolean isWatchingCursor (View view) 如当前输入法要看到输入编辑者的光标位置时返回真。
- public void restartInput (View view) 如有输入法联接至视图,重启输入以显示新的内容。可在以下情况时调用此方法:视图的文字导致输入法外观变化或有按键输入流,如应用程序调用TextView.setText()时。参数,view 文字发生变化的视图。
- public void sendAppPrivateCommand (View view, String action, Bundle data),对当前输入法调用 InputMethodSession.appPrivateCommand()。参数,view 可选的发送命令的视图,如你要发送命令而不考虑视图附加到输入法,此项可以为空。action 执行的命令名称。必须是作用域的名称,如前缀包名称,这样不同的开发者就不会创建冲突的命令。data 命令中包含的任何数据。
- public boolean setCurrentInputMethodSubtype (InputMethodSubtype subtype) 此方法为3.0中新增的方法
- public void setInputMethod (IBinder token, String id),强制切换到新输入法部件。只能由持有token的应用程序(application)或服务(service) 调用当前激活输入法。参数,token 在输入法启动时提供令牌验证,验证后可对其进行操作。id 切换到新输入法的唯一标识。
- public void setInputMethodAndSubtype (IBinder token, String id, InputMethodSubtype subtype),强制切换到一个新的输入法和指定的类型。只能由持有token的应用程序(application)或服务(service) 调用当前激活输入法。参数,token 在输入法启动时提供令牌验证,验证后可对其进行操作。id 切换到新输入法的唯一标识。subtype 切换到新输入法的新类型。
- public void showInputMethodAndSubtypeEnabler (String topId) 此方法为3.0中新增的方法
- public void showInputMethodPicker () 显示输入法菜单列表
- public boolean showSoftInput (View view, int flags, ResultReceiver resultReceiver),如需要,显式要求当前输入法的软键盘区域向用户显示。当用户与视图交互,用户表示要开始执行输入操作时,可以调用此方法。参数,view 当前焦点视图,可接受软键盘输入。flags 提供额外的操作标志。当前可以是0或SHOW_IMPLICIT 位设置。resultReceiver 如不为空,当IME处理请求告诉你完成时调用。你收到的结果码可以是RESULT_UNCHANGED_SHOWN, RESULT_UNCHANGED_HIDDEN, RESULT_SHOWN, 或 RESULT_HIDDEN 。
- public boolean showSoftInput (View view, int flags),showSoftInput(View, int, ResultReceiver)的无返回值版:如需要,显式要求当前输入法的软键盘区域向用户显示。参数,view 当前焦点视图,可接受软键盘输入。flags 提供额外的操作标志。当前可以是0或SHOW_IMPLICIT 位设置。
- public void showSoftInputFromInputMethod (IBinder token, int flags),显示输入法的软键盘区域,这样用户可以到看到输入法窗口并能与其交互。只能由当前激活输入法调用,因需令牌(token)验证。参数,token 在输入法启动时提供令牌验证,验证后可对其进行操作。flags 提供额外的操作标志。可以是0或 SHOW_IMPLICIT, SHOW_FORCED位设置。
- public void showStatusIcon (IBinder imeToken, String packageName, int iconId) 显示状态栏图标
- public boolean switchToLastInputMethod (IBinder imeToken)
- public void toggleSoftInput (int showFlags, int hideFlags) 切换软键盘
- public void toggleSoftInputFromWindow (IBinder windowToken, int showFlags, int hideFlags),本方法切换输入法的窗口显示。如输入窗口已显示,它隐藏。如无输入窗口则显示。参数,windowToken 由窗口请求View.getWindowToken()返回得到的令牌(token)。showFlags 提供额外的操作标志。当前可以为0或 HIDE_IMPLICIT_ONLY位设置。hideFlags 提供额外的操作标志。可以是0或 HIDE_IMPLICIT_ONLY, HIDE_NOT_ALWAYS位设置。
- public void updateCursor (View view, int left, int top, int right, int bottom),返回窗口的当前光标位置。
- public void updateExtractedText (View view, int token, ExtractedText text) 当内容变化时文本编辑器调用此方法,通知其新提取文本。
- public void updateSelection (View view, int selStart, int selEnd, int candidatesStart, int candidatesEnd),返回当前选择区域。
代码
public class MainActivity extends Activity implements OnClickListener, OnLayoutChangeListener { private LinearLayout root; private TextView tv; private ImageView iv; private EditText et; private InputMethodManager imm; private Rect firstRect; private final int ANIMATE_Y = 500; private final int ANIMATE_X = 200; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); root = (LinearLayout) findViewById(R.id.root); tv = (TextView) findViewById(R.id.tv); iv = (ImageView) findViewById(R.id.iv); et = (EditText) findViewById(R.id.et); imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); Log.i("bqt", "onCreate++++++" + imm.isActive());//获取输入法打开的状态,false tv.setOnClickListener(this); //弹出窗口时自动让控件获取焦点,并弹出输入法。注意要在onCreate中法中设置,不能在onResume中设置。 et.requestFocus(); //开启一个定时器,500毫秒后执行一个定时任务 new Timer().schedule(new TimerTask() { @Override public void run() { Log.i("bqt", "Timer++++++" + imm.isActive());//true //imm.showSoftInput(et,InputMethodManager.SHOW_FORCED);//如此控件有需要,则显式要求软键盘区域向用户显示 //imm.hideSoftInputFromWindow(MainActivity.this.getCurrentFocus().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);//隐藏软键盘 imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);//切换软键盘的显示与隐藏状态 } }, 500); root.addOnLayoutChangeListener(this); root.post(new Runnable() { @Override public void run() { firstRect = new Rect(); iv.getWindowVisibleDisplayFrame(firstRect);//封装可视大小到一个矩形中 } }); } //****************************************************************************************** @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv: imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);//切换软键盘的显示与隐藏 Log.i("bqt", "hide++++++" + imm.isActive());//true,输入法虽然不显示了,但返回的仍然是true break; default: break; } } @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { Rect rect = new Rect(); root.getWindowVisibleDisplayFrame(rect); if (firstRect != null) { //有时输入法弹出时会自动压缩或平移布局,此时这个值就要设置有一定阈值 if (firstRect.height() - rect.height() > 0) softInputShowAnimate(); else softInputHideAnimate(); } } //****************************************************************************************** /** * 键盘弹出时的动画 */ private void softInputShowAnimate() { if (iv.getTranslationX() != 0) return; //如果偏移过就不偏移了 ObjectAnimator animatorX = ObjectAnimator.ofFloat(iv, "translationX", 0, ANIMATE_Y);//水平偏移 ObjectAnimator animatorY = ObjectAnimator.ofFloat(iv, "translationY", -ANIMATE_X);//竖值偏移 AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animatorX, animatorY); animatorSet.setDuration(1000); animatorSet.start(); } /** * 键盘隐藏时的动画 */ private void softInputHideAnimate() { if (iv.getTranslationX() == 0) return; //如果偏移过就不偏移了 ObjectAnimator animatorX = ObjectAnimator.ofFloat(iv, "translationX", 0);//水平偏移 ObjectAnimator animatorY = ObjectAnimator.ofFloat(iv, "translationY", firstRect.top);//竖值偏移,当然也可用ANIMATE_Y AnimatorSet animatorSet = new AnimatorSet(); animatorSet.playTogether(animatorX, animatorY); animatorSet.setDuration(1000); animatorSet.start(); } }
布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:id="@+id/tv" android:layout_width="wrap_content" android:layout_height="300dp" android:background="#ff0" android:text="adjustPan 平移模式,当输入框不会被遮挡时,该模式没有对布局进行调整;然而当输入框将要被遮挡时,窗口就会进行平移。也就是说,该模式始终是保持输入框为可见。该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间,相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。" /> <ImageView android:id="@+id/iv" android:layout_width="wrap_content" android:layout_height="100dp" android:src="@drawable/ic_launcher" /> <EditText android:id="@+id/et" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#f0f" android:text="djustResize 压缩模式, 当软键盘弹出时,该Activity总是调整屏幕的大小以便留出软键盘的空间" /> </LinearLayout>
时间: 2024-08-13 05:50:26