问题说明:本人刚接触安卓开发不是很久,在练习的过程中遇到了输入法的隐藏和弹出的问题,想让输入法软键盘在合适的时候进行显示和隐藏。经过查询各种资料和亲身测试,总结了这个小的技巧,在这里和大家分享一下。有不正确的请大家指正。

1.创建安卓项目之后,编写需要用到EditText的布局文件,如下:

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:id="@+id/all_layout"
    tools:context="${relativePackage}.${activityClass}" >

    <TextView
        android:id="@+id/head"
        android:layout_width="match_parent"
        android:layout_height="40sp"
        android:text="@string/hello_world"
        android:background="#3399FF"
        android:textSize="20sp"
        android:textColor="#FFFFFF"
        android:gravity="center" />
    <TextView 
        android:id="@+id/name"
        android:layout_height="50sp"
        android:layout_width="80sp"
        android:layout_below="@id/head"
        android:layout_marginTop="2sp"
        android:text="@string/name"
        android:textSize="20sp"
        android:gravity="center"/>
    <EditText 
        android:id="@+id/enterName"
        android:layout_height="50sp"
        android:layout_width="match_parent"
        android:layout_marginTop="2sp"
        android:hint="@string/enterName"
        android:background="@drawable/bg_edittext"
        android:gravity="center"
        android:layout_toRightOf="@id/name"
        android:layout_toEndOf="@id/name"
        android:layout_below="@id/head"
        android:focusableInTouchMode="true"
        android:focusable="true"/>
    <TextView 
        android:id="@+id/age"
        android:layout_height="50sp"
        android:layout_width="80sp"
        android:layout_below="@id/name"
        android:layout_marginTop="2sp"
        android:text="@string/age"
        android:textSize="20sp"
        android:gravity="center"/>
    <EditText 
        android:id="@+id/enterAge"
        android:layout_height="50sp"
        android:layout_width="match_parent"
        android:layout_marginTop="2sp"
        android:hint="@string/enterAge"
        android:background="@drawable/bg_edittext"
        android:gravity="center"
        android:layout_toRightOf="@id/age"
        android:layout_toEndOf="@id/age"
        android:layout_below="@id/enterName"/>
    <TextView 
        android:id="@+id/height"
        android:layout_height="50sp"
        android:layout_width="80sp"
        android:layout_below="@id/age"
        android:layout_marginTop="2sp"
        android:text="@string/height"
        android:textSize="20sp"
        android:gravity="center"/>
    <EditText 
        android:id="@+id/enterHei"
        android:layout_height="50sp"
        android:layout_width="match_parent"
        android:layout_marginTop="2sp"
        android:hint="@string/enterHeight"
        android:background="@drawable/bg_edittext"
        android:gravity="center"
        android:layout_toRightOf="@id/name"
        android:layout_toEndOf="@id/name"
        android:layout_below="@id/enterAge"/>
    <TextView 
        android:id="@+id/Id_id"
        android:layout_height="40sp"
        android:layout_width="80sp"
        android:layout_below="@id/add"
        android:layout_marginTop="2sp"
        android:text="@string/Id"
        android:textSize="20sp"
        android:gravity="center"/>
    <EditText 
        android:id="@+id/enterId"
        android:layout_height="40sp"
        android:layout_width="match_parent"
        android:layout_marginTop="2sp"
        android:hint="@string/enterId"
        android:background="@drawable/bg_edittext"
        android:gravity="center"
        android:layout_toRightOf="@id/Id_id"
        android:layout_toEndOf="@id/Id_id"
        android:layout_below="@id/showAll"/>

</RelativeLayout>

以上需要注意的是,我这里用到的是让布局能够获得焦点,从而达到和输入框抢焦点,隐藏输入法的目的。就是在刚刚进入这个页面时不让输入法直接弹出,需要手动点击输入框才会弹出输入法

在相对布局的设置中加入了两句:

android:focusable="true"
android:focusableInTouchMode="true"

以前本人在测试时增加过clickable属性,后来发现会点击两次才会隐藏输入法,所以为了提升体验,就删去了。有兴趣的可以试试看。

让布局可以获得焦点

2.接下来就是在java文件中对界面进行监听

MainActivity.java

package com.example.androidexperimentfive;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.view.Window;
import android.widget.EditText;

public class MainActivity extends Activity{

	private EditText name_et;
	private EditText age_et;
	private EditText height_et;
	private EditText id_et;
	private int name_etleft, name_ettop, name_et_bottom, name_et_right;
	private int age_etleft, age_ettop, age_et_bottom, age_et_right;
	private int height_etleft, height_ettop, height_et_bottom, height_et_right;
	private int id_etleft, id_ettop, id_et_bottom, id_et_right;
	//记录是否计算过本页面各个输入框的位置
	private static boolean registeOpenCount = false;

	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);//去除主页面的Title
		setContentView(R.layout.activity_main);
		initView();
	}

	public void initView() {
		name_et = (EditText) findViewById(R.id.enterName);
		age_et = (EditText) findViewById(R.id.enterAge);
		height_et = (EditText) findViewById(R.id.enterHei);
		id_et = (EditText) findViewById(R.id.enterId);
	}

	// 隐藏输入法算法
	// 重写dispachTouchEvent方法进行判定什么时候进行隐藏
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if (!registeOpenCount) {
			calculateEtXY();
			registeOpenCount = true;
		}
		if (ev.getAction() == MotionEvent.ACTION_DOWN){
			return super.dispatchTouchEvent(ev);
		}
		else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
			return super.dispatchTouchEvent(ev);
		}
		else if (ev.getAction() == MotionEvent.ACTION_UP) {
			boolean b = false;
			View v = getCurrentFocus();
			float x = ev.getX();
			float y = ev.getY();
			b = isAlsoET(x, y);
			if (!b) {//如果点击的位置不是输入框
				if (v instanceof EditText)
					v.clearFocus();//如果当前获得焦点的是输入框EditText,就清除焦点
				InputMethodManager imm = (InputMethodManager) 
						getSystemService(Context.INPUT_METHOD_SERVICE);
				if (imm != null) {
					imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
				}
			}
			return super.dispatchTouchEvent(ev);
		}
		if (getWindow().superDispatchTouchEvent(ev)) {
			return true;
		}
		return onTouchEvent(ev);
	}

	// 判断点击的区域是否是文本框
	public boolean isAlsoET(float x, float y) {
		if ((x > name_etleft) && (y > name_ettop) && (x < name_et_right) && (y < name_et_bottom))
			return true;
		if ((x > age_etleft) && (y > age_ettop) && (x < age_et_right) && (y < age_et_bottom))
			return true;
		if ((x > height_etleft) && (y > height_ettop) && (x < height_et_right) && (y < height_et_bottom))
			return true;
		if ((x > id_etleft) && (y > id_ettop) && (x < id_et_right) && (y < id_et_bottom))
			return true;
		return false;
	}

	// 事先计算好所有EditText的x,y坐标,用到的时候不用重复计算
	public void calculateEtXY() {
		int[] name_etleftTop = { 0, 0 };
		name_et.getLocationInWindow(name_etleftTop);
		name_etleft = name_etleftTop[0];
		name_ettop = name_etleftTop[1];
		name_et_bottom = name_ettop + name_et.getHeight();
		name_et_right = name_etleft + name_et.getWidth();

		int[] age_etleftTop = { 0, 0 };
		age_et.getLocationInWindow(age_etleftTop);
		age_etleft = age_etleftTop[0];
		age_ettop = age_etleftTop[1];
		age_et_bottom = age_ettop + age_et.getHeight();
		age_et_right = age_etleft + age_et.getWidth();

		int[] height_etleftTop = { 0, 0 };
		height_et.getLocationInWindow(height_etleftTop);
		height_etleft = height_etleftTop[0];
		height_ettop = height_etleftTop[1];
		height_et_bottom = height_ettop + height_et.getHeight();
		height_et_right = height_etleft + height_et.getWidth();

		int[] id_etleftTop = { 0, 0 };
		id_et.getLocationInWindow(id_etleftTop);
		id_etleft = id_etleftTop[0];
		id_ettop = id_etleftTop[1];
		id_et_bottom = id_ettop + id_et.getHeight();
		id_et_right = id_etleft + id_et.getWidth();
	}

}

上面的代码中隐藏输入法的关键代码是

InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(v.getWindowToken(), 0);

是隐藏输入法的能够实现语句。之前查过一些资料,也有很多说法,试了多次发现这个是可以使用的。我加入了一些改进的比较实用的小东西。

其中isAlsoET(float x, float y)是判断点击位置是否是EditText,calculateEtXY()是获取当前页面中所有EditText的位置,这段代码会在当界面有多个EditText时,从一个点击到另外一个不会频繁的隐藏和弹出软键盘。

本人新人上手,欢迎交流,有不对之处还请指出,谢谢。