最近在用原生的控件和佈局繪製一些界面並使用,雖然這些都是Android基本知識,但是有的時候真的感覺力不從心,感覺有必要對Android常用的控件和佈局做一個系統的瞭解。後續一個月甚至更多的時間都會圍繞這個主題展開,畢竟這裏面還是有不少高級控件的,我也會盡量結合應用深入的進行了解。
今天,我們的主題是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我們就介紹完了。
注:歡迎掃碼關注