最近在用原生的控件和布局绘制一些界面并使用,虽然这些都是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我们就介绍完了。
注:欢迎扫码关注