问题描述: 一个 ScrollView 中包含了好几个 childView,有一个 childview 很大,一个屏幕显示不完,每个 childview 都能获取 focus。当那个很大的 chilvView 获取焦点时,由于一屏显示不完,它就会自动滑动到最后(就是该 childView 的底部)。
问题原因以及解决方案分析:
由于该 childView 超过屏幕大小,并且有获取焦点的能力,所以造成了该问题。由于不能改变其大小,只能阻止其获取焦点。基本思路有,取消它获取焦点的能力,让 ScrovView 截获它的焦点等。以下是具体方法:
将可能自动滑动的 childview 的 focus 禁掉,防止它自动滑动mContentTextBox.setFocusable(false);
恢复默认状态,允许 childview 的 focus,使它可以自动滑动mContentTextBox.setFocusableInTouchMode(true); mContentTextBox.setFocusable(true);
这里要注意,仅仅 setFocusable 为 true 是不够的,需要设置 setFocusableInTouchMode。
让 ScrollView 优先获取 focus,这样 childview 获取不到 focus,就不会滑动
private void disableAutoScrollToBottom() {
mScrollView.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
mScrollView.setFocusable(true);
mScrollView.setFocusableInTouchMode(true);
mScrollView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
v.requestFocusFromTouch();
return false;
}
});
}
恢复默认状态,禁掉 scrollview 的 focus,这样就允许 childview 自动滑动
private void enableChildAutoScrollToBottom() {
mScrollView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
mScrollView.setFocusable(false);
mScrollView.setFocusableInTouchMode(false);
mScrollView.setOnTouchListener(null);
}
@Override
protected boolean onRequestFocusInDescendants(int direction, Rect previouslyFocusedRect) {
return true;
}
@Override
protected int computeScrollDeltaToGetChildRectOnScreen(Rect rect) {
return 0;
}