[英]Android : Animate Rating Bar to expand and shrink each star
我有一个评级栏,它显示 5 颗星,我想通过归档从 0 到 5 进行动画处理,具体取决于传递到视图中的评级值,并且每颗星的大小扩大,然后缩小到每颗星的原始大小已着色/填充。
例如,5 颗星中的所有 4 颗星都应该以 3.5 的星级为例进行扩展和缩小。
我已经用下面的代码将它从 0 填充到 3.5,但不知道如何扩展每个应用了填充的星星?
这可能吗?
这是我到目前为止所拥有的:
ObjectAnimator.ofFloat(starRating, "rating", 0f, 3.5f).apply {
duration = animDuration
addListener(onEachStarFilled?/onEachFrame?? = {
//todo expand each star? how?
})
start()
}
添加一个容器来保存五个带有默认图像的图像视图。
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="@+id/start_ratting"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:scaleType="fitCenter"
android:src="@drawable/empty"
android:id="@+id/star_1"/>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:src="@drawable/empty"
android:scaleType="fitCenter"
android:id="@+id/star_2"/>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:scaleType="fitCenter"
android:src="@drawable/empty"
android:id="@+id/star_3"/>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="@android:color/transparent"
android:scaleType="fitCenter"
android:src="@drawable/empty"
android:id="@+id/star_4"/>
<ImageView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:src="@drawable/empty"
android:background="@android:color/transparent"
android:scaleType="fitCenter"
android:id="@+id/star_5"/>
</LinearLayout>
然后添加动画师
private fun expandHorizontal(v: ImageView, image: Drawable) {
val width: Int = v.width
v.visibility = View.VISIBLE
v.layoutParams.width = 0
v.setImageDrawable(image)
val valueAnimator = ValueAnimator.ofInt(0, width)
valueAnimator.addUpdateListener { animation ->
v.layoutParams.width = animation.animatedValue as Int
v.requestLayout()
}
valueAnimator.interpolator = DecelerateInterpolator()
valueAnimator.duration = VIEW_TRANSITION_TIME
valueAnimator.start()
}
在需要时调用设置星值
private fun setStarValue(ratting: Double){
star1.visibility = View.INVISIBLE
star2.visibility = View.INVISIBLE
star3.visibility = View.INVISIBLE
star4.visibility = View.INVISIBLE
star5.visibility = View.INVISIBLE
var i = 0
for(i in 0..5){
when(i){
0->{
val res = ratting - i;
if(res >= 1){
Log.d(TAG, "start 1")
getDrawable(R.drawable.full)?.let { expandHorizontal(star1, it) }
}
else if(res > 0 && res < 1){
Log.d(TAG, "start half")
getDrawable(R.drawable.half)?.let { expandHorizontal(star1, it) }
}
else{
Log.d(TAG, "no start")
getDrawable(R.drawable.empty)?.let { expandHorizontal(star1, it) }
}
}
1 -> {
val res = ratting - i;
if(res >= 1){
Log.d(TAG, "start 2")
getDrawable(R.drawable.full)?.let { expandHorizontal(star2, it) }
}
else if(res > 0 && res < 1){
Log.d(TAG, "start two and half")
getDrawable(R.drawable.half)?.let { expandHorizontal(star2, it) }
}
else{
Log.d(TAG, "no start")
getDrawable(R.drawable.empty)?.let { expandHorizontal(star2, it) }
}
}
2->{
val res = ratting - i;
if(res >= 1){
Log.d(TAG, "start 3")
getDrawable(R.drawable.full)?.let { expandHorizontal(star3, it) }
}
else if(res > 0 && res < 1){
Log.d(TAG, "start three and half")
getDrawable(R.drawable.half)?.let { expandHorizontal(star3, it) }
}
else{
Log.d(TAG, "no start")
getDrawable(R.drawable.empty)?.let { expandHorizontal(star3, it) }
}
}
3 -> {
val res = ratting - i;
if(res >= 1){
Log.d(TAG, "start 4")
getDrawable(R.drawable.full)?.let { expandHorizontal(star4, it) }
}
else if(res > 0 && res < 1){
Log.d(TAG, "start 4 and half")
getDrawable(R.drawable.half)?.let { expandHorizontal(star4, it) }
}
else{
Log.d(TAG, "no start")
getDrawable(R.drawable.empty)?.let { expandHorizontal(star4, it) }
}
}
4 ->{
val res = ratting - i;
if(res >= 1){
Log.d(TAG, "start 5")
getDrawable(R.drawable.full)?.let { expandHorizontal(star5, it) }
}
else if(res > 0 && res < 1){
Log.d(TAG, "start three and half")
getDrawable(R.drawable.half)?.let { expandHorizontal(star5, it) }
}
else{
Log.d(TAG, "no start")
getDrawable(R.drawable.empty)?.let { expandHorizontal(star5, it) }
}
}
}
}
}
您可以在 expandHorizontal 中选择 animation
这是一个有点hackish的方法,你可以做到这一点。 带有背景颜色的图层会出现在您要隐藏的星星之上。 我尝试更改评分栏的大小,但评分显示错误。
activity_main.xml
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="60dp"
android:layout_marginTop="20dp">
<androidx.appcompat.widget.AppCompatRatingBar
android:id="@+id/ratingBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:isIndicator="true"
android:rating="3.5"
android:stepSize="0.1" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="#ffffff"
android:id="@+id/hideView"
android:orientation="horizontal"
android:layout_gravity="end"/>
</FrameLayout>
<Button
android:id="@+id/button3_5Stars"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="Set rating to 3.5 star" />
</LinearLayout>
MainActivity.kt
package com.example.test
import android.os.Bundle
import android.widget.Button
import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatRatingBar
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlin.math.ceil
class MainActivity : AppCompatActivity() {
var oneStarWidth:Int?=null
lateinit var ratingBar: AppCompatRatingBar
lateinit var hideView: LinearLayout
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
ratingBar=findViewById(R.id.ratingBar)
hideView=findViewById(R.id.hideView)
getSingleStarWidth()
findViewById<Button>(R.id.button3_5Stars).setOnClickListener {
CoroutineScope(Dispatchers.Main).launch {
ratingBar.rating=3.5F
expandTogivenRating(ratingBar.rating)
delay(1000)
collapseToSingleStar()
}
}
}
fun getSingleStarWidth(){
if(oneStarWidth==null){
ratingBar.post {
oneStarWidth=ratingBar.width/5
collapseToSingleStar()
}
}
}
fun collapseToSingleStar(){
expandTogivenRating(1.0f)
}
fun expandTogivenRating(rating:Float){
val ratingInt= ceil(rating.toDouble())
val layoutParams=hideView.layoutParams
layoutParams.width= ((5- ratingInt) * (oneStarWidth?:0)).toInt()
hideView.layoutParams=layoutParams
}
}
Output:-
您可以改进命名,animation,处理协程中的一次性。 这应该给你一个粗略的想法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.