Merge "Add haptic feedback to auth ripple animation" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
8c8765d3c3
@@ -23,7 +23,11 @@ import android.content.Context
|
|||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.PointF
|
import android.graphics.PointF
|
||||||
|
import android.media.AudioAttributes
|
||||||
|
import android.os.VibrationEffect
|
||||||
|
import android.os.Vibrator
|
||||||
import android.util.AttributeSet
|
import android.util.AttributeSet
|
||||||
|
import android.util.MathUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.animation.PathInterpolator
|
import android.view.animation.PathInterpolator
|
||||||
import com.android.internal.graphics.ColorUtils
|
import com.android.internal.graphics.ColorUtils
|
||||||
@@ -31,15 +35,26 @@ import com.android.systemui.statusbar.charging.RippleShader
|
|||||||
|
|
||||||
private const val RIPPLE_ANIMATION_DURATION: Long = 1533
|
private const val RIPPLE_ANIMATION_DURATION: Long = 1533
|
||||||
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
|
private const val RIPPLE_SPARKLE_STRENGTH: Float = 0.4f
|
||||||
|
private const val RIPPLE_VIBRATION_PRIMITIVE: Int = VibrationEffect.Composition.PRIMITIVE_LOW_TICK
|
||||||
|
private const val RIPPLE_VIBRATION_SIZE: Int = 60
|
||||||
|
private const val RIPPLE_VIBRATION_SCALE_START: Float = 0.6f
|
||||||
|
private const val RIPPLE_VIBRATION_SCALE_DECAY: Float = -0.1f
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expanding ripple effect on the transition from biometric authentication success to showing
|
* Expanding ripple effect on the transition from biometric authentication success to showing
|
||||||
* launcher.
|
* launcher.
|
||||||
*/
|
*/
|
||||||
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
|
class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
|
||||||
|
private val vibrator: Vibrator? = context?.getSystemService(Vibrator::class.java)
|
||||||
private var rippleInProgress: Boolean = false
|
private var rippleInProgress: Boolean = false
|
||||||
private val rippleShader = RippleShader()
|
private val rippleShader = RippleShader()
|
||||||
private val ripplePaint = Paint()
|
private val ripplePaint = Paint()
|
||||||
|
private val rippleVibrationEffect = createVibrationEffect(vibrator)
|
||||||
|
private val rippleVibrationAttrs =
|
||||||
|
AudioAttributes.Builder()
|
||||||
|
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
||||||
|
.setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
|
||||||
|
.build()
|
||||||
|
|
||||||
init {
|
init {
|
||||||
rippleShader.color = 0xffffffff.toInt() // default color
|
rippleShader.color = 0xffffffff.toInt() // default color
|
||||||
@@ -95,6 +110,7 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
visibility = GONE
|
visibility = GONE
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
vibrate()
|
||||||
animatorSet.start()
|
animatorSet.start()
|
||||||
visibility = VISIBLE
|
visibility = VISIBLE
|
||||||
rippleInProgress = true
|
rippleInProgress = true
|
||||||
@@ -108,4 +124,23 @@ class AuthRippleView(context: Context?, attrs: AttributeSet?) : View(context, at
|
|||||||
// draw over the entire screen
|
// draw over the entire screen
|
||||||
canvas?.drawRect(0f, 0f, width.toFloat(), height.toFloat(), ripplePaint)
|
canvas?.drawRect(0f, 0f, width.toFloat(), height.toFloat(), ripplePaint)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun vibrate() {
|
||||||
|
if (rippleVibrationEffect != null) {
|
||||||
|
vibrator?.vibrate(rippleVibrationEffect, rippleVibrationAttrs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createVibrationEffect(vibrator: Vibrator?): VibrationEffect? {
|
||||||
|
if (vibrator?.areAllPrimitivesSupported(RIPPLE_VIBRATION_PRIMITIVE) == false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
val composition = VibrationEffect.startComposition()
|
||||||
|
for (i in 0 until RIPPLE_VIBRATION_SIZE) {
|
||||||
|
val scale =
|
||||||
|
RIPPLE_VIBRATION_SCALE_START * MathUtils.exp(RIPPLE_VIBRATION_SCALE_DECAY * i)
|
||||||
|
composition.addPrimitive(RIPPLE_VIBRATION_PRIMITIVE, scale, 0 /* delay */)
|
||||||
|
}
|
||||||
|
return composition.compose()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user