diff --git a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/AppComponentsPagerAdapter.kt b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/AppComponentsPagerAdapter.kt index c550ec4b3215..8971acd18b24 100644 --- a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/AppComponentsPagerAdapter.kt +++ b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/AppComponentsPagerAdapter.kt @@ -24,6 +24,7 @@ import com.duckduckgo.mobile.android.R import com.duckduckgo.mobile.android.themepreview.ui.component.ComponentOtherFragment import com.duckduckgo.mobile.android.themepreview.ui.component.buttons.ComponentButtonsFragment import com.duckduckgo.mobile.android.themepreview.ui.component.buttons.ComponentInteractiveElementsFragment +import com.duckduckgo.mobile.android.themepreview.ui.component.cards.ComponentCardsFragment import com.duckduckgo.mobile.android.themepreview.ui.component.listitems.ComponentListItemsElementsFragment import com.duckduckgo.mobile.android.themepreview.ui.component.navigation.ComponentMessagingFragment import com.duckduckgo.mobile.android.themepreview.ui.component.textinput.ComponentTextInputFragment @@ -44,6 +45,7 @@ class AppComponentsPagerAdapter( BUTTONS(R.string.tab_title_buttons), TEXT_INPUT(R.string.tab_title_text_input), DIALOGS(R.string.tab_title_dialogs), + CARDS(R.string.tab_title_cards), INTERACTIVE_ELEMENTS(R.string.tab_title_component_interactive), MESSAGING(R.string.tab_title_component_messaging), LIST_ITEMS(R.string.tab_title_component_list_items), @@ -67,6 +69,7 @@ class AppComponentsPagerAdapter( MainFragments.BUTTONS -> ComponentButtonsFragment() MainFragments.TEXT_INPUT -> ComponentTextInputFragment() MainFragments.DIALOGS -> DialogsFragment() + MainFragments.CARDS -> ComponentCardsFragment() MainFragments.INTERACTIVE_ELEMENTS -> ComponentInteractiveElementsFragment() MainFragments.MESSAGING -> ComponentMessagingFragment() MainFragments.LIST_ITEMS -> ComponentListItemsElementsFragment() diff --git a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/ComponentViewHolder.kt b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/ComponentViewHolder.kt index f758175f3095..2337060fd6a3 100644 --- a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/ComponentViewHolder.kt +++ b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/ComponentViewHolder.kt @@ -27,6 +27,9 @@ import com.duckduckgo.mobile.android.R import com.duckduckgo.mobile.android.ui.view.listitem.OneLineListItem import com.duckduckgo.mobile.android.ui.view.listitem.SectionHeaderListItem import com.duckduckgo.mobile.android.ui.view.listitem.TwoLineListItem +import com.google.android.material.card.MaterialCardView +import com.google.android.material.shape.ShapeAppearanceModel +import com.google.android.material.shape.TriangleEdgeTreatment import com.google.android.material.snackbar.Snackbar sealed class ComponentViewHolder(val view: View) : RecyclerView.ViewHolder(view) { @@ -202,6 +205,23 @@ sealed class ComponentViewHolder(val view: View) : RecyclerView.ViewHolder(view) class DividerComponentViewHolder(parent: ViewGroup) : ComponentViewHolder(inflate(parent, R.layout.component_section_divider)) + class CardComponentViewHolder(parent: ViewGroup) : ComponentViewHolder(inflate(parent, R.layout.component_card)) { + override fun bind(component: Component) { + view.findViewById(R.id.ticketViewCard).apply { + val cornerSize = resources.getDimension(R.dimen.smallShapeCornerRadius) + val edgeTreatment = TriangleEdgeTreatment(cornerSize, true) + shapeAppearanceModel = ShapeAppearanceModel.Builder() + .setLeftEdge(edgeTreatment) + .setRightEdge(edgeTreatment) + .setAllCornerSizes(cornerSize) + .build() + elevation = 8f + + setOnClickListener { Snackbar.make(this, component.name, Snackbar.LENGTH_SHORT).show() } + } + } + } + companion object { fun create( parent: ViewGroup, @@ -222,6 +242,7 @@ sealed class ComponentViewHolder(val view: View) : RecyclerView.ViewHolder(view) Component.SINGLE_LINE_LIST_ITEM -> OneLineListItemComponentViewHolder(parent) Component.TWO_LINE_LIST_ITEM -> TwoLineItemComponentViewHolder(parent) Component.SECTION_DIVIDER -> DividerComponentViewHolder(parent) + Component.CARD -> CardComponentViewHolder(parent) else -> { TODO() } diff --git a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/buttons/ComponentInteractiveElementsFragment.kt b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/buttons/ComponentInteractiveElementsFragment.kt index 8e35be674988..04d8afd36170 100644 --- a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/buttons/ComponentInteractiveElementsFragment.kt +++ b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/buttons/ComponentInteractiveElementsFragment.kt @@ -22,7 +22,6 @@ import com.duckduckgo.mobile.android.themepreview.ui.component.ComponentFragment class ComponentInteractiveElementsFragment : ComponentFragment() { override fun getComponents(): List { return listOf( - Component.TOP_APP_BAR, Component.SWITCH, Component.RADIO_BUTTON, Component.CHECKBOX, diff --git a/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/cards/ComponentCardsFragment.kt b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/cards/ComponentCardsFragment.kt new file mode 100644 index 000000000000..38fdd935a42a --- /dev/null +++ b/common-ui/src/main/java/com/duckduckgo/mobile/android/themepreview/ui/component/cards/ComponentCardsFragment.kt @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2021 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.mobile.android.themepreview.ui.component.cards + +import com.duckduckgo.mobile.android.themepreview.ui.component.Component +import com.duckduckgo.mobile.android.themepreview.ui.component.ComponentFragment + +class ComponentCardsFragment : ComponentFragment() { + override fun getComponents(): List { + return listOf(Component.CARD) + } +} diff --git a/common-ui/src/main/java/com/duckduckgo/mobile/android/ui/view/shape/DaxBubbleCardView.kt b/common-ui/src/main/java/com/duckduckgo/mobile/android/ui/view/shape/DaxBubbleCardView.kt new file mode 100644 index 000000000000..db1eb0ae810a --- /dev/null +++ b/common-ui/src/main/java/com/duckduckgo/mobile/android/ui/view/shape/DaxBubbleCardView.kt @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022 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.mobile.android.ui.view.shape + +import android.content.Context +import android.content.res.ColorStateList +import android.util.AttributeSet +import com.duckduckgo.mobile.android.R +import com.duckduckgo.mobile.android.ui.view.getColorFromAttr +import com.google.android.material.card.MaterialCardView +import com.google.android.material.shape.MaterialShapeDrawable +import com.google.android.material.shape.ShapeAppearanceModel + +class DaxBubbleCardView +@JvmOverloads +constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = R.attr.cardViewStyle, +) : MaterialCardView(context, attrs, defStyleAttr) { + + init { + val cornderRadius = resources.getDimension(R.dimen.mediumShapeCornerRadius) + val cornerSize = resources.getDimension(R.dimen.daxBubbleDialogEdge) + val distanceFromEdge = resources.getDimension(R.dimen.daxBubbleDialogDistanceFromEdge) + val edgeTreatment = DaxBubbleEdgeTreatment(cornerSize, distanceFromEdge) + + background = MaterialShapeDrawable( + ShapeAppearanceModel.builder() + .setAllCornerSizes(cornderRadius) + .setTopEdge(edgeTreatment) + .build(), + ).apply { + fillColor = ColorStateList.valueOf(context.getColorFromAttr(R.attr.daxColorSurface)) + } + } +} diff --git a/common-ui/src/main/java/com/duckduckgo/mobile/android/ui/view/shape/Shapes.kt b/common-ui/src/main/java/com/duckduckgo/mobile/android/ui/view/shape/Shapes.kt new file mode 100644 index 000000000000..3b179817cc0b --- /dev/null +++ b/common-ui/src/main/java/com/duckduckgo/mobile/android/ui/view/shape/Shapes.kt @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2022 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.mobile.android.ui.view.shape + +import com.google.android.material.shape.CornerFamily +import com.google.android.material.shape.EdgeTreatment +import com.google.android.material.shape.MaterialShapeDrawable +import com.google.android.material.shape.ShapeAppearanceModel +import com.google.android.material.shape.ShapePath + +class DaxBubbleEdgeTreatment +/** + * Instantiates a triangle treatment of the given size, which faces inward or outward relative to + * the shape. + * + * @param size the length in pixels that the triangle extends into or out of the shape. The length + * of the side of the triangle coincident with the rest of the edge is 2 * size. + * @param inside true if the triangle should be "cut out" of the shape (i.e. inward-facing); false + * if the triangle should extend out of the shape. + */( + private val size: Float, + private val distanceFromEdge: Float, +) : EdgeTreatment() { + override fun getEdgePath( + length: Float, + center: Float, + interpolation: Float, + shapePath: ShapePath, + ) { + shapePath.lineTo(distanceFromEdge - size * interpolation, 0f) + shapePath.lineTo(distanceFromEdge, -size * interpolation) + shapePath.lineTo(distanceFromEdge + size * interpolation, 0f) + shapePath.lineTo(length, 0f) + } +} + +class TicketEdgeTreatment( + private val size: Float, +) : EdgeTreatment() { + override fun getEdgePath( + length: Float, + center: Float, + interpolation: Float, + shapePath: ShapePath, + ) { + val circleRadius = size * interpolation + shapePath.lineTo(center - circleRadius, 0f) + shapePath.addArc( + center - circleRadius, + -circleRadius, + center + circleRadius, + circleRadius, + 180f, + -180f, + ) + shapePath.lineTo(length, 0f) + } +} + +val ticketShapePathModel = ShapeAppearanceModel + .Builder() + .setAllCorners(CornerFamily.ROUNDED, 36f) + .setLeftEdge(TicketEdgeTreatment(36f)) + .setRightEdge(TicketEdgeTreatment(36f)) + .build() + +class TicketDrawable : MaterialShapeDrawable(ticketShapePathModel) diff --git a/common-ui/src/main/res/layout/component_card.xml b/common-ui/src/main/res/layout/component_card.xml new file mode 100644 index 000000000000..8962b362a08d --- /dev/null +++ b/common-ui/src/main/res/layout/component_card.xml @@ -0,0 +1,93 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/common-ui/src/main/res/layout/view_dax_dialog.xml b/common-ui/src/main/res/layout/view_dax_dialog.xml index 728a4a0e124e..ca6a3b866a57 100644 --- a/common-ui/src/main/res/layout/view_dax_dialog.xml +++ b/common-ui/src/main/res/layout/view_dax_dialog.xml @@ -38,8 +38,7 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@color/dimmed" - app:layout_constraintTop_toTopOf="@id/hideText"/> - + app:layout_constraintTop_toTopOf="@id/hideText" tools:layout_editor_absoluteX="0dp"/> + + + + + + diff --git a/common-ui/src/main/res/values/design-system-dimensions.xml b/common-ui/src/main/res/values/design-system-dimensions.xml index 10257d83e9b4..0dda360eead6 100644 --- a/common-ui/src/main/res/values/design-system-dimensions.xml +++ b/common-ui/src/main/res/values/design-system-dimensions.xml @@ -89,4 +89,8 @@ 16dp + + + 40dp + 9dp \ No newline at end of file diff --git a/common-ui/src/main/res/values/design-system-theming.xml b/common-ui/src/main/res/values/design-system-theming.xml index 52ddb47f99bc..8f0e8b3f2de3 100644 --- a/common-ui/src/main/res/values/design-system-theming.xml +++ b/common-ui/src/main/res/values/design-system-theming.xml @@ -80,6 +80,7 @@ @style/Widget.DuckDuckGo.DaxButton.TextButton.Primary @style/Widget.DuckDuckGo.DaxButton.Secondary @style/Widget.DuckDuckGo.DaxButton.Ghost + @style/Widget.DuckDuckGo.CardView @style/Widget.DuckDuckGo.DaxButton.TextButton.Primary @@ -97,8 +98,11 @@ @style/Widget.DuckDuckGo.Button.Rounded @style/Widget.DuckDuckGo.Button.Secondary.Rounded @style/Widget.DuckDuckGo.Button.Primary.Lowercase + @style/Widget.DuckDuckGo.OneLineListItem @style/Widget.DuckDuckGo.TwoLineListItem + + @style/Widget.DuckDuckGo.CardView + + + + \ No newline at end of file