android-ScrollView中嵌套EditText使用问题

直接上布局文件




    

        ....

        
			.....
        

        

            
            

            

            ...
        

    


问题1:当文字很多时,EditText会被拉伸的很长不便于用户操作.

        问题2:最严重的是当文字过多时,整个EditText会全白或者文字显示错乱.

问题2只要设置EditText最大高度,让其可滚动就可以解决了(具体为啥,我也不是很清楚,摸索出来的规律),同时问题1也就解决了,不会太长.

修改EditText,让它可滚动,并设置其最大高度为150dp,如下所示:

此时EditText长度的确不会随着文字增多而变得特别长,但由于android平台限制,一个页面只能有一个滚动元素,在ScrollView中嵌套EditText后,EditText不能滚动,这是一个比较蛋疼的问题.

ViewParent接口有这样一个方法

/**
     * Called when a child does not want this parent and its ancestors to
     * intercept touch events with
     * {@link ViewGroup#onInterceptTouchEvent(MotionEvent)}.
     *
     * 

This parent should pass this call onto its parents. This parent must obey * this request for the duration of the touch (that is, only clear the flag * after this parent has received an up or a cancel.

* * @param disallowIntercept True if the child does not want the parent to * intercept touch events. */ public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
如果一个Child View不希望其Parent View拦截TouchEvent的话,可以执行该方法。方法说明中强调该方法需要遵循TouchEvent的生命周期,即在Down事件时申请该标志,在up/cancle事件时清除该标志。具体使用如下

et_content.setOnTouchListener(new View.OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					v.getParent().requestDisallowInterceptTouchEvent(true);
				} else if (event.getAction() == MotionEvent.ACTION_UP) {
					v.getParent().requestDisallowInterceptTouchEvent(false);
				} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
					v.getParent().requestDisallowInterceptTouchEvent(false);
				}
				return false;
			}
		});

添加如上代码,EditText立马可以滚动了。貌似大功告成了。

可是,稍一操作,EditText中输入过多文字,然后将其滑动到最后一行位置,此时点击最后一行文字弹出输入法,然后,尼玛发现根本看不到我的输入框了,被EditText下面的布局顶到上面去了。

可以理解为,在输入法弹出后,整个ScrollView的size发生了改变,回调其onSizeChanged()方法。此时整个ScrollView向上平移了输入法框高度。然后,我就各种计算,想重写ScrollView的onSizeChanged()方法,让ScrollView恰好onSizeChanged()后再向下平移输入法框高度,以抵消其自动行为。貌似完美了,弹出输入法,EditText依旧在原来位置(两次滚动抵消了),可见。

可是,紧接着又发现,EditText在最后添加文字后,又出现上面的情形了,EditText又被顶到上面看不见了。不明所以啊。貌似只要EditText执行requestLayou()就会出现类似问题。onSizeChanged()中的修改治标不治本啊。

看了半天TextView源码,看得头大也没搞明白缘由。

无意中看到Manifest文件中Activity有这么一个属性android:windowSoftInputMode

各值的含义:(COPY来的)

【A】stateUnspecified:软键盘的状态并没有指定,系统将选择一个合适的状态或依赖于主题的设置

【B】stateUnchanged:当这个activity出现时,软键盘将一直保持在上一个activity里的状态,无论是隐藏还是显示

【C】stateHidden:用户选择activity时,软键盘总是被隐藏

【D】stateAlwaysHidden:当该Activity主窗口获取焦点时,软键盘也总是被隐藏的

【E】stateVisible:软键盘通常是可见的

【F】stateAlwaysVisible:用户选择activity时,软键盘总是显示的状态

【G】adjustUnspecified:默认设置,通常由系统自行决定是隐藏还是显示

【H】adjustResize:该Activity总是调整屏幕的大小以便留出软键盘的空间

【I】adjustPan:当前窗口的内容将自动移动以便当前焦点从不被键盘覆盖和用户能总是看到输入内容的部分

adjustPan没解释清楚,看看注释吧

/** Adjustment option for {@link #softInputMode}: set to have a window
         * pan when an input method is
         * shown, so it doesn't need to deal with resizing but just panned
         * by the framework to ensure the current input focus is visible.  This
         * can not be combined with {@link #SOFT_INPUT_ADJUST_RESIZE}; if
         * neither of these are set, then the system will try to pick one or
         * the other depending on the contents of the window.
         */
        public static final int SOFT_INPUT_ADJUST_PAN = 0x20;

SOFT_INPUT_ADJUST_PAN:设置该值后,window就不需要处理resizeing(即不会触发onSizeChanged回调了)。输入法窗体由framewokr控制可见和悬浮。

果断设置该属性试一试,

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);

果然,两个问题都解决了,因为window大小不会变化,前面的两个问题的诱因就不存在了(弹出输入法和输入文字时,EditText被顶到上面看不见问题)。


总结,解决ScrollView和EditText嵌套问题的方案如下:

一.设置EditText的scroll属性

android:maxHeight="150dp"
                android:scrollbars="vertical"
                android:scrollbarStyle="insideOverlay"

二.执行requestDisallowInterceptTouchEvent()使能触摸滚动

		et_content.setOnTouchListener(new View.OnTouchListener() {
			
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if (event.getAction() == MotionEvent.ACTION_DOWN) {
					v.getParent().requestDisallowInterceptTouchEvent(true);
				} else if (event.getAction() == MotionEvent.ACTION_UP) {
					v.getParent().requestDisallowInterceptTouchEvent(false);
				} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
					v.getParent().requestDisallowInterceptTouchEvent(false);
				}
				return false;
			}
		});

三.设置Activity Window的softInputMode属性---确保输入法弹出不会触发window大小改变

getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);


你可能感兴趣的:(Android)