Skip to content

Commit 9108782

Browse files
authored
update input screen in/out transitions (#6390)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1208671518894266/task/1210750831271803?focus=true ### Description Updates the Input Screen in/out transitions ### Steps to test this PR - [x] Open/close input screen and verify the transition matches the mockups. - [x] (optional) Verify the transition on API 33 or below but note https://app.asana.com/1/137249556945/task/1210786203196179 which we'll need to address separately. On Emulator API 33 it works fine to me.
1 parent 03b25ea commit 9108782

File tree

11 files changed

+167
-62
lines changed

11 files changed

+167
-62
lines changed

app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,10 +1059,10 @@ class BrowserTabFragment :
10591059
requireContext(),
10601060
InputScreenActivityParams(query = query),
10611061
)
1062-
val options = ActivityOptionsCompat.makeSceneTransitionAnimation(
1062+
val options = ActivityOptionsCompat.makeCustomAnimation(
10631063
requireActivity(),
1064-
omnibar.omniBarContainer,
1065-
"omnibar_transition",
1064+
CommonR.anim.slide_in_from_top_fade_in,
1065+
CommonR.anim.slide_out_to_bottom_fade_out,
10661066
)
10671067
searchInterstitialLauncher.launch(intent, options)
10681068
}

app/src/main/res/layout/view_fade_omnibar.xml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,7 @@
5959
android:layout_marginTop="@dimen/experimentalOmnibarCardMarginTop"
6060
android:layout_marginBottom="@dimen/experimentalOmnibarCardMarginBottom"
6161
app:strokeColor="?daxColorAccentBlue"
62-
app:strokeWidth="@dimen/experimentalOmnibarOutlineWidth"
63-
android:transitionName="omnibar_transition">
62+
app:strokeWidth="@dimen/experimentalOmnibarOutlineWidth">
6463

6564
<androidx.constraintlayout.widget.ConstraintLayout
6665
android:id="@+id/omniBarContentContainer"

app/src/main/res/layout/view_single_omnibar.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,6 @@
6565
style="@style/Widget.DuckDuckGo.OmnibarCardView"
6666
android:layout_width="match_parent"
6767
android:layout_height="match_parent"
68-
android:transitionName="omnibar_transition"
6968
app:cardElevation="0dp"
7069
app:strokeColor="?daxColorAccentBlue"
7170
app:strokeWidth="@dimen/experimentalOmnibarOutlineWidth">
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!--
2+
~ Copyright (c) 2025 DuckDuckGo
3+
~
4+
~ Licensed under the Apache License, Version 2.0 (the "License");
5+
~ you may not use this file except in compliance with the License.
6+
~ You may obtain a copy of the License at
7+
~
8+
~ http://www.apache.org/licenses/LICENSE-2.0
9+
~
10+
~ Unless required by applicable law or agreed to in writing, software
11+
~ distributed under the License is distributed on an "AS IS" BASIS,
12+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
~ See the License for the specific language governing permissions and
14+
~ limitations under the License.
15+
-->
16+
17+
<overshootInterpolator
18+
xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:tension="1.0" />
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright (c) 2025 DuckDuckGo
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<set xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:duration="300"
20+
android:interpolator="@anim/overshoot_interpolator_tension_1">
21+
22+
<translate
23+
android:fromYDelta="56dp"
24+
android:toYDelta="0dp" />
25+
26+
<alpha
27+
android:fromAlpha="0.0"
28+
android:toAlpha="1.0" />
29+
30+
</set>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright (c) 2025 DuckDuckGo
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<set xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:duration="300"
20+
android:interpolator="@anim/overshoot_interpolator_tension_1">
21+
22+
<translate
23+
android:fromYDelta="-56dp"
24+
android:toYDelta="0dp" />
25+
26+
<alpha
27+
android:fromAlpha="0.0"
28+
android:toAlpha="1.0" />
29+
30+
</set>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright (c) 2025 DuckDuckGo
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<set xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:duration="300"
20+
android:interpolator="@anim/overshoot_interpolator_tension_1">
21+
22+
<translate
23+
android:fromYDelta="0dp"
24+
android:toYDelta="56dp" />
25+
26+
<alpha
27+
android:fromAlpha="1.0"
28+
android:toAlpha="0.0" />
29+
30+
</set>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
~ Copyright (c) 2025 DuckDuckGo
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
18+
<set xmlns:android="http://schemas.android.com/apk/res/android"
19+
android:duration="300"
20+
android:interpolator="@anim/overshoot_interpolator_tension_1">
21+
22+
<translate
23+
android:fromYDelta="0dp"
24+
android:toYDelta="-56dp" />
25+
26+
<alpha
27+
android:fromAlpha="1.0"
28+
android:toAlpha="0.0" />
29+
30+
</set>

duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/inputscreen/ui/InputScreenActivity.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616

1717
package com.duckduckgo.duckchat.impl.inputscreen.ui
1818

19+
import android.os.Build.VERSION
1920
import android.os.Bundle
20-
import android.transition.ChangeBounds
21-
import android.view.animation.OvershootInterpolator
2221
import com.duckduckgo.anvil.annotations.ContributeToActivityStarter
2322
import com.duckduckgo.anvil.annotations.InjectWith
2423
import com.duckduckgo.common.ui.DuckDuckGoActivity
2524
import com.duckduckgo.di.scopes.ActivityScope
2625
import com.duckduckgo.duckchat.impl.R
26+
import com.duckduckgo.mobile.android.R as CommonR
2727
import com.duckduckgo.navigation.api.GlobalActivityStarter
2828

2929
data class InputScreenActivityParams(
@@ -37,24 +37,31 @@ class InputScreenActivity : DuckDuckGoActivity() {
3737
override fun onCreate(savedInstanceState: Bundle?) {
3838
super.onCreate(savedInstanceState)
3939
setContentView(R.layout.activity_input_screen)
40+
}
4041

41-
val transition = ChangeBounds().apply {
42-
duration = TRANSITION_DURATION
43-
interpolator = OvershootInterpolator(TRANSITION_INTERPOLATOR_TENSION)
44-
}
42+
override fun finish() {
43+
super.finish()
44+
applyExitTransition()
45+
}
4546

46-
window.apply {
47-
sharedElementEnterTransition = transition
48-
sharedElementReturnTransition = transition
47+
private fun applyExitTransition() {
48+
if (VERSION.SDK_INT >= 34) {
49+
overrideActivityTransition(
50+
OVERRIDE_TRANSITION_CLOSE,
51+
CommonR.anim.slide_in_from_bottom_fade_in,
52+
CommonR.anim.slide_out_to_top_fade_out,
53+
)
54+
} else {
55+
overridePendingTransition(
56+
CommonR.anim.slide_in_from_bottom_fade_in,
57+
CommonR.anim.slide_out_to_top_fade_out,
58+
)
4959
}
5060
}
5161

5262
companion object {
5363
// TODO: This is in an :impl module and accessed directly from :app module, it should be moved to an API
5464
const val QUERY = "query"
5565
const val TAB_ID = "tab_id"
56-
57-
const val TRANSITION_DURATION = 300L
58-
const val TRANSITION_INTERPOLATOR_TENSION = 1F
5966
}
6067
}

duckchat/duckchat-impl/src/main/java/com/duckduckgo/duckchat/impl/inputscreen/ui/tabs/SearchTabFragment.kt

Lines changed: 5 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ package com.duckduckgo.duckchat.impl.inputscreen.ui.tabs
1818

1919
import android.os.Build.VERSION
2020
import android.os.Bundle
21-
import android.transition.Transition
2221
import android.view.View
2322
import android.view.View.OVER_SCROLL_NEVER
2423
import android.view.ViewTreeObserver
25-
import android.view.animation.OvershootInterpolator
2624
import androidx.core.content.ContextCompat
2725
import androidx.core.view.isVisible
2826
import androidx.lifecycle.ViewModelProvider
@@ -66,30 +64,17 @@ class SearchTabFragment : DuckDuckGoFragment(R.layout.fragment_search_tab) {
6664
private lateinit var autoCompleteSuggestionsAdapter: BrowserAutoCompleteSuggestionsAdapter
6765

6866
private val binding: FragmentSearchTabBinding by viewBinding()
69-
private lateinit var favoritesView: View
7067

7168
override fun onViewCreated(
7269
view: View,
7370
savedInstanceState: Bundle?,
7471
) {
7572
super.onViewCreated(view, savedInstanceState)
7673

77-
requireActivity().window.sharedElementEnterTransition?.addListener(
78-
object : Transition.TransitionListener {
79-
override fun onTransitionEnd(transition: Transition) {
80-
configureFavorites()
81-
configureAutoComplete()
82-
configureObservers()
83-
configureBottomBlur()
84-
transition.removeListener(this)
85-
}
86-
87-
override fun onTransitionStart(transition: Transition) {}
88-
override fun onTransitionCancel(transition: Transition) {}
89-
override fun onTransitionPause(transition: Transition) {}
90-
override fun onTransitionResume(transition: Transition) {}
91-
},
92-
)
74+
configureFavorites()
75+
configureAutoComplete()
76+
configureObservers()
77+
configureBottomBlur()
9378
}
9479

9580
private fun configureBottomBlur() {
@@ -116,25 +101,8 @@ class SearchTabFragment : DuckDuckGoFragment(R.layout.fragment_search_tab) {
116101
showPlaceholders = false,
117102
placement = FavoritesPlacement.FOCUSED_STATE,
118103
)
119-
favoritesView = savedSitesViewsProvider.getFavoritesGridView(requireContext(), config = favoritesGridConfig)
120-
favoritesView.alpha = 0f
121-
122-
val displayMetrics = requireContext().resources.displayMetrics
123-
val slideDistance = displayMetrics.heightPixels * CONTENT_SLIDE_DISTANCE
124-
favoritesView.translationY = -slideDistance
125-
104+
val favoritesView = savedSitesViewsProvider.getFavoritesGridView(requireContext(), config = favoritesGridConfig)
126105
binding.contentContainer.addView(favoritesView)
127-
128-
favoritesView.animate()
129-
.alpha(1f)
130-
.setDuration(CONTENT_ANIMATION_DURATION)
131-
.start()
132-
133-
favoritesView.animate()
134-
.translationY(0f)
135-
.setInterpolator(OvershootInterpolator(CONTENT_INTERPOLATOR_TENSION))
136-
.setDuration(CONTENT_ANIMATION_DURATION)
137-
.start()
138106
}
139107

140108
private fun configureAutoComplete() {
@@ -182,10 +150,4 @@ class SearchTabFragment : DuckDuckGoFragment(R.layout.fragment_search_tab) {
182150
autoCompleteSuggestionsAdapter.updateData(it.query, it.suggestions)
183151
}.launchIn(lifecycleScope)
184152
}
185-
186-
companion object {
187-
private const val CONTENT_ANIMATION_DURATION = 500L
188-
private const val CONTENT_INTERPOLATOR_TENSION = 1F
189-
private const val CONTENT_SLIDE_DISTANCE = 0.05F
190-
}
191153
}

0 commit comments

Comments
 (0)