Android控件與佈局——基礎控件RatingBar

        最近在用原生的控件和佈局繪製一些界面並使用,雖然這些都是Android基本知識,但是有的時候真的感覺力不從心,感覺有必要對Android常用的控件和佈局做一個系統的瞭解。後續一個月甚至更多的時間都會圍繞這個主題展開,畢竟這裏面還是有不少高級控件的,我也會盡量結合應用深入的進行了解。

項目GitHub地址入口

上一篇:SeekBar    下一篇:Switch

今天,我們的主題是SeekBar,下面看一下官方文檔的部分介紹:它是一種通過星形表示比率的SeekBar和Progressbar控件的延伸,用戶可以通過拖拽或者點擊等方式來設置默認大小以及style的rating值;當一個RatingBar支持與用戶交互的時候,不建議在其兩側放置控件;

* A RatingBar is an extension of SeekBar and ProgressBar that shows a rating in
* stars. The user can touch/drag or use arrow keys to set the rating when using
* the default size RatingBar. The smaller RatingBar style (
* {@link android.R.attr#ratingBarStyleSmall}) and the larger indicator-only
* style ({@link android.R.attr#ratingBarStyleIndicator}) do not support user
* interaction and should only be used as indicators.
* <p>
* When using a RatingBar that supports user interaction, placing widgets to the
* left or right of the RatingBar is discouraged.

上面的解釋我們看着有點模糊,下面我們先結合一個動圖看一下效果:

可見,這是一種支持與用戶交互的標識程度的控件,我們對這個控件其實應該很熟悉,或者這個控件所表示的樣式,最最常見的就是我們的淘寶評價,幾星幾星的評價,其實好多應用也都使用類似這個控件的樣式,比如很多學習軟件可以用這個表示你目前的能力,一些遊戲軟件用來表示 能力指數等等。就我們平時所見的基本上都是與用戶不可交互的,那說明這個控件的rating值肯定是通過接口來動態設置的,主要是通過如下接口實現:

   /**
     * Sets the rating (the number of stars filled).
     *
     * @param rating The rating to set.
     */
    public void setRating(float rating) {
        setProgress(Math.round(rating * getProgressPerStar()));
    }

比如我們現在再舉一個例子

關鍵佈局代碼:

        <RatingBar
            android:id="@+id/rating_bar_spoken"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="20dp"
            android:max="5" />

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="30dp"
            android:onClick="updateRating"
            android:text="更新" />

關鍵邏輯代碼:

 /**
     * 更新Rating
     * @param view
     */
    public void updateRating(View view){
        float curRating=spokenEnglishRating.getRating();
        if(++curRating<=spokenEnglishRating.getMax()){
            spokenEnglishRating.setRating(curRating);
        }
        else {
            spokenEnglishRating.setRating(0.0f);
        }
    }

測試的效果:

可見我們通過setRating()可以設置它的值,需要注意一點,我們在xml代碼中雖然設置了max=5;但是當我們通過getMax()獲取最大值的時候默認還是10,但是我們通過setRating()設置值時顯示的比例是依據我們的xml代碼中max設置的值爲基礎的。這一點需要注意一下。我們可以通過接口setMax()來實現修改通過getMax()接口獲取的值,但是不能通過xml中的max屬性。

說到這裏,我們再展開以下,在第一張圖中,我們可以看到是可以實現半個填充的,後面我們設置了max=5之後就不行了,究竟是爲什麼了,先看一下對比圖再分析:

這裏需要理清幾個值之間的關係:

  • max:最大值
  • stepSize:步長
  • numStars:圖標星星數目

搞清楚它們三個關係只需要看一下RatingBar的getStepSize()源碼即可:

 /**
     * Gets the step size of this rating bar.
     *
     * @return The step size.
     */
    public float getStepSize() {
        return (float) getNumStars() / getMax();
    }

哦,原來步長等於星星數目除予最大值,所以當星星數固定和最大值固定,那麼步長就固定了。它們的默認值是:

  • numStars=5;
  • max=10;

所以默認情況下,步長是0.5,是可以設置爲一半的,當我們把max設置爲5時,步長就爲1了,所以只能整個選擇,那我們把max設置爲20,是不是可以0.25的進行選擇了,先看一下效果:

我們可以看到默認風格的0.25個星星其實就是外邊框顏色變深,在實際的應用中,我們可以根據自己的需求設計樣式,通常0.25,0.5,1這樣的stepSize基本就夠用了。這裏我再多囉嗦一句,看一下setStepSize()的源碼:

 /**
     * Sets the step size (granularity) of this rating bar.
     *
     * @param stepSize The step size of this rating bar. For example, if
     *            half-star granularity is wanted, this would be 0.5.
     */
    public void setStepSize(float stepSize) {
        if (stepSize <= 0) {
            return;
        }

        final float newMax = mNumStars / stepSize;
        final int newProgress = (int) (newMax / getMax() * getProgress());
        setMax((int) newMax);
        setProgress(newProgress);
    }

我們在設置stepSize的時候,會更新RatingBar的顯示和max值。

上面的與用戶可交互的RatingBar在平時的使用中其實是相對較少的,用的多的是將其用於表示程度的指示器(Indicator),下面我們接着看文檔介紹:通過設置它的style爲下面兩種的時候,RatingBar是不支持用戶交互的,只能被用作指示器。

The smaller RatingBar style (
* {@link android.R.attr#ratingBarStyleSmall}) and the larger indicator-only
* style ({@link android.R.attr#ratingBarStyleIndicator}) do not support user
* interaction and should only be used as indicators.

好的下面我們就來對比一下這三種style的樣式:

<RatingBar
    android:id="@+id/rating_bar0"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    style="@style/Widget.AppCompat.RatingBar"
    android:max="5" />

    <RatingBar
    android:id="@+id/rating_bar1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    style="@style/Widget.AppCompat.RatingBar.Small"
    android:layout_marginTop="20dp"
    android:max="5" />

    <RatingBar
    android:id="@+id/rating_bar3"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    style="@style/Widget.AppCompat.RatingBar.Indicator"
    android:layout_marginTop="20dp"
    android:max="5"
     />

可見,當RatingBar的style爲以下四種的時候,它的不可交互的,但是我們是可以通過setRating()來動態修改的

  style="@style/Widget.AppCompat.RatingBar.Indicator"
  style="@style/Base.Widget.AppCompat.RatingBar.Indicator"
  style="@style/Widget.AppCompat.RatingBar.Small"
  style="@style/Base.Widget.AppCompat.RatingBar.Small"

我們再回到第一個小示例,把佈局代碼中的RatingBar換成:

         <RatingBar
            android:id="@+id/rating_bar_spoken"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/Widget.AppCompat.RatingBar.Indicator"
            android:layout_marginTop="20dp"
            android:max="5" />

我們重新運行一下代碼,結果如下:

那我們也是可以通過接口來動態設置它是否是指示器的(RatingBar接口源碼):

 /**
     * Whether this rating bar should only be an indicator (thus non-changeable
     * by the user).
     *
     * @param isIndicator Whether it should be an indicator.
     *
     * @attr ref android.R.styleable#RatingBar_isIndicator
     */
    public void setIsIndicator(boolean isIndicator) {
        mIsUserSeekable = !isIndicator;
        if (isIndicator) {
            setFocusable(FOCUSABLE_AUTO);
        } else {
            setFocusable(FOCUSABLE);
        }
    }

下面我們把上面的RatingBar代碼恢復到最初的模樣,然後在Activity中通過調用如下代碼實現上述同樣的功能:

spokenEnglishRating.setIsIndicator(true);

可見,這個時候RatingBar也不能交互,但是可以通過接口設置值,同時你也可以發現,這個style的樣式沒有Indicator的樣式好看,同樣的,我們平時在其他的應用上看到的樣式都是各種各樣比較好看的,有心形的,有花形的等等。下面我們就來看看如何

上面所說的效果。首先分爲以下幾步:

  • 自定義RatingBar背景樣式my_rating_bar_back.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <!-- 必須使用此id,drawable爲 未選中 狀態的圖片 -->
    <item
        android:id="@android:id/background"
        android:drawable="@drawable/default_rating_bar_back"/>
    <!-- 必須使用此id,drawable爲 半選中 狀態的圖片 -->
    <item
        android:id="@android:id/secondaryProgress"
        android:drawable="@drawable/rating_bar_half1"/>

    <!-- 必須使用此id,drawable爲 全選中 狀態的圖片 -->
    <item
        android:id="@android:id/progress"
        android:drawable="@drawable/chosen_rating_bar_back"/>
</layer-list>
  • 自定義RatingBar的樣式MyRatingBarStyle1
    <style name="MyRatingBarStyle1" parent="@android:style/Widget.RatingBar">
        <!-- 定義星星圖片 -->
        <item name="android:progressDrawable">@drawable/my_rating_bar_back</item>
    </style>
  • 使用自定義style
         <RatingBar
            android:id="@+id/rating_bar1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            style="@style/MyRatingBarStyle1"
            android:layout_marginTop="20dp"
            />

使用的效果如下:

好了,到這裏,關於Ratingbar我們就介紹完了。

注:歡迎掃碼關注


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章