因为项目需求,需要在ScrollView中放EditText, 但是发现如果EditText里面内容过多时无法上下滑动,上网搜索了下,发现解决方式基本如下:
private void initializeEditText()
{
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
editText.getParent().requestDisallowInterceptTouchEvent(true);
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_UP:
editText.getParent().requestDisallowInterceptTouchEvent(false);
break;
}
return false;
}
});
}
但是我发现虽然EditText可以滑动了,但是当EditText中的内同比较少或者滑动到顶部或底部后,ScrollView不会滑动,感觉效果不好,所以想解决这个问题。
正好在View.class中发现了一个方法可以判断View是否可以向上(传正值)或向下(传负值)滑动:
/**
* Check if this view can be scrolled vertically in a certain direction.
*
* @param direction Negative to check scrolling up, positive to check scrolling down.
* @return true if this view can be scrolled in the specified direction, false otherwise.
*/
public boolean canScrollVertically(int direction) {
final int offset = computeVerticalScrollOffset();
final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
if (range == 0) return false;
if (direction < 0) {
return offset > 0;
} else {
return offset < range - 1;
}
}
最终我的代码时这样的:
private void initializeEditText()
{
final float[] touchY = new float[1];
touchY[0] = 0; // 记录触点的Y值
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
editText.getParent().requestDisallowInterceptTouchEvent(true);
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
touchY[0] = motionEvent.getY();
break;
case MotionEvent.ACTION_UP:
editText.getParent().requestDisallowInterceptTouchEvent(false);
break;
default:
// 向上滑
if (motionEvent.getY() < touchY[0])
{
// edit text不可以向上滑, 滑动scroll view
if (!editText.canScrollVertically(1))
{
scrollView.smoothScrollBy(0, (int)(touchY[0] - motionEvent.getY()));
}
}
// 向下滑
else if (motionEvent.getY() > touchY[0])
{
// edit text不可以向下滑, 滑动scroll view
if (!editText.canScrollVertically(-1))
{
scrollView.smoothScrollBy(0, (int)(touchY[0] - motionEvent.getY()));
}
}
touchY[0] = motionEvent.getY();
break;
}
return false;
}
});
}
ps:我发现上面的代码还是有问题的,触摸EditText上下拖动会有抖动,因为滑动ScrollView的同时EditText的位置也变了。修改后的代码如下:
private void initializeEditText()
{
final float[] touchY = new float[1];
touchY[0] = 0; // 记录触点的Y值
editText.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK)
{
case MotionEvent.ACTION_DOWN:
editText.getParent().requestDisallowInterceptTouchEvent(true);
touchY[0] = motionEvent.getY();
break;
case MotionEvent.ACTION_UP:
editText.getParent().requestDisallowInterceptTouchEvent(false);
break;
default:
// 向上滑
if (motionEvent.getY() < touchY[0])
{
// edit text不可以向上滑, 滑动scroll view
if (!editText.canScrollVertically(1))
{
editText.getParent().requestDisallowInterceptTouchEvent(false);
}
}
// 向下滑
else if (motionEvent.getY() > touchY[0])
{
// edit text不可以向下滑, 滑动scroll view
if (!editText.canScrollVertically(-1))
{
editText.getParent().requestDisallowInterceptTouchEvent(false);
}
}
touchY[0] = motionEvent.getY();
break;
}
return false;
}
});
}