代码之家  ›  专栏  ›  技术社区  ›  Jono

安卓:制作分级栏动画,以放大和缩小每个星星

  •  0
  • Jono  · 技术社区  · 5 年前

    我有一个分级栏,显示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()
    }
    
    0 回复  |  直到 5 年前
        1
  •  1
  •   alokHarman    5 年前

    添加一个容器,以容纳具有默认图像的五个图像视图。

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

    可以选择水平方向的动画

    enter image description here

        2
  •  0
  •   Manohar    5 年前

    这里有一个简单的方法。带有背景色的图层将显示在要隐藏的星星的顶部。我试着改变评级条的大小,但评级显示错误。

    主要活动。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>
    

    主要活动。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
    
        }
    }
    

    输出:-

    enter image description here

    您可以改进命名、动画、处理来自协同程序的一次性文件。这会给你一个大致的想法。