Не удается получить правильное значение настраиваемого атрибута в настраиваемом переходе - PullRequest
0 голосов
/ 01 августа 2020
• 1000 . Но в процессе работы, когда я получаю imageCornerRadius, он возвращает значение в файле xml. Итак, как я могу заставить imageCornerRadius выполнить переход.

Это объявление моего настраиваемого представления

RoundedImageView

настраиваемый атрибут

    <declare-styleable name="RoundedImageView">
        <attr name="imageCornerRadius" format="dimension" />
    </declare-styleable>
class RoundedImageView : AppCompatImageView {
    constructor(context: Context) : super(context) {
        Log.d("debug", "first constructor")
    }

    constructor(context: Context, attrSet: AttributeSet) : super(context, attrSet) {
        Log.d("debug", "second constructor")

        init(attrSet)
    }

    constructor(context: Context, attrSet: AttributeSet, defStyleAttr: Int) : super(
        context,
        attrSet,
        defStyleAttr
    ) {
        Log.d("debug", "third constructor")
        init(attrSet)
    }

    private fun init(attrSet: AttributeSet){
        context.theme.obtainStyledAttributes(
            attrSet,
            R.styleable.RoundedImageView,
            0,
            0
        ).apply {
            try {
                imageCornerRadius = getDimensionPixelSize(
                    R.styleable.RoundedImageView_imageCornerRadius,
                    0
                ).toFloat()
            } finally {
                recycle()
            }
        }
    }
    // Custom attr
    var imageCornerRadius: Float = 0F

    //Attr for drawing
    private lateinit var bitmapRect: RectF
    val rect = RectF(drawable.bounds)
    val holePath = Path()

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        Log.d("size changed", "w = $w h = $h")
        bitmapRect = RectF(0f, 0f, w.toFloat(), h.toFloat())
    }

    override fun onDraw(canvas: Canvas?) {
        val drawableWidth = this.width
        val drawableHeight = this.height
        /* Clip */
        holePath.apply {
            reset()
            addRoundRect(
                0F,
                0F,
                rect.right + drawableWidth,
                rect.bottom + drawableHeight,
                imageCornerRadius,
                imageCornerRadius,
                Path.Direction.CW
            )
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            canvas?.clipPath(holePath)
        } else {
            @Suppress("DEPRECATION")
            canvas?.clipPath(holePath, Region.Op.REPLACE)
        }

        // Draw image
        super.onDraw(canvas)

    }
}

Мой пользовательский переход изменить Size, Coordinate, imageCornerRadius CircleTransition.kt

class CircleTransition() : Transition() {
    private val TAG = CircleTransition::class.java.simpleName
    private val BOUNDS = TAG + ":viewBounds"
    private val CORNER_RADIUS = TAG + ":imageCornerRadius"
    private val PROPS = arrayOf(BOUNDS, CORNER_RADIUS)

    init {
        Log.d("debug", "Circle Transition called")
    }

    override fun captureStartValues(transitionValues: TransitionValues?) {
        captureValues(transitionValues)
    }

    override fun captureEndValues(transitionValues: TransitionValues?) {
        captureValues(transitionValues)
    }


    fun captureValues(transitionValues: TransitionValues?) {
        val view = transitionValues?.view

        //get View Bound
        val bound = RectF()
        bound.left = view?.left?.toFloat() ?: return
        bound.top = view.top.toFloat()
        bound.right = view.right.toFloat()
        bound.bottom = view.bottom.toFloat()
        transitionValues.values.put(BOUNDS, bound)

        //get view Corner radius
        if(view is RoundedImageView){
            val cornerRadius = view.imageCornerRadius
            transitionValues.values.put(CORNER_RADIUS, cornerRadius)
        }
    }

    override fun getTransitionProperties(): Array<String> {
        return PROPS
    }


    override fun createAnimator(
        sceneRoot: ViewGroup?,
        startValues: TransitionValues?,
        endValues: TransitionValues?
    ): Animator? {
        if (startValues == null || endValues == null) {
            return null
        }

        val view = endValues.view as RoundedImageView
        //startScene
        val sBound = startValues.values[BOUNDS] as RectF? ?: return null
        
        //How I get imageCornerRadius
        val sCornerRadius = startValues.values[CORNER_RADIUS] as Float? ?: return null 
        val sWidth = sBound.right - sBound.left
        val sHeight = sBound.top - sBound.bottom

        //endScene
        val eBound = endValues.values[BOUNDS] as RectF? ?: return null

        //How I get imageCornerRadius
        val eCornerRadius = endValues.values[CORNER_RADIUS] as Float? ?: return null
        val eWidth = eBound.right - eBound.left
        val eHeight = eBound.top - eBound.bottom

        if (sBound == eBound && sCornerRadius == eCornerRadius) {
            return null
        }

        val widthAnimator: ValueAnimator =
            ValueAnimator.ofInt(sWidth.toInt(), eWidth.toInt()).apply {
                addUpdateListener {
                    val layoutParams = view.layoutParams
                    layoutParams.width = it.animatedValue as Int
                    view.layoutParams = layoutParams
                }
            }

        val heightAnimator: ValueAnimator =
            ValueAnimator.ofInt(sHeight.toInt() * -1, eHeight.toInt() * -1).apply {
                interpolator = AccelerateInterpolator()
                addUpdateListener {
                    val layoutParams = view.layoutParams
                    layoutParams.height = it.animatedValue as Int
                    view.layoutParams = layoutParams
                }
            }

        val cornerRadiusAnimator = ValueAnimator.ofFloat(96F, 0F).apply {
            addUpdateListener {
                view.imageCornerRadius = it.animatedValue as Float
            }
        }

        // set endView have the same size, coorinate like startScene
        view.x = sBound.left
        view.y = sBound.top

//        view.layoutParams = ViewGroup.LayoutParams(sBound.width().toInt(), sBound.height().toInt())
        // move view
        val startX = sBound.left
        val startY = sBound.top

        val moveXTo = eBound.left
        val moveYTo = eBound.top

        val moveXAnimator: Animator =
            ObjectAnimator.ofFloat(view, "x", startX, moveXTo.toFloat())
        val moveYAnimator: Animator =
            ObjectAnimator.ofFloat(view, "y", startY, moveYTo.toFloat()).apply {
                addUpdateListener {
                    view.invalidate()
                }
            }


        val animatorSet = AnimatorSet()
        animatorSet.playTogether(
            widthAnimator,
            heightAnimator,
            cornerRadiusAnimator,
            moveXAnimator,
            moveYAnimator
        )
        return animatorSet
    }
}
...