本篇随笔将讲解一下Android当中比较常用的两个布局容器--ScrollView和HorizontalScrollView,从字面意义上来看也是非常的简单的,ScrollView就是一个可以滚动的View,这个滚动的方向是垂直方向的,而HorizontalScrollView则是一个水平方向的可以滚动的View。本篇随笔可能描述性的知识比较少,最主要还是通过代码来看看如何使用这两个View。

一、ScrollView的简单介绍

首先来看看ScrollView和HorizontalScrollView这两个View的定义。ScrollView和HorizontalScrollView都是一个布局容器,里面可以放入child View控件,我们通过其继承关系看到,ScrollView和HorizontalScrollView这两个类是ViewGroup的一个间接子类。

java.lang.Object
       android.view.View
            android.view.ViewGroup
                 android.widget.FrameLayout
                      android.widget.ScrollView
java.lang.Object
       android.view.View
            android.view.ViewGroup
                 android.widget.FrameLayout
                      android.widget.HorizontalScrollView

因为ScrollView和HorizontalScrollView只是两种滚动方向不同的View而已,其他方面都基本相同,所以下面只单单以ScrollView来讲解。

通过使用ScrollView,我们可以滚动其里面的子View控件,这样就允许我们控件的高度可以大于我们实际屏幕的尺寸高度。ScrollView是一个FrameLayout,至于什么是FrameLayout,简单的来说,FrameLayout通常被用来设计成在屏幕上占用一块地方并且里面只有一个Item,我们常用到的例如DatePicker、TimePicker这些控件都是属于FrameLayout布局的。因此在ScrollView当中,也通常只包含一个子元素,并且这个子元素也是一个布局文件,这样我们才能在这个布局文件里面添加我们想要的任何子控件,从而实现滚动的效果。

对于ScrollView来说,因为其是垂直方向上的滚动布局,因此通常我们给其添加一个LinearLayout的子元素,并且设置orientation为vertical(垂直方向的)。下面我们通过一个小例子来看看如何使用我们的ScrollView来展示多张图片,并且实现图片的垂直方向的滚动。

首先我们定义一个ScrollView,因为ScrollView也是一个ViewGroup,所以我们可以直接使用ScrollView作为我们的xml文件的根元素:

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="false">    <LinearLayout        android:id="@+id/layout"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:orientation="vertical"/></ScrollView>

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

我们看到,在ScrollView元素下面我们还给其定义了一个LinearLayout,并且设置了其方向为垂直方向的线性布局。我们添加图片的操作放在了代码中来完成。下面来看一下ScrollViewActivity这个类:

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

public class ScrollViewActivity extends Activity
{    private LinearLayout layout;    public void onCreate(Bundle savedInstanceState)
    {        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_scrollview);

        layout = (LinearLayout) findViewById(R.id.layout);        for(int i = 0; i < 8; i++)
        {            //  通过资源文件来获得指定一个Drawable对象
            Drawable drawable = getResources().getDrawable(R.drawable.kk_hero);
            ImageView p_w_picpathView = new ImageView(this);
            p_w_picpathView.setImageDrawable(drawable);
            layout.addView(p_w_picpathView);
        }
    }
}

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

我们看到,这个Activity非常的简单,因为LinearLayout就是一个ViewGroup对象,所以我们可以动态的给其添加我们想要的View控件,这里我们给其添加了8张图片,我们来看看效果:

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr_05

我们看到,在Activity启动以后,就会在其下面生成8个ImageView的对象,并且这几张图片是可以在垂直方向上滚动的。

二、通过ScrollView实现从服务器端获取一条新闻,显示在界面上

接下来咱们通过ScrollView来做一个稍微实际一点的例子,我们经常会用手机来看新闻,当然一篇新闻是从服务器端获取过来的数据,而且可能一篇新闻里面有很多的内容,因此我们需要使用一个可以滚动的布局来显示我们的新闻内容,而TextView本身是可以实现文本的滚动显示的,但是结合ScrollView和TextView可以有更好的效果。

我们服务器端就很简单,让我们的应用程序访问服务器端的一个Html的文件,我们知道Html的文件里面会有许多的Html标签,那么我们如果想在Android上也能够显示标签的样式,就不能单单的只是将获取到的文本内容展示出来而已,这里就需要用的Android提供的一个 Html 的类,用它来处理我们从服务器端获得的Html的字符串内容:

我们的布局文件还是使用的刚才那一个:

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fillViewport="false">    <LinearLayout        android:id="@+id/layout"
        android:layout_height="match_parent"
        android:layout_width="wrap_content"
        android:orientation="vertical"/></ScrollView>

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

因为要访问网络,所以这里需要新建一个HttpUtils的工具类,来获得服务器端的文本内容:

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

public class HttpUtils
{    /**
     * 访问服务器端的内容
     * @param path  访问的url地址
     * @param encode    编码方式
     * @return  返回String类型的值     */    public static String getDataFromServer(String path, String encode)
    {
        String result = "";

        HttpClient httpClient = new DefaultHttpClient();        try
        {
            HttpPost httpPost = new HttpPost(path);
            HttpResponse httpResponse = httpClient.execute(httpPost);            if (httpResponse != null && httpResponse.getStatusLine().getStatusCode() == HttpStatus.SC_OK)
            {
                result = EntityUtils.toString(httpResponse.getEntity(), "utf-8");
            }
        }        catch (Exception e)
        {
            e.printStackTrace();
        }        finally
        {
            httpClient.getConnectionManager().shutdown();
        }        return result;
    }
}

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

我们还是用之前那个Activity:

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

public class ScrollViewActivity extends Activity
{    private LinearLayout layout;    private ProgressDialog dialog;    private TextView textView;    private final String PATH = "http://172.25.152.34:8080/httptest/news.html";    public void onCreate(Bundle savedInstanceState)
    {        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_scrollview);

        dialog = new ProgressDialog(this);
        dialog.setTitle("提示信息");
        dialog.setMessage("loading......");
        dialog.setCancelable(false);
        dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);

        layout = (LinearLayout) findViewById(R.id.layout);
        textView = new TextView(this);

        layout.addView(textView);        new MyTask().execute(PATH);
    }    public class MyTask extends AsyncTask<String, Void, String>
    {
        @Override        protected void onPreExecute()
        {
            dialog.show();
        }

        @Override        protected String doInBackground(String... params)
        {
            String result = HttpUtils.getDataFromServer(params[0], "utf-8");            return result;
        }

        @Override        protected void onPostExecute(String s)
        {            //  Html类的fromHtml方法可以处理一个Html的字符串文本,这样就可以根据Html的标签在手机上展示其样式
            Spanned spanned = Html.fromHtml(s);
            textView.setText(spanned);            //  给TextView设置一个方法,传一个LinkMovementMethod对象进去,这样当文本中如果有href链接时,系统会自动打开浏览器跳转到该href上
            textView.setMovementMethod(new LinkMovementMethod());
            dialog.dismiss();
        }
    }
}

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr

因为要访问网络数据,所以我们需要开启一个AsyncTask的一部任务,我们来看看onPostExecute方法,在获取到服务器端的Html文本内容后,我们通过Android提供的Html.fromHtml方法可以处理我们的Html文本,将Html的标签转化为我们需要的样式显示,但是这里要注意一点,这里并不会处理所有的Html的表情,例如<img>我们来看看Android官方API对这个方法的描述:

public static Spanned fromHtml (String source)

Returns displayable styled text from the provided HTML string. Any <img> tags in the HTML will display as a generic replacement p_w_picpath which your program can then go through and replace with real p_w_picpaths.

This uses TagSoup to handle real HTML, including all of the brokenness found in the wild.

如果文本当中有<img>标签,那么这个方法就会用一个默认的图片来代替我们的<img>标签中的图片,我们可以自己写一个Html.ImageGetter来加载我们自己想要的图片。

同时,因为文本内容中可能有href链接,因此我们可以通过 textView.setMovementMethod(new LinkMovementMethod()); 来绑定一个LinkMovementMethod,这样在点击链接的时候,就会调用浏览器跳转到该链接上。

Android UI系列-----ScrollView和HorizontalScrollView_Android UI系列-----Scr_12

相信通过前面的讲解,大家对ScrollView有了进一步的认识,这里并没有讲太多的HorizontalScrollView的知识,因为这个其实是和ScrollView基本上是一样的,只不过一个是垂直方向的滚动,而HorizontalScrollView是水平方向的滚动,同样HorizontalScrollView也是一个FrameLayout,因此我们通常给其定义一个水平方向布局的LinearLayout子元素,这样我们在里面添加的View子控件就可以在水平方向上滚动显示了。

 

三、总结

本篇随笔主要讲解了一下ScrollView和HorizontalScrollView的知识,因为这两个布局容器比较简单,因此基本上概念性的东西讲的少,主要还是通过代码来了解了ScrollView的使用方式,而对于HorizontalScrollView,其使用方式大同小异,大家可以通过Android官方API来了解更多有关这两个控件的知识。