实现思路,了解android事件分发机制的小伙伴们都知道,view的事件分发首先会调用dispatchTouchEvent方法,在这个方法中会调用onTouch事件,根据onTouch的返回值(true or false)决定是否继续往下传递,意味着onClick事件的执行是在onTouch之后,并且是否执行是由onTouch返回值决定的。那么对我们来说, 只要在onTouch事件中对点击图片还是点击TextView做出区分,这个问题就迎刃而解了。在 ontouch中事件监听中,我们首先获取当我们手指点击屏幕时候的X轴坐标,然后获取布局中TextView这个控件的宽度和drawableRight(drawableLeft)的宽度,当x轴坐标大于(drawableRight)或者小于(drawableLeft)textview减去控件的宽度的时候就触发点击事件,否则的话就不触发,这样就能实现对drawableRight和drawableLeft的点击触发事件,下面的贴出简单的代码。
public class MainActivity extends Activity {
private EditText et;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
et = (EditText) this.findViewById(R.id.et);
et.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
// et.getCompoundDrawables()得到一个长度为4的数组,分别表示左右上下四张图片
Drawable drawable = et.getCompoundDrawables()[2];
//如果右边没有图片,不再处理
if (drawable == null)
return false;
//如果不是按下事件,不再处理
if (event.getAction() != MotionEvent.ACTION_UP)
return false;
if (event.getX() > et.getWidth()
- et.getPaddingRight()
- drawable.getIntrinsicWidth()){
//隐藏软键盘
HideKeyboard();
//do something
}
return false;
}
});
}
private void HideKeyboard() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
InputMethodManager manager = ((InputMethodManager) getSystemService(INPUT_METHOD_SERVICE));
manager.hideSoftInputFromWindow(
readMeterActivity.this.getCurrentFocus().getWindowToken(),
InputMethodManager.HIDE_NOT_ALWAYS
);
}
}, 10);
}
}
getX是获取以当前控件左上角为坐标原点计算的X轴坐标直.获得的是一个相对的坐标
getRawX 获取的是以屏幕左上角为坐标原点计算的X轴坐标直.获得的是一个真实的坐标
计算公式就是:整个控件宽度-图片宽度 如果x大于这个值就代表进入了drawableRight的区域了 同理,drawableLeft也可以用这种方式计算。并且由于onTouch返回了一个true,不会对TextView的onClick事件进行干扰。
键盘挡住输入框解决办法
方法一:非透明状态栏下使用adjustResize和adjustPan,或是透明状态栏下使用fitsSystemWindows=true属性
主要实现方法:
在AndroidManifest.xml对应的Activity里添加
android:windowSoftInputMode=”adjustPan”或是android:windowSoftInputMode=”adjustResize”属性
这两种属性的区别,官方的解释是:
方法二:在界面最外层布局包裹ScrollView
方法三:使用scrollTo方法,当键盘弹起时,让界面整体上移;键盘收起,让界面整体下移
方法四:适配键盘高度变化情况,当键盘弹起时,让界面整体上移;键盘收起,让界面整体下移
方法五:监听Activity顶层View,判断软键盘是否弹起,对界面重新绘制
下面对上面几种方法进行对比:
方法一:优点:使用简单,只需在Activity的AndroidMainfest.xml中设置windowSoftInput属性即可。
注意点:adjustResize属性必须要界面大小可以自身改变;
缺点:当输入框比较多时,当前输入框下方的输入框会初键盘挡住,须收起键盘再进入输入;使用adjustPan,输入框较多时,因它是把界面当成一个整体,只会显示一屏的高度,会把ActionBar顶上去。
方法二:优点:使用简单,只需在Activity的最外层布局包裹一个ScrollView即可。
注意点:不可使用adjustPan属性,否则ScrollView失效;
缺点:对于全屏时,在键盘显示时,无法上下滑动界面达到输入的目的;
方法三:优点:可以解决全屏时,键盘挡入按钮问题。
缺点:只要有此需求的Activity均需要获取到最外层控件和最后一个控件,监测键盘是否弹出,再调用控件的scrollTo方法对界面整体上移或是下移。代码冗余。对于键盘高度变化时,适配不好。
方法四:优点:可以解决全屏时,键盘挡入按钮问题。
缺点:只要有此需求的Activity均需要获取到最外层控件和最后一个控件,布局多出一层。
方法五:优点:可以解决全屏时,键盘挡入输入框问题。只需要写一个全局类,其他有需求的界面直接在onCreate方法里调用此类的全局方法,即可。
缺点:多用了一个类。
综上所述:
1) 当输入框比较少时,界面只有一个输入框时,可以通过方法一设置adjustPan;
2) 如果对于非全屏/非沉浸式状态栏需求,只需要使用方法二ScrollView+adjustResize;
3) 如果对于使用沉浸式状态栏,使用fitSystemWindow=true属性,按道理android系统已经做好适配,键盘不会挡住输入框;
4) 如果全屏/沉浸式状态栏界面,类似于登录界面,有需要把登录键钮或是评论按钮也顶起,如果键盘没有变化需求,可以使用方法三,若需要适配键盘高度变化,则需要使用方法四;
5) 如果界面使用全屏或沉浸式状态栏,没有使用fitSystemWindow=true属性,一般如需要用到抽屈而且状态栏颜色也需要跟着变化,则选择方法五更恰当。
具体原理:https://blog.csdn.net/smileiam/article/details/69055963