Android UI系列-----ScrollView和HorizontalScrollView

xiaoluo501395377發表於2013-12-06

本篇隨筆將講解一下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檔案的根元素:

<?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>

我們看到,在ScrollView元素下面我們還給其定義了一個LinearLayout,並且設定了其方向為垂直方向的線性佈局。我們新增圖片的操作放在了程式碼中來完成。下面來看一下ScrollViewActivity這個類:

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 imageView = new ImageView(this);
            imageView.setImageDrawable(drawable);
            layout.addView(imageView);
        }
    }
}

我們看到,這個Activity非常的簡單,因為LinearLayout就是一個ViewGroup物件,所以我們可以動態的給其新增我們想要的View控制元件,這裡我們給其新增了8張圖片,我們來看看效果:

我們看到,在Activity啟動以後,就會在其下面生成8個ImageView的物件,並且這幾張圖片是可以在垂直方向上滾動的。

二、通過ScrollView實現從伺服器端獲取一條新聞,顯示在介面上

接下來我們們通過ScrollView來做一個稍微實際一點的例子,我們經常會用手機來看新聞,當然一篇新聞是從伺服器端獲取過來的資料,而且可能一篇新聞裡面有很多的內容,因此我們需要使用一個可以滾動的佈局來顯示我們的新聞內容,而TextView本身是可以實現文字的滾動顯示的,但是結合ScrollView和TextView可以有更好的效果。

我們伺服器端就很簡單,讓我們的應用程式訪問伺服器端的一個Html的檔案,我們知道Html的檔案裡面會有許多的Html標籤,那麼我們如果想在Android上也能夠顯示標籤的樣式,就不能單單的只是將獲取到的文字內容展示出來而已,這裡就需要用的Android提供的一個 Html 的類,用它來處理我們從伺服器端獲得的Html的字串內容:

我們的佈局檔案還是使用的剛才那一個:

<?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>

因為要訪問網路,所以這裡需要新建一個HttpUtils的工具類,來獲得伺服器端的文字內容:

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;
    }
}

我們還是用之前那個Activity:

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();
        }
    }
}

因為要訪問網路資料,所以我們需要開啟一個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 image which your program can then go through and replace with real images.

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,這樣在點選連結的時候,就會呼叫瀏覽器跳轉到該連結上。

相信通過前面的講解,大家對ScrollView有了進一步的認識,這裡並沒有講太多的HorizontalScrollView的知識,因為這個其實是和ScrollView基本上是一樣的,只不過一個是垂直方向的滾動,而HorizontalScrollView是水平方向的滾動,同樣HorizontalScrollView也是一個FrameLayout,因此我們通常給其定義一個水平方向佈局的LinearLayout子元素,這樣我們在裡面新增的View子控制元件就可以在水平方向上滾動顯示了。

 

三、總結

本篇隨筆主要講解了一下ScrollView和HorizontalScrollView的知識,因為這兩個佈局容器比較簡單,因此基本上概念性的東西講的少,主要還是通過程式碼來了解了ScrollView的使用方式,而對於HorizontalScrollView,其使用方式大同小異,大家可以通過Android官方API來了解更多有關這兩個控制元件的知識。

相關文章