diff --git a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt
index 74bea9cd936c..62ba290ef757 100644
--- a/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt
+++ b/app/src/main/java/com/duckduckgo/app/browser/BrowserTabFragment.kt
@@ -110,6 +110,7 @@ import com.duckduckgo.app.browser.api.WebViewCapabilityChecker.WebViewCapability
import com.duckduckgo.app.browser.applinks.AppLinksLauncher
import com.duckduckgo.app.browser.applinks.AppLinksSnackBarConfigurator
import com.duckduckgo.app.browser.autocomplete.BrowserAutoCompleteSuggestionsAdapter
+import com.duckduckgo.app.browser.autocomplete.SuggestionItemDecoration
import com.duckduckgo.app.browser.commands.Command
import com.duckduckgo.app.browser.commands.Command.ShowBackNavigationHistory
import com.duckduckgo.app.browser.commands.NavigationCommand
@@ -2329,6 +2330,9 @@ class BrowserTabFragment :
omnibarPosition = settingsDataStore.omnibarPosition,
)
binding.autoCompleteSuggestionsList.adapter = autoCompleteSuggestionsAdapter
+ binding.autoCompleteSuggestionsList.addItemDecoration(
+ SuggestionItemDecoration(ContextCompat.getDrawable(context, R.drawable.suggestions_divider)!!),
+ )
}
private fun configureNewTab() {
diff --git a/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionItemDecoration.kt b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionItemDecoration.kt
new file mode 100644
index 000000000000..486aaf58b469
--- /dev/null
+++ b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionItemDecoration.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2024 DuckDuckGo
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.duckduckgo.app.browser.autocomplete
+
+import android.graphics.Canvas
+import android.graphics.drawable.Drawable
+import android.view.ViewGroup.MarginLayoutParams
+import androidx.recyclerview.widget.RecyclerView
+
+class SuggestionItemDecoration(private val divider: Drawable) : RecyclerView.ItemDecoration() {
+
+ override fun onDrawOver(
+ canvas: Canvas,
+ parent: RecyclerView,
+ state: RecyclerView.State,
+ ) {
+ canvas.save()
+
+ val childCount = parent.childCount
+ val parentRight = parent.width - parent.paddingRight
+
+ for (i in 0 until childCount) {
+ val child = parent.getChildAt(i)
+ val params = child.layoutParams as MarginLayoutParams
+ val currentViewType = child.tag
+ val nextViewType = if (i + 1 < childCount) parent.getChildAt(i + 1).tag else UNKNOWN
+
+ if (nextViewType == UNKNOWN) {
+ continue
+ }
+
+ if (currentViewType == SEARCH_ITEM && nextViewType == OTHER_ITEM) {
+ drawDivider(canvas, child, params, parentRight)
+ }
+
+ if (currentViewType == OTHER_ITEM && nextViewType == SEARCH_ITEM) {
+ drawDivider(canvas, child, params, parentRight)
+ }
+ }
+
+ canvas.restore()
+ }
+
+ private fun drawDivider(
+ canvas: Canvas,
+ child: android.view.View,
+ params: MarginLayoutParams,
+ parentRight: Int,
+ ) {
+ val horizontalSize = parentRight
+ val verticalSize = child.bottom + params.bottomMargin
+ divider.setBounds(0, verticalSize, horizontalSize, verticalSize + divider.intrinsicHeight)
+ divider.draw(canvas)
+ }
+
+ companion object {
+ internal const val SEARCH_ITEM = "SEARCH_ITEM"
+ internal const val OTHER_ITEM = "OTHER_ITEM"
+ internal const val UNKNOWN = "UNKNOWN"
+ }
+}
diff --git a/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt
index 8c5846037b1a..57d563cdcd82 100644
--- a/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt
+++ b/app/src/main/java/com/duckduckgo/app/browser/autocomplete/SuggestionViewHolderFactory.kt
@@ -29,6 +29,8 @@ import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.A
import com.duckduckgo.app.autocomplete.api.AutoComplete.AutoCompleteSuggestion.AutoCompleteUrlSuggestion.AutoCompleteSwitchToTabSuggestion
import com.duckduckgo.app.browser.R
import com.duckduckgo.app.browser.autocomplete.AutoCompleteViewHolder.InAppMessageViewHolder
+import com.duckduckgo.app.browser.autocomplete.SuggestionItemDecoration.Companion.OTHER_ITEM
+import com.duckduckgo.app.browser.autocomplete.SuggestionItemDecoration.Companion.SEARCH_ITEM
import com.duckduckgo.app.browser.databinding.ItemAutocompleteBookmarkSuggestionBinding
import com.duckduckgo.app.browser.databinding.ItemAutocompleteDefaultBinding
import com.duckduckgo.app.browser.databinding.ItemAutocompleteHistorySuggestionBinding
@@ -269,6 +271,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
if (omnibarPosition == OmnibarPosition.BOTTOM) {
editQueryImage.setImageResource(R.drawable.ic_autocomplete_down_20dp)
}
+
+ root.tag = SEARCH_ITEM
}
}
@@ -294,6 +298,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
if (omnibarPosition == OmnibarPosition.BOTTOM) {
editQueryImage.setImageResource(R.drawable.ic_autocomplete_down_20dp)
}
+
+ root.tag = OTHER_ITEM
}
}
@@ -307,6 +313,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
bookmarkIndicator.setImageResource(if (item.isFavorite) R.drawable.ic_bookmark_favorite_20 else R.drawable.ic_bookmark_20)
root.setOnClickListener { immediateSearchListener(item) }
+
+ root.tag = OTHER_ITEM
}
}
@@ -324,6 +332,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
longPressClickListener(item)
true
}
+
+ root.tag = OTHER_ITEM
}
}
@@ -336,6 +346,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
url.text = root.context.getString(R.string.autocompleteSwitchToTab, item.phrase.formatIfUrl())
root.setOnClickListener { immediateSearchListener(item) }
+
+ root.tag = OTHER_ITEM
}
}
@@ -353,6 +365,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
if (omnibarPosition == OmnibarPosition.BOTTOM) {
binding.editQueryImage.setImageResource(R.drawable.ic_autocomplete_down_20dp)
}
+
+ binding.root.tag = OTHER_ITEM
}
}
@@ -371,6 +385,8 @@ sealed class AutoCompleteViewHolder(itemView: View) : RecyclerView.ViewHolder(it
)
binding.messageCta.onCloseButtonClicked { deleteClickListener(item) }
binding.messageCta.onPrimaryActionClicked { openSettingsClickListener() }
+
+ binding.root.tag = OTHER_ITEM
}
}
diff --git a/app/src/main/res/drawable/ic_switch_to_tab_20.xml b/app/src/main/res/drawable/ic_switch_to_tab_20.xml
index 052c8511bd82..8860a3f5d23e 100644
--- a/app/src/main/res/drawable/ic_switch_to_tab_20.xml
+++ b/app/src/main/res/drawable/ic_switch_to_tab_20.xml
@@ -5,6 +5,6 @@
android:viewportHeight="20">
diff --git a/app/src/main/res/drawable/suggestions_divider.xml b/app/src/main/res/drawable/suggestions_divider.xml
new file mode 100644
index 000000000000..c111e7320c8f
--- /dev/null
+++ b/app/src/main/res/drawable/suggestions_divider.xml
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file