Android--EditText、TextView 的drawableRight 和drawableLeft 的点击事件

时间:2024-04-05 09:53:08

        实现思路,了解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”属性 
这两种属性的区别,官方的解释是: 

Android--EditText、TextView 的drawableRight 和drawableLeft 的点击事件

方法二:在界面最外层布局包裹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

软键盘隐藏、显示原理:https://www.cnblogs.com/plokmju/p/7978500.html