解决方案一:
为了测试,把父布局设置成可点击可获取交点的。如下:
<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 = new int[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