章节索引 :

滚动条 ScrollView

到这里基本上你已经掌握了 Android 所有的常用控件,不知道有没有这样的疑惑:如果控件太多,在有的小尺寸手机上将屏幕占满了怎么办?是不是有一种通用的解决方法?没错,本节的主角——ScrollView 就是来帮你解决这个问题的,它让你的控件能够在屏幕显示不足的情况下,支持滚动展示。

1. ScrollView 的特性

ScrollView 是一种可以有效解决由于 View 过多显示不全的布局,它可以让控件在横向或者纵向上支持滚动显示。它其实是一个 FrameLayout,内部可以包含一个或多个 View / ViewGroup,当然它的滚动效果也只会作用于子 View / ViewGroup 当中
另外需要注意的是因为它是一个 FrameLayout,所以我们需要注意它的布局排列方式(对于 FrameLayout 的布局方式可以参考第 11 节的内容),大多数场景下我们需要结合其他的布局一起使用,其实最简单的使用方式就是直接在写好的布局外面套一个 ScrollView 就可以支持滚动了
ScrollView 默认是纵向的滚动,如果需要横向滚动可以使用HorizontalScrollView,只是方向不同,用法是完全一样的。

注:对于需要支持滚动的场景而言,ScrollView 是一个非常完美的解决方案,但是我们后面会学到两大滚动列表控件——ListView / GridView,因为这两个控件天生就带有滚动效果,所以通常我们不会将 ScrollView 和这两个控件一起使用。

2. ScrollView 的基本用法

通常无论是控件还是布局我们会先介绍属性,但是 ScrollView 本质是一个 FrameLayout,作用也只是增加一个滚动效果,并没有什么很特别的属性,这里主要介绍一下几个控制滚动的 API:

  • fullScroll():
    将列表滚动到顶部或者底部:ScrollView.FOCUS_DOWN 表示滚动到底部;ScrollView.FOCUS_UP 表示滚动到顶部。
  • scrollTo():
    将列表滚动到指定位置,参数为 x/y,分别表示横纵坐标的坐标值。这里要注意如果是纵向的 ScrollView,那么横坐标(x)是无效的;相反横向的 ScrollView,纵向(y)是无效的。

3. ScrollView 使用示例

ScrollView 的适用场景也很明显,我们人为创造一个 View 过多的场景即可。

3.1 布局文件的编写

首先布局文件主要包括 3 个部分:

  1. Button——用于点击回到顶部;
  2. Button——用于点击跳转底部;
  3. ScrollView——包含过多的子 View,支持滚动。

然后我们将两个用于跳转的 Button 放入一个 LinearLayout 中,和 ScrollView 同层,这样两个 Button 就不会响应 ScrollView 的滑动,然后在 ScrollView 中添加一个 LinearLayout 用来管理需要滑动的 n 个 View,布局文件如下:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ScrollView
        android:id="@+id/scrollView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="30dp">

        <LinearLayout
            android:id="@+id/button_group"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="80dp"
                android:text="ScrollView"
                android:textSize="25dp"
                android:textStyle="bold" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="20dp"
                android:text="Welcome to Imooc Android" />
            <!-- 在Java代码中动态添加若干个Button,超出屏幕范围即可滑动 -->
        </LinearLayout>
    </ScrollView>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <Button
            android:id="@+id/bt_to_top"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="滚动到顶部" />

        <Button
            android:id="@+id/bt_to_bottom"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="30dp"
            android:text="跳转到底部" />
    </LinearLayout>
</FrameLayout>

3.2 Java 文件编写

以上代码主要实现了两个 Button 及一个 ScrollView,可以看到 ScrollView 中只有一个 LinearLayout,而 LinearLayout 中只有两个 Button,所以我们需要在 Java 代码中动态添加 Button,这里也可以让大家熟悉一下如何动态创建并添加 Button。接下来在 Java 代码中主要做两件事:

  • 为两个 Button 设置点击事件,分别实现回到顶部及跳转到底部;
  • 往 ScrollView 中添加 View,并绑定点击事件。

代码如下:

package com.emercy.myapplication;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.Toast;

public class MainActivity extends Activity implements View.OnClickListener {

    public static final int BUTTON_COUNT = 10;

    private ScrollView mScrollView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        findViewById(R.id.bt_to_top).setOnClickListener(this);
        findViewById(R.id.bt_to_bottom).setOnClickListener(this);
        mScrollView = findViewById(R.id.scrollView);

        LinearLayout layout = findViewById(R.id.button_group);

        for (int i = 0; i < BUTTON_COUNT; i++) {
            Button button = new Button(this);
            LinearLayout.LayoutParams params =
                    new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
            params.topMargin = 100;
            layout.addView(button, params);
            button.setOnClickListener(this);
            button.setText(i + "");
        }
    }


    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_to_top:
                mScrollView.fullScroll(ScrollView.FOCUS_UP);
                break;
            case R.id.bt_to_bottom:
                mScrollView.fullScroll(ScrollView.FOCUS_DOWN);
                break;
            default:
                Toast.makeText(this, "当前点击的是第" + ((Button) v).getText() + "个Button", Toast.LENGTH_SHORT).show();
                break;
        }
    }
}

效果如下:

ScrollView示例

我们在代码中通过 for 循环往 ScrollView 中添加了 10 个 Button,动态添加一个 View 主要有以下 4 步:

  1. 通过构造器创建 View。
  2. 设置其属性(宽、高、margin、padding 等)。
  3. 设置响应事件(比如点击、触摸、滚动等)。
  4. 添加到相应的 ViewGroup 中。

我们在创建 Button 的同时通过setTextsetOnClickListener设置了文本及点击事件,然后在点击的时候展示当前 Button 的序号。

4. 小结

本节学习了一个新的 ViewGroup,它主要解决的就是当子 View 过多而导致屏幕显示不下的问题。通过将过多的 View 放在一个 ScrollView 当中,系统会让这些 View 支持列表滑动显示,并提供了简单的 API 帮助我们操作列表。对于需要横向排列的 View 我们直接将 ScrollView 换成 HorizontalScrollView 即可,其他的使用方式完全一样。

整体来说 ScrollView 是一种比较直接的实现列表的方式,优点是使用简单,而且一目了然;缺点是数据和 UI 强耦合在一起,我们需要考虑的东西非常多,在实现复杂列表逻辑的时候会显得很臃肿,这点在下一节以及后面学到 ListView / GridView 之后就会有深切的体会。

环境搭建,开发相关
Android 系统背景及结构概述 Android 开发环境搭建 Genymotion 的安装与使用 Android 工程解析及使用 Android 程序签名打包
常用 UI 布局
Android 的 UI 根基 View与View Android 线性布局 LinearLayout Android相对布局RelativeLayout Android 表格布局 TableLayout Android 网格布局 GridLayout Android 帧布局 FrameLayout Android绝对布局AbsoluteLayout
基础控件
Android 文本框 TextView Android 文本输入框 EditText 按钮 Button/ImageButton 选择框 RadioButton/Check 开关控件ToggleButton/Switch Android 图片控件 ImageView Android 进度条 ProgressBar Android 拖动条 SeekBar Android 评分条 RatingBar Android 滚动条 ScrollView 轮播滚动视图 ViewFlipper
Adapter 相关控件
Android 适配器 Adapter Android 列表控件 ListView Android 网格视图 GridView Android 下拉选择框 Spinner 自动补全文本框 AutoCompleteText 折叠列表 ExpandableListView
提示类控件
吐司提示:Toast 的使用方法 状态栏通知:Notification 对话框:AlertDialog 悬浮窗:PopupWindow
菜单类控件
菜单:Menu
其他控件
视频页面:ViewPager 侧滑菜单:DrawerLayout
事件处理机制
基于监听的事件处理机制 Handler 消息传递机制 触摸事件分发处理 AsyncTask:异步任务 Android 手势处理
Android 四大组件
活动:Activity 服务:Service 广播接收器:Broadcast Receiver 内容提供者 - Content Provider
数据存储
文件存储 SharedPreferences 存储 数据库:SQLite 的使用
网络编程
HTTP 使用详解 xml 数据解析 JSON 数据解析 网页视图:WebView Socket 网络接口
绘图与动画
图片资源:Drawable 位图:Bitmap
多媒体开发
媒体播放器:MediaPlayer 相机:Camera 音频录制:MediaRecorder
并发编程
多线程