A view group that allows the view hierarchy placed within it to be scrolled. Scroll view may have only one direct child placed within it. To add multiple views within the scroll view, make the direct child you add a view group, for example {@link LinearLayout}, and place additional views within that LinearLayout.
以上是Google api对于ScrollView的简介,ScrollView是一个允许内部子布局滑动的视图控件,而且只允许有一个子控件,想要有其他的视图效果,只需要添加到ScrollView的唯一的子控件里面即可。
ScrollView的属性及方法
ScrollView作为一个可以滑动的空间,在xml里面大部分的属性设置都是围绕着滚动条ScrollBar设置的,其他的属性最重要的就是下面要介绍的这一条:
* android:fillViewport:在视图没有铺满屏幕的情况下,是否用颜色填充满其他位置
ScrollView在xml的属性设置用的最多的就是fillViewport,当ScrollView没有被子布局中的内容铺满时,就会被ScrollView的默认背景色填满。这个属性值默认是false,需要自己去设置为true。ScrollView的大部分方法都是与ListView相同的,具体的可以去ListView篇看看。
ScrollView的常见问题
1、与ListView、GridView和RecyclerView的嵌套使用的滑动冲突问题
我们平常在做项目的时候,经常会遇到那种非常复杂的布局,这种情况下通常会同时用到ScrollView和RecyclerView,而两者嵌套使用的时候经常会遇到各种奇怪的问题,经常会滑动卡顿,设置直接不能滑动。这种时候就会发现原生的ScrollView有太多的限制,而且ScrollView的滑动监听事件,是需要Android 23之后才有的,这就需要继承ScrollView,来重写自己需要的方法。
public class CustomScrollView extends ScrollView {
private ScrollListener scrollListener;
public CustomScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public CustomScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomScrollView(Context context) {
super(context);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int scrollSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);
super.onMeasure(widthMeasureSpec, scrollSpec);
}
@Override
protected void onScrollChanged(int l, int t, int oldl, int oldt) {
super.onScrollChanged(l, t, oldl, oldt);
if (scrollListener != null) {
scrollListener.scrollOrientation(l, t, oldl, oldt);
}
}
public void setScrollListener(ScrollListener scrollListener) {
this.scrollListener = scrollListener;
}
/**
* 滑动距离回调
*/
public interface ScrollListener {
void scrollOrientation(int l, int t, int oldl, int oldt);
}
}
2、ScrollView的scrollTo方法不生效
有些特殊的要求需要页面显示完后,将页面内容显示在特定的位置上,这时候用scrollTo方法,滑动到指定的位置上,但是我们在用的时候发现有时生效,有时不生效,我们来看一下源码:
@Override
public void scrollTo(int x, int y) {
// we rely on the fact the View.scrollBy calls scrollTo.
if (getChildCount() > 0) {
View child = getChildAt(0);
x = clamp(x, getWidth() - mPaddingRight - mPaddingLeft, child.getWidth());
y = clamp(y, getHeight() - mPaddingBottom - mPaddingTop, child.getHeight());
if (x != mScrollX || y != mScrollY) {
super.scrollTo(x, y);
}
}
}
可以看到,在scrollTo方法里面有一个判断,所以就有一下两种情况会造成scrollTo方法无法生效
- 在xml布局里面没有为ScrollView添加子布局,而是在Java代码通过addView方法添加的子布局,而你的scrollTo方法在addView方法调用之前就调用了,导致判断没有通过,不能滑动到指定的位置。
- 由于ScrollView里面的内容过于复杂,导致页面还没有完全加载完成,就调用了scrollTo方法,这也会使scrollTo方法失效。
对于第一种情况,只需要换一下方法的调用顺序即可,对于第二种方法,一下两种思路解决:
// post方法就不做详细的介绍了,里面用的是handler机制,可以保证在ScrollView加载完成后才调用Runnable里面的方法
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(100, 100);
}
});
// 这个方法使用的是观察者与被观察者模式,也可以保证在ScrollView加载完成后才调用onGlobalLayout里面的方法
scrollView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
scrollView.scrollTo(100, 100);
}
});