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