16
16
17
17
package com.duckduckgo.duckchat.impl.inputscreen.ui.view
18
18
19
- import android.animation.ValueAnimator
20
19
import android.content.Context
20
+ import android.os.Build
21
21
import android.text.InputType
22
22
import android.transition.ChangeBounds
23
23
import android.transition.Fade
@@ -26,21 +26,15 @@ import android.util.AttributeSet
26
26
import android.view.LayoutInflater
27
27
import android.view.View
28
28
import android.view.ViewGroup
29
- import android.view.animation.DecelerateInterpolator
30
29
import android.view.inputmethod.EditorInfo
31
30
import android.view.inputmethod.InputMethodManager
32
31
import android.widget.EditText
33
32
import androidx.annotation.IdRes
34
33
import androidx.constraintlayout.widget.ConstraintLayout
35
- import androidx.core.animation.addListener
36
34
import androidx.core.view.isVisible
37
- import androidx.core.view.marginBottom
38
- import androidx.core.view.marginEnd
39
- import androidx.core.view.marginStart
40
- import androidx.core.view.marginTop
41
- import androidx.core.view.updateLayoutParams
42
35
import androidx.core.widget.doOnTextChanged
43
36
import com.duckduckgo.anvil.annotations.InjectWith
37
+ import com.duckduckgo.common.ui.view.addBottomShadow
44
38
import com.duckduckgo.di.scopes.ActivityScope
45
39
import com.duckduckgo.duckchat.impl.R
46
40
import com.duckduckgo.mobile.android.R as CommonR
@@ -54,27 +48,11 @@ class InputModeWidget @JvmOverloads constructor(
54
48
defStyle : Int = 0 ,
55
49
) : ConstraintLayout(context, attrs, defStyle) {
56
50
57
- private val omnibarCardMarginHorizontal by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarCardMarginHorizontal) }
58
- private val omnibarCardMarginTop by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarCardMarginTop) }
59
- private val omnibarCardMarginBottom by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarCardMarginBottom) }
60
- private val omnibarCardFocusedMarginHorizontal by lazy {
61
- resources.getDimensionPixelSize(
62
- CommonR .dimen.experimentalOmnibarCardFocusedMarginHorizontal,
63
- )
64
- }
65
- private val omnibarCardFocusedMarginTop by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarCardFocusedMarginTop) }
66
- private val omnibarCardFocusedMarginBottom by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarCardFocusedMarginBottom) }
67
-
68
- private val omnibarOutlineWidth by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarOutlineWidth) }
69
- private val omnibarOutlineFocusedWidth by lazy { resources.getDimensionPixelSize(CommonR .dimen.experimentalOmnibarOutlineFocusedWidth) }
70
-
71
- private val omnibarCard: MaterialCardView by lazy { findViewById(R .id.inputModeWidgetCard) }
72
- private val omnibarContent: View by lazy { findViewById(R .id.inputModeWidgetCardContent) }
73
-
74
51
val inputField: EditText
75
- val inputFieldClearText: View
76
- val inputModeWidgetBack: View
77
- val inputModeSwitch: TabLayout
52
+ private val inputFieldClearText: View
53
+ private val inputModeWidgetBack: View
54
+ private val inputModeSwitch: TabLayout
55
+ private val inputModeWidgetCard: MaterialCardView
78
56
79
57
var onBack: (() -> Unit )? = null
80
58
var onSearchSent: ((String ) -> Unit )? = null
@@ -97,7 +75,6 @@ class InputModeWidget @JvmOverloads constructor(
97
75
98
76
@IdRes
99
77
private var contentId: Int = View .NO_ID
100
- private var focusAnimator: ValueAnimator ? = null
101
78
private var originalText: String? = null
102
79
private var hasTextChangedFromOriginal = false
103
80
@@ -108,11 +85,13 @@ class InputModeWidget @JvmOverloads constructor(
108
85
inputFieldClearText = findViewById(R .id.inputFieldClearText)
109
86
inputModeWidgetBack = findViewById(R .id.InputModeWidgetBack )
110
87
inputModeSwitch = findViewById(R .id.inputModeSwitch)
88
+ inputModeWidgetCard = findViewById(R .id.inputModeWidgetCard)
111
89
112
90
configureClickListeners()
113
91
configureInputBehavior()
114
92
configureTabBehavior()
115
93
applyModeSpecificInputBehaviour(isSearchTab = true )
94
+ configureShadow()
116
95
}
117
96
118
97
fun provideInitialText (text : String ) {
@@ -135,10 +114,6 @@ class InputModeWidget @JvmOverloads constructor(
135
114
setHorizontallyScrolling(false )
136
115
setRawInputType(InputType .TYPE_CLASS_TEXT or InputType .TYPE_TEXT_VARIATION_URI or InputType .TYPE_TEXT_FLAG_NO_SUGGESTIONS )
137
116
138
- setOnFocusChangeListener { _, hasFocus ->
139
- animateOmnibarFocusedState(hasFocus)
140
- }
141
-
142
117
setOnEditorActionListener { _, actionId, _ ->
143
118
if (actionId == EditorInfo .IME_ACTION_GO ) {
144
119
submitMessage()
@@ -251,58 +226,6 @@ class InputModeWidget @JvmOverloads constructor(
251
226
contentId = id
252
227
}
253
228
254
- fun animateOmnibarFocusedState (focused : Boolean ) {
255
- focusAnimator?.cancel()
256
-
257
- val startTop = omnibarCard.marginTop
258
- val startBottom = omnibarCard.marginBottom
259
- val startStart = omnibarCard.marginStart
260
- val startEnd = omnibarCard.marginEnd
261
- val startStroke = omnibarCard.strokeWidth
262
-
263
- val endTop = if (focused) omnibarCardFocusedMarginTop else omnibarCardMarginTop
264
- val endBottom = if (focused) omnibarCardFocusedMarginBottom else omnibarCardMarginBottom
265
- val endStart = if (focused) omnibarCardFocusedMarginHorizontal else omnibarCardMarginHorizontal
266
- val endEnd = if (focused) omnibarCardFocusedMarginHorizontal else omnibarCardMarginHorizontal
267
- val endStroke = if (focused) omnibarOutlineFocusedWidth else omnibarOutlineWidth
268
-
269
- ValueAnimator .ofFloat(0f , 1f ).apply {
270
- duration = DEFAULT_ANIMATION_DURATION
271
- interpolator = DecelerateInterpolator ()
272
- addUpdateListener { valueAnimator ->
273
- val fraction = valueAnimator.animatedFraction
274
- (omnibarCard.layoutParams as MarginLayoutParams ).apply {
275
- leftMargin = (startStart + (endStart - startStart) * fraction).toInt()
276
- topMargin = (startTop + (endTop - startTop) * fraction).toInt()
277
- rightMargin = (startEnd + (endEnd - startEnd) * fraction).toInt()
278
- bottomMargin = (startBottom + (endBottom - startBottom) * fraction).toInt()
279
- }.also { omnibarCard.layoutParams = it }
280
- omnibarCard.strokeWidth = (startStroke + (endStroke - startStroke) * fraction).toInt()
281
- }
282
- addListener(
283
- onStart = { lockContentDimensions() },
284
- onEnd = { if (! focused) unlockContentDimensions() },
285
- onCancel = { removeAllListeners() },
286
- )
287
- start()
288
- focusAnimator = this
289
- }
290
- }
291
-
292
- private fun lockContentDimensions () {
293
- omnibarContent.updateLayoutParams {
294
- width = omnibarContent.measuredWidth
295
- height = ViewGroup .LayoutParams .WRAP_CONTENT
296
- }
297
- }
298
-
299
- private fun unlockContentDimensions () {
300
- omnibarContent.updateLayoutParams {
301
- width = ViewGroup .LayoutParams .MATCH_PARENT
302
- height = ViewGroup .LayoutParams .WRAP_CONTENT
303
- }
304
- }
305
-
306
229
fun printNewLine () {
307
230
val currentText = inputField.text.toString()
308
231
val selectionStart = inputField.selectionStart
@@ -317,8 +240,18 @@ class InputModeWidget @JvmOverloads constructor(
317
240
return text.ifBlank { null }
318
241
}
319
242
243
+ private fun configureShadow () {
244
+ if (Build .VERSION .SDK_INT >= 28 ) {
245
+ inputModeWidgetCard.addBottomShadow(
246
+ shadowSizeDp = 12f ,
247
+ offsetYDp = 3f ,
248
+ insetDp = 3f ,
249
+ shadowColor = context.getColor(CommonR .color.background_omnibar_shadow),
250
+ )
251
+ }
252
+ }
253
+
320
254
companion object {
321
- private const val DEFAULT_ANIMATION_DURATION = 300L
322
255
private const val FADE_DURATION = 150L
323
256
private const val MAX_LINES = 8
324
257
private const val SEARCH_MIN_LINES = 1
0 commit comments