Android是一个针对触摸屏专门设计的操作系统,当点击编辑框,系统自动为用户弹出软键盘,以便用户进行输入。
那么,弹出软键盘后必然会造成原有布局高度的减少,那么系统应该如何来处理布局的减少?我们能否在应用程序中进行自定义的控制?这些是本文要讨论的重点。
一、软键盘显示的原理
软件盘的本质是什么?软键盘其实是一个Dialog!
InputMethodService为我们的输入法创建了一个Dialog,并且将该Dialog的Window的某些参数(如Gravity)进行了设置,使之能够在底部或者全屏显示。当我们点击输入框时,系统对活动主窗口进行调整,从而为输入法腾出相应的空间,然后将该Dialog显示在底部,或者全屏显示。
二、活动主窗口调整
android定义了一个属性,名字为windowSoftInputMode, 用它可以让程序可以控制活动主窗口调整的方式。我们可以在AndroidManifet.xml中对Activity进行设置。如:android:windowSoftInputMode="stateUnchanged|adjustPan"
该属性可选的值有两部分,一部分为软键盘的状态控制,另一部分是活动主窗口的调整。前一部分本文不做讨论,请读者自行查阅android文档。
模式一,压缩模式
windowSoftInputMode的值如果设置为adjustResize,那么该Activity主窗口总是被调整大小以便留出软键盘的空间。
我们通过一段代码来测试一下,当我们设置了该属性后,弹出输入法时,系统做了什么。
重写Layout布局:
public class ResizeLayout extends LinearLayout{
private static int count = 0;
public ResizeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
Log.e("onSizeChanged " + count++, "=>onResize called! w="+w + ",h="+h+",oldw="+oldw+",oldh="+oldh);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
Log.e("onLayout " + count++, "=>OnLayout called! l=" + l + ", t=" + t + ",r=" + r + ",b="+b);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
Log.e("onMeasure " + count++, "=>onMeasure called! widthMeasureSpec=" + widthMeasureSpec + ", heightMeasureSpec=" + heightMeasureSpec);
}
我们的布局设置为:
<com.winuxxan.inputMethodTest.ResizeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<LinearLayout
android:id="@+id/bottom_layout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:gravity="bottom">s
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/hello"
android:background="#77777777"
/>
</LinearLayout>
</com.winuxxan.inputMethodTest.ResizeLayout>
AndroidManifest.xml的Activity设置属性:android:windowSoftInputMode = "adjustResize"
运行程序,点击文本框,查看调试信息:
E/onMeasure 6(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742024
E/onMeasure 7(7960): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec = 1073742025
E/onSizeChanged 8(7960): =>onSizeChanged called! w=320,h=201,oldw=320,oldh=377
E/onLayout 9(7960): =>OnLayout called! l=0, t=0,r=320,b=201
从调试结果我们可以看出,当我们点击文本框后,根布局调用了onMeasure,onSizeChanged和onLayout。
实际上,当设置为adjustResize后,软键盘弹出时,要对主窗口布局重新进行measure和layout,而在layout时,发现窗口的大小发生的变化,因此调用了onSizeChanged。
从下图的运行结果我们也可以看出,原本在下方的TextView被顶到了输入法的上方。
模式二,平移模式
windowSoftInputMode的值如果设置为adjustPan,那么该Activity主窗口并不调整屏幕的大小以便留出软键盘的空间。相反,当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分。这个通常是不期望比调整大小,因为用户可能关闭软键盘以便获得与被覆盖内容的交互操作。
上面的例子中,我们将AndroidManifest.xml的属性进行更改:android: windowSoftInputMode = "adjustPan"
重新运行,并点击文本框,查看调试信息:
E/onMeasure 6(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742200
E/onMeasure 7(8378): =>onMeasure called! widthMeasureSpec=1073742144, heightMeasureSpec=1073742201
E/onLayout 8(8378): =>OnLayout called! l=0, t=0,r=320,b=377
我们看到:系统也重新进行了measrue和layout,但是我们发现,layout过程中onSizeChanged并没有调用,这说明输入法弹出前后并没有改变原有布局的大小。
从下图的运行结果我们可以看到,下方的TextView并没有被顶到输入法上方。
事实上,当输入框不会被遮挡时,该模式没有对布局进行调整,然而当输入框将要被遮挡时,窗口就会进行平移。也就是说,该模式始终是保持输入框为可见。如下图,整个窗口,包括标题栏均被上移,以保证文本框可见。
模式三 自动模式
当属性windowSoftInputMode被设置为adjustUspecified时,它不被指定是否该Activity主窗口调整大小以便留出软键盘的空间,或是否窗口上的内容得到屏幕上当前的焦点是可见的。系统将自动选择这些模式中一种主要依赖于是否窗口的内容有任何布局视图能够滚动他们的内容。如果有这样的一个视图,这个窗口将调整大小,这样的假设可以使滚动窗口的内容在一个较小的区域中可见的。这个是主窗口默认的行为设置。
也就是说,系统自动决定是采用平移模式还是压缩模式,决定因素在于内容是否可以滚动。
三、侦听软键盘的显示隐藏
有时候,借助系统本身的机制来实现主窗口的调整并非我们想要的结果,我们可能希望在软键盘显示隐藏的时候,手动的对布局进行修改,以便使软键盘弹出时更加美观。这时就需要对软键盘的显示隐藏进行侦听。
直接对软键盘的显示隐藏侦听的方法本人没有找到,如果哪位找到的方法请务必告诉本人一声。还有本方法针对压缩模式,平移模式不一定有效。
我们可以借助软键盘显示和隐藏时,对主窗口进行了重新布局这个特性来进行侦听。如果我们设置的模式为压缩模式,那么我们可以对布局的onSizeChanged函数进行跟踪,如果为平移模式,那么该函数可能不会被调用。
我们可以重写根布局,因为根布局的高度一般情况下是不发生变化的。
假设跟布局为线性布局,模式为压缩模式,我们写一个例子,当输入法弹出时隐藏某个view,输入法隐藏时显示某个view。
public class ResizeLayout extends LinearLayout{
private OnResizeListener mListener;
public interface OnResizeListener {
void OnResize(int w, int h, int oldw, int oldh);
}
public void setOnResizeListener(OnResizeListener l) {
mListener = l;
}
public ResizeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mListener != null) {
mListener.OnResize(w, h, oldw, oldh);
}
}
}
在我们的Activity中,通过如下方法调用:
public class InputMethodTestActivity extends Activity {
private static final int BIGGER = 1;
private static final int SMALLER = 2;
private static final int MSG_RESIZE = 1;
private static final int HEIGHT_THREADHOLD = 30;
class InputHandler extends Handler {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_RESIZE: {
if (msg.arg1 == BIGGER) {
findViewById(R.id.bottom_layout).setVisibility(View.VISIBLE);
} else {
findViewById(R.id.bottom_layout).setVisibility(View.GONE);
}
}
break;
default:
break;
}
super.handleMessage(msg);
}
}
private InputHandler mHandler = new InputHandler();
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ResizeLayout layout = (ResizeLayout) findViewById(R.id.root_layout);
layout.setOnResizeListener(new ResizeLayout.OnResizeListener() {
public void OnResize(int w, int h, int oldw, int oldh) {
int change = BIGGER;
if (h < oldh) {
change = SMALLER;
}
Message msg = new Message();
msg.what = 1;
msg.arg1 = change;
mHandler.sendMessage(msg);
}
});
}
}
这里特别需要注意的是,不能直接在OnResizeListener中对要改变的View进行更改,因为OnSizeChanged函数实际上是运行在View的layout方法中,如果直接在onSizeChange中改变view的显示属性,那么很可能需要重新调用layout方法才能显示正确。然而我们的方法又是在layout中调用的,因此会出现错误。因此我们在例子中采用了Handler的方法。
分享到:
相关推荐
JavaScript(简称JS)软键盘是一种基于Web的输入解决方案,它允许用户在网页上进行安全的输入操作,尤其适用于处理敏感信息如密码时,避免了原生系统键盘在公共设备上的安全风险。本压缩包文件主要包含一个名为"软...
在这个压缩包中,我们主要关注的是易语言调用软键盘的相关源码,这涉及到易语言的几个关键概念和技术。 首先,"软键盘"是指在计算机程序中通过模拟键盘输入的方式实现文字输入的功能,通常用于移动设备或特定应用中...
《基于MFC的软键盘开发详解》 在计算机软件开发中,软键盘是一种常见的功能,尤其在输入设备受限或者安全需求较高的场景下。MFC(Microsoft Foundation Classes)是微软提供的一种C++类库,用于构建Windows应用程序...
QT官方软键盘是一款基于QT库开发的虚拟键盘应用,它为需要输入的嵌入式设备提供了方便的解决方案。QT是一个跨平台的C++图形用户界面应用程序开发框架,广泛应用于桌面、移动以及嵌入式系统中。这个软键盘程序是QT...
在Android开发中,有时我们需要对软键盘的显示和隐藏状态进行监控,以便调整布局或实现特定功能。这个需求通常出现在创建聊天应用、编辑器或者其他需要根据输入法状态改变界面布局的场景。本篇文章将深入探讨如何在...
标题"\"c# winform完美软键盘实现 软键盘 源码\"\"揭示了这是一个关于用C#编程语言在WinForms环境中开发软键盘的应用程序,而且这个软键盘在功能和用户体验上具有较高的完善度,解决了以往可能遇到的问题。...
在Qt开发过程中,有时我们需要为应用添加软键盘支持,特别是在嵌入式设备如Zynq板上。然而,遇到软键盘背景全黑的问题可能是由于多种原因导致的,这些问题可能涉及到Qt的渲染机制、系统主题或者与硬件交互的方式。...
在本文中,我们将深入探讨如何使用Qt框架来实现一个功能完备的软键盘,支持中文、英文和数字输入。Qt是一个跨平台的应用程序开发框架,广泛应用于桌面、移动和嵌入式设备。它提供了丰富的图形用户界面(GUI)组件,...
网页软键盘是一种基于JavaScript技术实现的虚拟键盘,它在网页上提供了一种用户输入数据的方式,主要用于增强在线安全,特别是当用户需要输入敏感信息如密码时。这种软键盘的目的是防止键盘记录器或其他恶意软件捕获...
在这个场景中,"使用labview2019做的一个软键盘"是一个使用LabVIEW 2019开发的软件模拟键盘,它允许用户通过程序输入文本或数字,尤其适用于自动化测试、设备控制等场合,无需物理键盘即可完成数据输入。 标题中的...
标题中的“漂亮C#软键盘(小键盘)源代码”是指一种使用C#编程语言编写的软件键盘,也称为虚拟键盘或屏幕键盘。这种键盘通常出现在应用程序中,以替代物理键盘,尤其在需要输入敏感信息或者移动设备上没有实体键盘的...
此时,调用软键盘成为了一个实用的解决方案。本篇文章将详细介绍如何在VB.NET中实现这个功能,特别是在一个窗体中点击文本框控件时自动弹出类似Windows 10的软键盘。 首先,我们需要了解软键盘的基本原理。软键盘是...
标题中的“软键盘程序C++源代码”是指一个使用C++编程语言开发的软件,它在Windows操作系统环境下模拟了一个虚拟键盘。这个虚拟键盘允许用户输入中英文字符,具备与系统自带键盘类似的切换功能,但不包含Windows键,...
【VB软键盘含源码】项目是一个基于Visual Basic(VB)开发的软件,它利用了WinIO.dll动态链接库来创建一个系统级别的虚拟键盘。这个软键盘的主要目标是提供一个安全的输入方式,特别是在公共电脑或者网络环境中,...
本案例关注的是如何使用C#构建一个软键盘,类似于QQ软键盘和金山打字通,这两个都是广为人知的输入工具。软键盘在某些场景下非常有用,比如在公共电脑上保护隐私,或者在触摸屏设备上提供更方便的输入方式。 首先,...
在Android开发中,有时会遇到一个常见的问题:当用户在悬浮窗内的EditText输入时,软键盘弹出可能会遮挡住部分视图,导致用户体验下降。本文将深入探讨如何解决这一问题,并实现软键盘与悬浮窗的联动,即软键盘弹出...
"中标麒麟5.0 下的软键盘 安装包" 指的是专门为中标麒麟操作系统版本5.0设计的一款虚拟键盘软件的安装程序。中标麒麟是国产的Linux发行版,广泛应用于政府、企业以及教育等领域,这款软键盘可能是为了满足在无实体...
在C#编程中,有时我们需要实现一些特殊的功能,比如打开计算机的软键盘,这在开发桌面应用时尤其有用,特别是当应用程序需要用户在无物理键盘的触摸设备上输入信息时。本文将详细介绍如何使用C#打开软键盘。 首先,...
本文将深入探讨使用JavaScript实现Web软键盘的技术原理、设计思路以及相关应用。 首先,JavaScript作为客户端脚本语言,是实现Web软键盘的核心工具。它允许我们在网页上动态生成元素,监听用户事件,并对用户交互...
### C#制作软键盘知识点详解 #### 一、概述 在C#的Windows Forms应用程序开发过程中,有时我们需要为用户提供一个虚拟软键盘的功能,这在触摸屏应用或特定场景下的输入控制非常有用。本文将详细介绍如何在C# ...