触摸屏幕取消键盘

当点击文本框和发送按钮的时候不需要取消键盘,点击屏幕其他按钮或者其他控件的时候消失键盘

解决方案一:

为了测试,把父布局设置成可点击可获取交点的。如下:

<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:clickable="true"
    tools:context=".MainActivity" >

    <LinearLayout
        android:id="@+id/ll"
        android:background="#11ff0000"
        android:layout_width="match_parent"
        android:layout_height="45dp"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal" >

        <EditText
            android:id="@+id/et"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="8" />

        <Button
            android:id="@+id/bt"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="2"
            android:text="发送" />
    </LinearLayout>

</RelativeLayout>

主要逻辑代码如下:

@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		ll = (LinearLayout) findViewById(R.id.ll);
		EditText et = (EditText) findViewById(R.id.et);
		Button bt = (Button) findViewById(R.id.bt);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		if (ev.getAction() == MotionEvent.ACTION_DOWN) {
			// View v = getCurrentFocus();
			View v = ll;
			if (isShouldHideKeyboard(v, ev)) {
				hideKeyboard(v.getWindowToken());
			}
		}
		return super.dispatchTouchEvent(ev);
	}

	/**
	 * 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时则不能隐藏
	 */
	private boolean isShouldHideKeyboard(View v, MotionEvent event) {
		if (v != null) {// 如果点击的是edittext
			int[] l = { 0, 0 };
			v.getLocationInWindow(l);// 获取v在窗口中的位置
			int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left
					+ v.getWidth();
			// 判断点击的是不是在v的区域里面
			System.out.println("位置:(" + left + "," + top + ")(" + right + ","
					+ bottom + ")");
			System.out.println("event-x:" + event.getX());
			System.out.println("event-y:" + event.getY());
			if (event.getX() > left && event.getX() < right
					&& event.getY() > top && event.getY() < bottom) {
				// 点击的位置在v区域里面
				return false;
			} else {
				return true;
			}
		}
		// 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
		return false;
	}

	/**
	 * 获取InputMethodManager,隐藏软键盘
	 * 
	 * @param token
	 */
	private void hideKeyboard(IBinder token) {
		if (token != null) {
			InputMethodManager im = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
			im.hideSoftInputFromWindow(token,
					InputMethodManager.HIDE_NOT_ALWAYS);
		}
	}

	/**
	 * 点击空白位置 隐藏软键盘
	 */
	public boolean onTouchEvent(MotionEvent event) {
		if (null != this.getCurrentFocus()) {
			InputMethodManager mInputMethodManager = (InputMethodManager) getSystemService(INPUT_METHOD_SERVICE);
			return mInputMethodManager.hideSoftInputFromWindow(this
					.getCurrentFocus().getWindowToken(), 0);
		}
		return super.onTouchEvent(event);
	}

经过测试发现,当弹出键盘的时候点击输入框仍然会取消键盘然后再次弹出键盘。这个问题是因为当弹起键盘的时候键盘会挤压屏幕,导致点击的坐标被判断在指定的布局之外所以就取消键盘,但同时输入框获取了焦点所以又再次弹出键盘,解决这个问题只需要让屏幕不被键盘挤压即可,代码如下:

<activity
            android:name="com.example.touchdissmis.MainActivity"
            android:windowSoftInputMode="adjustResize"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

解决方案二:

获取相对于屏幕的点击位置和控件位置,即将getX(),getY()改成getRawX(),getRawY()。

getX()是表示Widget相对于自身右上角的x坐标二getRawX()是表示相对于屏幕左上角的x坐标值(注意:这个屏幕右上角是手机屏幕右上角,不管Activity是否有titleBar或者是全屏),getY(),getRawY()一样的道理。

代码如下:

不限制屏幕滚动:

      
<activity
            android:name="com.example.touchdissmis.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

修改获取坐标的方法:

本例中使用v.getLocationInWindow或者是v.getLocationOnScreen都行,是因为屏幕中就一个界面。所以两种方法获取的位置一样,最后有观月这两个方法的区别

private boolean isShouldHideKeyboard(View v, MotionEvent event) {
		if (v != null) {//如果点击的是edittext
			int[] l = { 0, 0 };
			v.getLocationOnScreen(l);//获取v在窗口中的位置
			int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left + v.getWidth();
			//判断点击的是不是在v的区域里面
			System.out.println("位置:("+left+","+top+")("+right+","+bottom+")");
			System.out.println("event-x:"+event.getRawX());
			System.out.println("event-y:"+event.getRawY());
			if (event.getRawX() > left && event.getRawX() < right&& event.getRawY() > top && event.getRawY() < bottom) {
				// 点击的位置在v区域里面
				return false;
			} else {
				return true;
			}
		}
		// 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditText上,和用户用轨迹球选择其他的焦点
		return false;
	}

getLocationInWindow与getLocationOnScreen的区别

getLocationInWindow

一个控件在其父窗口中的坐标位置

getLocationOnScreen

一个控件在其整个屏幕上的坐标位置

getLocationInWindow是以B为原点的C的坐标,而getLocationOnScreen以A为原点。

int[]location=newint[2];

view.getLocationInWindow(location);//获取在当前窗口内的绝对坐标

view.getLocationOnScreen(location);//获取在整个屏幕内的绝对坐标

location[0]--->x坐标,location[1]--->y坐标

getLocationOnScreen

计算该视图在全局坐标系中的x,y值,(注意这个值是要从屏幕顶端算起,也就是索包括了通知栏的高度)//获取在当前屏幕内的绝对坐标

getLocationInWindow,计算该视图在它所在的widnow的坐标x,y值,//获取在整个窗口内的绝对坐标

getLeft,getTop,getBottom,getRight,这一组是获取相对在它父亲里的坐标

转载请注明出处:http://renyuan-1991.iteye.com/blog/2248876

希望爱好编程的小伙伴能加这个群,互相帮助,共同学习。群号:141877583

相关推荐