I'm making an animation of three rays coming out of the left top corner of the screen. They should spread out and then erase the whole "upper" screen. I've made a big progress in that, but two of these rays overlap strangely like they are pushing each other, so there remains a single line which I don't need. Can someone help me out and tell me what am I doing wrong?
CustomView code:
class CustomView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0,
) : View(context, attrs, defStyleAttr) {
companion object {
const val ADDITIONAL_NUM_VALUE_HOLDER = "additional_num"
const val TEXT_TOP_PADDING_VALUE_HOLDER = "text_top_padding"
}
private var rayPaint: Paint
private var textPaint: TextPaint
private var rayPath: Path = Path()
private var additionalNum = 1f
private var shouldAnimateRays = false
private var textX = 20f
private var textY = 0f
init {
rayPaint = Paint().apply {
style = Paint.Style.FILL
strokeWidth = 4f
color = -0x1
xfermode = PorterDuffXfermode(PorterDuff.Mode.CLEAR)
isAntiAlias = true
}
textPaint = TextPaint().apply {
style = Paint.Style.FILL
color = Color.BLUE
textSize = 60f
isAntiAlias = true
}
}
override fun dispatchDraw(canvas: Canvas) {
val bitmap = Bitmap.createBitmap(canvas.width, canvas.height, Bitmap.Config.ARGB_8888)
bitmap.eraseColor(Color.WHITE)
val additionalCanvas = Canvas(bitmap)
additionalCanvas.drawColor(Color.GREEN)
val someText = "Hello world"
val textLayout = StaticLayout.Builder
.obtain(someText, 0, someText.length, textPaint, additionalCanvas.width)
.setAlignment(Layout.Alignment.ALIGN_NORMAL)
.setLineSpacing(0.0f, 1.0f)
.setIncludePad(true)
.build()
additionalCanvas.save()
additionalCanvas.translate(textX, textY)
textLayout.draw(additionalCanvas)
additionalCanvas.restore()
if (shouldAnimateRays) {
val x = canvas.width.toFloat()
val y = canvas.height.toFloat()
// first ray
rayPath.moveTo(0f, 0f)
rayPath.lineTo(x, (y * 0.5f) - additionalNum)
rayPath.lineTo(x, (y * 0.5f) + additionalNum)
rayPath.lineTo(0f, 0f)
// second ray
rayPath.moveTo(0f, 0f)
rayPath.lineTo(x, (y * 0.7f) - additionalNum)
rayPath.lineTo(x, (y * 0.7f) + additionalNum)
rayPath.lineTo(0f, 0f)
// third ray
rayPath.moveTo(0f, 0f)
rayPath.lineTo((x * 0.7f) - additionalNum, y)
rayPath.lineTo((x * 0.7f) + additionalNum, y)
rayPath.lineTo(0f, 0f)
additionalCanvas.drawPath(rayPath, rayPaint)
}
canvas.drawBitmap(bitmap, 0f, 0f, null)
super.dispatchDraw(canvas)
}
fun animateShapes() {
val textValuesHolder = PropertyValuesHolder.ofFloat(TEXT_TOP_PADDING_VALUE_HOLDER, -100f, 20f)
val valuesHolder = PropertyValuesHolder.ofFloat(ADDITIONAL_NUM_VALUE_HOLDER, 1f, 800f)
val animator = ValueAnimator().apply {
setValues(valuesHolder)
duration = 2_000
interpolator = AccelerateDecelerateInterpolator()
addUpdateListener {
val addNum = it.getAnimatedValue(ADDITIONAL_NUM_VALUE_HOLDER) as Float
additionalNum = addNum
invalidate()
}
}
val textAnimator = ValueAnimator().apply {
setValues(textValuesHolder)
duration = 2_000
interpolator = AccelerateDecelerateInterpolator()
addUpdateListener {
val paddingTop = it.getAnimatedValue(TEXT_TOP_PADDING_VALUE_HOLDER) as Float
textY = paddingTop
invalidate()
}
doOnEnd {
shouldAnimateRays = true
animator.start()
}
}
textAnimator.start()
}
}
Acitivity code in order ro recreate this problem:
@AndroidEntryPoint
class CustomActivity : AppCompatActivity() {
private lateinit var binding: ActivityCustomBinding
protected var rootView: ViewGroup? = null
private set
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCustomBinding.inflate(layoutInflater)
setContentView(binding.root)
rootView = findViewById(android.R.id.content)
binding.customView.animateShapes()
}
}
Acitivity layout:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorWhite">
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleX="0.8"
android:scaleY="0.8"
android:src="@drawable/common_google_signin_btn_icon_dark_normal"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<com.app.android.view.CustomView
android:id="@+id/customView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
EDITED: link with the current result
