Skip to content

Commit 4c1fb2f

Browse files
authored
Post visual update: Toolbar shadows (#6697)
Task/Issue URL: https://app.asana.com/1/137249556945/project/1207418217763355/task/1210209951324419?focus=true ### Description This PR updates the toolbar shadows in the browser, NTP and tab switcher. Figma design: https://www.figma.com/design/triNDLtPcx4by8Hsw9CzYt/%F0%9F%96%8D%EF%B8%8F-2025-Visual-Design-Update---1-Tap-AI-ChatOS---Android?node-id=9026-13597&t=SDA77UdXNkaAqBAr-1 ### Steps to test this PR _Browser_ - [x] Set the omnibar position to the top - [x] Load some website - [x] Verify there is a 0.5dp outline below the toolbar (semi-transparent) and above the status bar (solid) that matches the design - [x] Change the omnibar position to the bottom - [x] Verify there is a 0.5dp outline above the toolbar (solid) and below the status bar at the top (semi-transparent) that matches the design _NTP_ - [x] Set the omnibar position to the top - [x] Open a NTP (without favorites) - [x] Verify there is no outline above or below - [x] Add some favorite bookmarks - [x] Open a NTP - [x] Verify there is a 0.5dp outline below the toolbar (semi-transparent) and above the status bar (solid) that matches the design - [x] Change the omnibar position to the bottom - [x] Verify there is a 0.5dp outline above the toolbar (solid) and below the status bar at the top (semi-transparent) that matches the design _Tab switcher_ - [x] Set the omnibar position to the top - [x] Open a tab switcher - [x] Verify there is a 0.5dp outline below the toolbar (semi-transparent) and above the status bar (solid) that matches the design - [x] Change the omnibar position to the bottom - [x] Verify there is a 0.5dp outline above the toolbar (solid) and below the status bar at the top (semi-transparent) that matches the design ### UI changes | Browser | NTP (no favorites) | NTP (w/ favorites) | Tab switcher | | ------ | ----- | ----- | ----- | <img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/1daff0a7-ca6d-41ca-a4c9-9806884ba19f" />|<img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/5771a1be-8ee6-434c-ae73-25ad2b52fc9b" />|<img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/7eec67bf-313f-4eb2-b4c4-2321e2c0852d" />|<img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/76aea94f-9f8e-4e3d-bd16-789c01227521" /> <img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/b5648eff-158c-4518-9cf9-b4a51f665b62" />|<img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/fb64aa56-52ca-4105-9b4c-4bf1976574b6" />|<img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/3785babd-23b5-4eee-b977-430b87bc72da" />|<img width="250" height="2400" alt="image" src="https://github.com/user-attachments/assets/c2e5ff5b-fe80-4f6d-ab7c-12b218ba0186" />
1 parent 344a3ce commit 4c1fb2f

File tree

16 files changed

+127
-55
lines changed

16 files changed

+127
-55
lines changed

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

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import androidx.activity.OnBackPressedCallback
3434
import androidx.activity.result.ActivityResult
3535
import androidx.activity.result.contract.ActivityResultContracts
3636
import androidx.annotation.VisibleForTesting
37-
import androidx.core.content.ContextCompat
3837
import androidx.core.view.isVisible
3938
import androidx.core.view.postDelayed
4039
import androidx.lifecycle.Lifecycle.State.STARTED
@@ -1332,12 +1331,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
13321331
}
13331332

13341333
if (Build.VERSION.SDK_INT >= 28) {
1335-
omnibarToolbarMockupBinding.mockOmniBarContainerShadow.addBottomShadow(
1336-
shadowSizeDp = 12f,
1337-
offsetYDp = 3f,
1338-
insetDp = 3f,
1339-
shadowColor = ContextCompat.getColor(this, com.duckduckgo.mobile.android.R.color.background_omnibar_shadow),
1340-
)
1334+
omnibarToolbarMockupBinding.mockOmniBarContainerShadow.addBottomShadow()
13411335
}
13421336
}
13431337

@@ -1354,12 +1348,7 @@ open class BrowserActivity : DuckDuckGoActivity() {
13541348
}
13551349

13561350
if (Build.VERSION.SDK_INT >= 28) {
1357-
omnibarToolbarMockupBottomBinding.mockOmniBarContainerShadow.addBottomShadow(
1358-
shadowSizeDp = 12f,
1359-
offsetYDp = 3f,
1360-
insetDp = 3f,
1361-
shadowColor = ContextCompat.getColor(this, com.duckduckgo.mobile.android.R.color.background_omnibar_shadow),
1362-
)
1351+
omnibarToolbarMockupBottomBinding.mockOmniBarContainerShadow.addBottomShadow()
13631352
}
13641353
}
13651354
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,6 +1536,15 @@ class BrowserTabFragment :
15361536
},
15371537
)
15381538

1539+
lifecycleScope.launch {
1540+
viewModel.areFavoritesDisplayed
1541+
.flowWithLifecycle(lifecycle, Lifecycle.State.RESUMED)
1542+
.collectLatest { hasFavorites ->
1543+
binding.includeNewBrowserTab.topNtpOutlineStroke.isVisible = hasFavorites
1544+
binding.includeNewBrowserTab.bottomNtpOutlineStroke.isVisible = hasFavorites
1545+
}
1546+
}
1547+
15391548
addTabsObserver()
15401549
}
15411550

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,7 @@ import kotlinx.coroutines.async
370370
import kotlinx.coroutines.delay
371371
import kotlinx.coroutines.flow.Flow
372372
import kotlinx.coroutines.flow.MutableStateFlow
373+
import kotlinx.coroutines.flow.SharingStarted
373374
import kotlinx.coroutines.flow.asStateFlow
374375
import kotlinx.coroutines.flow.catch
375376
import kotlinx.coroutines.flow.combine
@@ -383,6 +384,8 @@ import kotlinx.coroutines.flow.flowOn
383384
import kotlinx.coroutines.flow.launchIn
384385
import kotlinx.coroutines.flow.map
385386
import kotlinx.coroutines.flow.onEach
387+
import kotlinx.coroutines.flow.stateIn
388+
import kotlinx.coroutines.flow.update
386389
import kotlinx.coroutines.launch
387390
import kotlinx.coroutines.withContext
388391
import logcat.LogPriority.ERROR
@@ -507,6 +510,9 @@ class BrowserTabViewModel @Inject constructor(
507510
var siteLiveData: MutableLiveData<Site> = MutableLiveData()
508511
val privacyShieldViewState: MutableLiveData<PrivacyShieldViewState> = MutableLiveData()
509512
val buckTryASearchAnimationEnabled: MutableStateFlow<Boolean> = MutableStateFlow(false)
513+
val areFavoritesDisplayed = savedSitesRepository.getFavorites()
514+
.map { it.isNotEmpty() }
515+
.stateIn(viewModelScope, SharingStarted.Lazily, false)
510516

511517
// if navigating from home, want to know if a site was loaded previously to decide whether to reset WebView
512518
private var returnedHomeAfterSiteLoaded = false

app/src/main/java/com/duckduckgo/app/browser/omnibar/SingleOmnibarLayout.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import android.view.View
2424
import android.view.ViewGroup
2525
import android.view.ViewTreeObserver.OnGlobalLayoutListener
2626
import android.widget.ImageView
27-
import androidx.core.content.ContextCompat
2827
import androidx.core.view.isGone
2928
import androidx.core.view.isVisible
3029
import androidx.core.view.updateLayoutParams
@@ -99,12 +98,7 @@ class SingleOmnibarLayout @JvmOverloads constructor(
9998
AndroidSupportInjection.inject(this)
10099

101100
if (Build.VERSION.SDK_INT >= 28) {
102-
omnibarCardShadow.addBottomShadow(
103-
shadowSizeDp = 12f,
104-
offsetYDp = 3f,
105-
insetDp = 3f,
106-
shadowColor = ContextCompat.getColor(context, CommonR.color.background_omnibar_shadow),
107-
)
101+
omnibarCardShadow.addBottomShadow()
108102
}
109103

110104
when (omnibarPosition) {

app/src/main/java/com/duckduckgo/app/tabs/ui/TabSwitcherActivity.kt

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import android.view.Menu
2424
import android.view.MenuItem
2525
import android.view.MotionEvent
2626
import android.view.View
27+
import android.widget.FrameLayout
2728
import androidx.activity.OnBackPressedCallback
2829
import androidx.appcompat.app.AppCompatDelegate.FEATURE_SUPPORT_ACTION_BAR
2930
import androidx.appcompat.widget.Toolbar
@@ -202,6 +203,7 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine
202203

203204
private lateinit var tabTouchHelper: TabTouchHelper
204205
private lateinit var tabsRecycler: RecyclerView
206+
private lateinit var tabsContainer: FrameLayout
205207
private lateinit var tabItemDecorator: TabItemDecorator
206208
private lateinit var toolbar: Toolbar
207209

@@ -293,6 +295,8 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine
293295
}
294296

295297
toolbar = findViewById(R.id.toolbar)
298+
299+
tabsContainer = findViewById(R.id.tabsContainer)
296300
}
297301

298302
private fun configureRecycler() {
@@ -328,7 +332,7 @@ class TabSwitcherActivity : DuckDuckGoActivity(), TabSwitcherListener, Coroutine
328332

329333
if (viewModel.isNewToolbarEnabled) {
330334
// Set the layout params for the tabs recycler view based on omnibar position
331-
tabsRecycler.updateLayoutParams {
335+
tabsContainer.updateLayoutParams {
332336
this as CoordinatorLayout.LayoutParams
333337
this.behavior = null
334338
if (settingsDataStore.omnibarPosition == OmnibarPosition.TOP) {

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

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,39 @@
3333
android:layout_width="match_parent"
3434
android:layout_height="wrap_content" />
3535

36-
<androidx.recyclerview.widget.RecyclerView
37-
android:id="@+id/tabsRecycler"
36+
<FrameLayout
37+
android:id="@+id/tabsContainer"
3838
android:layout_width="match_parent"
3939
android:layout_height="match_parent"
40-
android:clipToPadding="false"
41-
android:padding="@dimen/keyline_2"
42-
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
43-
app:layout_behavior="@string/appbar_scrolling_view_behavior"
44-
tools:itemCount="3"
45-
tools:listitem="@layout/item_tab_grid"
46-
tools:showIn="@layout/activity_tab_switcher"
47-
tools:spanCount="2" />
40+
android:elevation="10dp"
41+
app:layout_behavior="@string/appbar_scrolling_view_behavior">
42+
43+
<View
44+
android:layout_width="match_parent"
45+
android:layout_height="0.5dp"
46+
android:background="?attr/daxColorShade"
47+
android:layout_gravity="top"
48+
android:elevation="20dp" />
49+
50+
<androidx.recyclerview.widget.RecyclerView
51+
android:id="@+id/tabsRecycler"
52+
android:layout_width="match_parent"
53+
android:layout_height="match_parent"
54+
android:clipToPadding="false"
55+
android:padding="@dimen/keyline_2"
56+
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
57+
tools:itemCount="3"
58+
tools:listitem="@layout/item_tab_grid"
59+
tools:showIn="@layout/activity_tab_switcher"
60+
tools:spanCount="2" />
61+
62+
<View
63+
android:layout_width="match_parent"
64+
android:layout_height="0.5dp"
65+
android:background="?attr/daxColorShadeSolid"
66+
android:layout_gravity="bottom" />
67+
68+
</FrameLayout>
4869

4970
<com.google.android.material.floatingactionbutton.FloatingActionButton
5071
android:id="@+id/aiChatFab"

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

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
android:id="@+id/singleOmnibar"
2525
android:layout_width="match_parent"
2626
android:layout_height="wrap_content"
27+
android:background="@android:color/transparent"
28+
android:elevation="1dp"
29+
android:outlineProvider="none"
2730
app:omnibarPosition="top" />
2831

2932
<FrameLayout
@@ -81,6 +84,14 @@
8184
app:layout_behavior="com.duckduckgo.app.browser.webview.TopOmnibarBrowserContainerLayoutBehavior"
8285
tools:context="com.duckduckgo.app.browser.BrowserActivity">
8386

87+
<View
88+
android:id="@+id/topBrowserOutlineStroke"
89+
android:layout_width="match_parent"
90+
android:layout_height="0.5dp"
91+
android:background="?attr/daxColorShade"
92+
android:elevation="20dp"
93+
android:layout_alignParentTop="true" />
94+
8495
<FrameLayout
8596
android:id="@+id/daxDialogOnboardingCtaContent"
8697
android:layout_width="match_parent"
@@ -140,12 +151,21 @@
140151
android:layout_below="@id/daxDialogOnboardingCtaContent"
141152
android:focusableInTouchMode="true" />
142153

154+
<View
155+
android:id="@+id/bottomBrowserOutlineStroke"
156+
android:layout_width="match_parent"
157+
android:layout_height="0.5dp"
158+
android:background="?attr/daxColorShadeSolid"
159+
android:elevation="1dp"
160+
android:layout_alignParentBottom="true" />
161+
143162
</RelativeLayout>
144163

145164
<com.duckduckgo.app.browser.omnibar.SingleOmnibarLayout
146165
android:id="@+id/singleOmnibarBottom"
147166
android:layout_width="match_parent"
148167
android:layout_height="wrap_content"
168+
android:outlineProvider="none"
149169
android:layout_gravity="bottom"
150170
app:omnibarPosition="bottom" />
151171

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

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,17 @@
3939
android:layout_height="match_parent"
4040
android:foreground="@android:color/transparent">
4141

42+
<View
43+
android:id="@+id/topNtpOutlineStroke"
44+
android:layout_width="match_parent"
45+
android:layout_height="0.5dp"
46+
android:background="?attr/daxColorShade"
47+
android:elevation="20dp"
48+
android:visibility="gone"
49+
app:layout_constraintStart_toStartOf="parent"
50+
app:layout_constraintTop_toTopOf="parent"
51+
app:layout_constraintEnd_toEndOf="parent" />
52+
4253
<androidx.core.widget.NestedScrollView
4354
android:id="@+id/newTabContainerScrollView"
4455
android:fillViewport="true"
@@ -52,6 +63,16 @@
5263

5364
</androidx.core.widget.NestedScrollView>
5465

66+
<View
67+
android:id="@+id/bottomNtpOutlineStroke"
68+
android:layout_width="match_parent"
69+
android:layout_height="0.5dp"
70+
android:background="?attr/daxColorShadeSolid"
71+
android:visibility="gone"
72+
app:layout_constraintStart_toStartOf="parent"
73+
app:layout_constraintBottom_toBottomOf="parent"
74+
app:layout_constraintEnd_toEndOf="parent" />
75+
5576
<include
5677
android:id="@+id/includeOnboardingDaxDialogBubble"
5778
layout="@layout/include_onboarding_bubble_dax_dialog"

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
android:layout_width="match_parent"
3030
android:layout_height="wrap_content"
3131
android:orientation="vertical"
32+
android:background="@android:color/transparent"
3233
app:layout_scrollFlags="scroll|enterAlways|snap">
3334

3435
<androidx.constraintlayout.widget.ConstraintLayout
@@ -271,7 +272,7 @@
271272
android:scaleType="center"
272273
android:visibility="gone"
273274
app:layout_constraintBottom_toBottomOf="parent"
274-
app:layout_constraintEnd_toStartOf="@+id/verticalDivider"
275+
app:layout_constraintEnd_toStartOf="@id/verticalDivider"
275276
app:layout_constraintTop_toTopOf="parent"
276277
app:srcCompat="@drawable/ic_microphone_24"
277278
tools:visibility="visible" />

common/common-ui/src/main/java/com/duckduckgo/common/ui/view/ViewExtension.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,10 @@ private inline fun <reified T : ViewGroup.LayoutParams> updateLayoutParam(
264264
*/
265265
@RequiresApi(28)
266266
fun View.addBottomShadow(
267-
shadowSizeDp: Float,
268-
offsetYDp: Float = 2f,
269-
insetDp: Float = 0f,
270-
@ColorInt shadowColor: Int,
267+
shadowSizeDp: Float = 12f,
268+
offsetYDp: Float = 3f,
269+
insetDp: Float = 3f,
270+
@ColorInt shadowColor: Int = ContextCompat.getColor(context, com.duckduckgo.mobile.android.R.color.background_omnibar_shadow),
271271
) {
272272
val shadowSize = shadowSizeDp.toPx(context)
273273
val offsetY = offsetYDp.toPx(context)

0 commit comments

Comments
 (0)