@@ -26,18 +26,15 @@ import android.util.AttributeSet
2626import android.view.GestureDetector
2727import android.view.LayoutInflater
2828import android.view.MotionEvent
29- import android.view.View
3029import android.view.animation.AnimationUtils
3130import android.view.animation.LinearInterpolator
3231import android.view.animation.OvershootInterpolator
33- import android.widget.Chronometer
34- import android.widget.ImageView
35- import androidx.appcompat.widget.AppCompatImageView
3632import androidx.appcompat.widget.ThemeUtils
3733import androidx.constraintlayout.widget.ConstraintLayout
3834import androidx.core.util.TypedValueCompat
3935import androidx.core.view.isVisible
4036import com.ichi2.anki.R
37+ import com.ichi2.anki.databinding.ViewAudioRecordBinding
4138import com.ichi2.compat.CompatHelper
4239import com.ichi2.compat.USAGE_TOUCH
4340import com.ichi2.utils.Permissions
@@ -58,16 +55,7 @@ import kotlin.time.Duration.Companion.milliseconds
5855 * It also displays a recording icon and time
5956 */
6057class AudioRecordView : ConstraintLayout {
61- // region Views
62- private val recordButton: View
63- private val recordButtonIcon: ImageView
64- private val lockArrow: View
65- private val imageViewLock: View
66- private val recordDisplayIcon: AppCompatImageView
67- private val layoutSlideCancel: View
68- private val layoutLock: View
69- private val chronometer: Chronometer
70- // endregion
58+ private val binding = ViewAudioRecordBinding .inflate(LayoutInflater .from(context), this )
7159
7260 // region Animations
7361 private val animBlink = AnimationUtils .loadAnimation(context, R .anim.blink)
@@ -110,17 +98,8 @@ class AudioRecordView : ConstraintLayout {
11098 defStyleAttr: Int ,
11199 defStyleRes: Int ,
112100 ) : super (context, attrs, defStyleAttr, defStyleRes) {
113- LayoutInflater .from(context).inflate(R .layout.audio_record_view, this , true )
114101 this .clipChildren = false
115102
116- recordButton = findViewById(R .id.recordButton)
117- recordButtonIcon = findViewById(R .id.recordIcon)
118- imageViewLock = findViewById(R .id.lock_icon)
119- lockArrow = findViewById(R .id.lock_arrow_icon)
120- chronometer = findViewById(R .id.chronometer)
121- layoutSlideCancel = findViewById(R .id.layout_slide_cancel)
122- layoutLock = findViewById(R .id.layoutLock)
123- recordDisplayIcon = findViewById(R .id.recording_status_icon)
124103 cancelOffset = max((resources.displayMetrics.widthPixels * 0.25f ), 60f * dp)
125104 cancelFadeOffset = cancelOffset * 0.8f
126105 lockOffset = max((resources.displayMetrics.heightPixels * 0.25f ), 80f * dp)
@@ -161,7 +140,7 @@ class AudioRecordView : ConstraintLayout {
161140 return true
162141 }
163142 startRecording()
164- recordButton
143+ binding. recordButton
165144 .animate()
166145 .scaleX(1.25f )
167146 .scaleY(1.25f )
@@ -185,7 +164,7 @@ class AudioRecordView : ConstraintLayout {
185164 }
186165 },
187166 )
188- recordButton.setOnTouchListener(gestureListener)
167+ binding. recordButton.setOnTouchListener(gestureListener)
189168 }
190169
191170 private val gestureListener =
@@ -248,14 +227,14 @@ class AudioRecordView : ConstraintLayout {
248227 private fun translateY (y : Float ) {
249228 if (y < - lockOffset) {
250229 lock()
251- recordButton.translationY = 0f
230+ binding. recordButton.translationY = 0f
252231 return
253232 }
254233
255- layoutLock.visibility = VISIBLE
256- recordButton.translationY = y
257- layoutLock.translationY = y / 2
258- recordButton.translationX = 0f
234+ binding. layoutLock.visibility = VISIBLE
235+ binding. recordButton.translationY = y
236+ binding. layoutLock.translationY = y / 2
237+ binding. recordButton.translationX = 0f
259238 }
260239
261240 /* *
@@ -266,23 +245,23 @@ class AudioRecordView : ConstraintLayout {
266245 private fun translateX (x : Float ) {
267246 if (x < - cancelOffset) {
268247 cancel()
269- recordButton.translationX = 0f
270- layoutSlideCancel.translationX = 0f
248+ binding. recordButton.translationX = 0f
249+ binding. layoutSlideCancel.translationX = 0f
271250 return
272251 }
273252
274253 val alpha = (cancelFadeOffset - abs(x)) / cancelFadeOffset
275- layoutSlideCancel.alpha = alpha.coerceIn(0f , 1f )
254+ binding. layoutSlideCancel.alpha = alpha.coerceIn(0f , 1f )
276255
277- recordButton.translationX = x
278- layoutSlideCancel.translationX = x
279- layoutLock.translationY = 0f
280- recordButton.translationY = 0f
256+ binding. recordButton.translationX = x
257+ binding. layoutSlideCancel.translationX = x
258+ binding. layoutLock.translationY = 0f
259+ binding. recordButton.translationY = 0f
281260
282- if (abs(x) < recordButton.width / 2 ) {
283- layoutLock.visibility = VISIBLE
261+ if (abs(x) < binding. recordButton.width / 2 ) {
262+ binding. layoutLock.visibility = VISIBLE
284263 } else {
285- layoutLock.visibility = GONE
264+ binding. layoutLock.visibility = GONE
286265 }
287266 }
288267
@@ -294,54 +273,54 @@ class AudioRecordView : ConstraintLayout {
294273 }
295274
296275 private fun showCancelAndLockSliders () {
297- recordButton
276+ binding. recordButton
298277 .animate()
299278 .scaleX(1.8f )
300279 .scaleY(1.8f )
301280 .setDuration(200 )
302281 .setInterpolator(OvershootInterpolator ())
303282 .start()
304283
305- layoutLock.visibility = VISIBLE
306- layoutSlideCancel.visibility = VISIBLE
307- lockArrow .startAnimation(animJumpFast)
308- imageViewLock .startAnimation(animJump)
284+ binding. layoutLock.visibility = VISIBLE
285+ binding. layoutSlideCancel.visibility = VISIBLE
286+ binding.lockArrowIcon .startAnimation(animJumpFast)
287+ binding.lockIcon .startAnimation(animJump)
309288 }
310289
311290 /* *
312291 * Sets the visibility of the record timer and icon to [isVisible]
313292 */
314293 fun setRecordDisplayVisibility (isVisible : Boolean ) {
315- chronometer.isVisible = isVisible
316- recordDisplayIcon .isVisible = isVisible
294+ binding. chronometer.isVisible = isVisible
295+ binding.recordingDisplayIcon .isVisible = isVisible
317296 }
318297
319298 private fun displayRunningRecord () {
320299 setRecordDisplayVisibility(true )
321300
322- recordDisplayIcon .setColorFilter(recordEnabledColor)
323- recordDisplayIcon .startAnimation(animBlink)
301+ binding.recordingDisplayIcon .setColorFilter(recordEnabledColor)
302+ binding.recordingDisplayIcon .startAnimation(animBlink)
324303
325- chronometer.base = if (chronometerBase > 0 ) chronometerBase else SystemClock .elapsedRealtime()
326- chronometer.isEnabled = true
327- chronometer.start()
304+ binding. chronometer.base = if (chronometerBase > 0 ) chronometerBase else SystemClock .elapsedRealtime()
305+ binding. chronometer.isEnabled = true
306+ binding. chronometer.start()
328307 }
329308
330309 private fun lock () {
331310 state = ViewState .LOCKED
332311 stopTrackingAction = true
333312
334- recordButtonIcon .setImageResource(R .drawable.ic_stop)
335- recordButton.animate().cancel()
336- recordButton.scaleX = 1f
337- recordButton.scaleY = 1f
313+ binding.recordIcon .setImageResource(R .drawable.ic_stop)
314+ binding. recordButton.animate().cancel()
315+ binding. recordButton.scaleX = 1f
316+ binding. recordButton.scaleY = 1f
338317
339- recordButton.setOnTouchListener(null )
340- recordButton.setOnClickListener {
318+ binding. recordButton.setOnTouchListener(null )
319+ binding. recordButton.setOnClickListener {
341320 stopRecording(RecordingBehavior .LOCK )
342321 }
343- layoutSlideCancel.visibility = GONE
344- layoutLock.visibility = GONE
322+ binding. layoutSlideCancel.visibility = GONE
323+ binding. layoutLock.visibility = GONE
345324 }
346325
347326 private fun cancel () {
@@ -354,7 +333,7 @@ class AudioRecordView : ConstraintLayout {
354333
355334 val animateRelease = outcome == RecordingBehavior .RELEASE
356335 reset(animate = animateRelease)
357- chronometer.stop()
336+ binding. chronometer.stop()
358337
359338 when (outcome) {
360339 RecordingBehavior .CANCEL -> {
@@ -375,12 +354,12 @@ class AudioRecordView : ConstraintLayout {
375354 lastY = 0f
376355 chronometerBase = 0
377356
378- recordButtonIcon .setImageResource(R .drawable.ic_action_mic)
379- recordButton.setOnClickListener(null )
380- recordButton.setOnTouchListener(gestureListener)
357+ binding.recordIcon .setImageResource(R .drawable.ic_action_mic)
358+ binding. recordButton.setOnClickListener(null )
359+ binding. recordButton.setOnTouchListener(gestureListener)
381360
382361 if (animate) {
383- recordButton
362+ binding. recordButton
384363 .animate()
385364 .scaleX(1f )
386365 .scaleY(1f )
@@ -390,47 +369,47 @@ class AudioRecordView : ConstraintLayout {
390369 .setInterpolator(LinearInterpolator ())
391370 .start()
392371 } else {
393- recordButton.animate().cancel()
394- recordButton.scaleX = 1f
395- recordButton.scaleY = 1f
396- recordButton.translationX = 0f
397- recordButton.translationY = 0f
372+ binding. recordButton.animate().cancel()
373+ binding. recordButton.scaleX = 1f
374+ binding. recordButton.scaleY = 1f
375+ binding. recordButton.translationX = 0f
376+ binding. recordButton.translationY = 0f
398377 }
399378
400- layoutSlideCancel.visibility = GONE
401- layoutLock.visibility = GONE
402- chronometer.visibility = INVISIBLE
403- recordDisplayIcon .visibility = INVISIBLE
379+ binding. layoutSlideCancel.visibility = GONE
380+ binding. layoutLock.visibility = GONE
381+ binding. chronometer.visibility = INVISIBLE
382+ binding.recordingDisplayIcon .visibility = INVISIBLE
404383
405384 // Reset the translation of the sliders to ensure they start from the correct position next time
406- layoutLock.translationY = 0f
407- layoutSlideCancel.translationX = 0f
408- layoutSlideCancel.alpha = 1f
385+ binding. layoutLock.translationY = 0f
386+ binding. layoutSlideCancel.translationX = 0f
387+ binding. layoutSlideCancel.alpha = 1f
409388
410389 setRecordDisplayVisibility(true )
411- chronometer.base = SystemClock .elapsedRealtime()
412- chronometer.isEnabled = false
413- recordDisplayIcon .setColorFilter(recordDisabledColor)
414- recordDisplayIcon .clearAnimation()
415- lockArrow .clearAnimation()
416- imageViewLock .clearAnimation()
390+ binding. chronometer.base = SystemClock .elapsedRealtime()
391+ binding. chronometer.isEnabled = false
392+ binding.recordingDisplayIcon .setColorFilter(recordDisabledColor)
393+ binding.recordingDisplayIcon .clearAnimation()
394+ binding.lockArrowIcon .clearAnimation()
395+ binding.lockIcon .clearAnimation()
417396 }
418397
419398 /* *
420399 * Immediately stops all actions and animations, and returns the view to its initial state.
421400 */
422401 fun forceReset () {
423- chronometer.stop()
424- recordButton.clearAnimation()
425- recordDisplayIcon .clearAnimation()
402+ binding. chronometer.stop()
403+ binding. recordButton.clearAnimation()
404+ binding.recordingDisplayIcon .clearAnimation()
426405 reset(animate = false )
427406 }
428407
429408 override fun onSaveInstanceState (): Parcelable {
430409 val superState = super .onSaveInstanceState()
431410 val savedState = SavedState (superState)
432411 savedState.state = state
433- savedState.chronometerBase = chronometer.base
412+ savedState.chronometerBase = binding. chronometer.base
434413 return savedState
435414 }
436415
0 commit comments