[fenix] For https://github.com/mozilla-mobile/fenix/issues/24333 - Replace the xml based CollectionViewHolder with a composable
parent
d92adcff12
commit
7185eee3df
@ -0,0 +1,226 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.home.collections
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.clickable
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.height
|
||||||
|
import androidx.compose.foundation.layout.padding
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.Card
|
||||||
|
import androidx.compose.material.Icon
|
||||||
|
import androidx.compose.material.IconButton
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
|
import androidx.compose.runtime.remember
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.BlendMode
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.Paint
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.painterResource
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.semantics.semantics
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import mozilla.components.browser.state.state.recover.RecoverableTab
|
||||||
|
import mozilla.components.concept.engine.Engine
|
||||||
|
import mozilla.components.feature.tab.collections.Tab
|
||||||
|
import mozilla.components.feature.tab.collections.TabCollection
|
||||||
|
import org.mozilla.fenix.R.drawable
|
||||||
|
import org.mozilla.fenix.R.string
|
||||||
|
import org.mozilla.fenix.compose.list.ExpandableListHeader
|
||||||
|
import org.mozilla.fenix.ext.getIconColor
|
||||||
|
import org.mozilla.fenix.theme.FirefoxTheme
|
||||||
|
import org.mozilla.fenix.theme.Theme
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rectangular shape with all corners rounded used to display a collapsed collection.
|
||||||
|
*/
|
||||||
|
private val collapsedCollectionShape = RoundedCornerShape(8.dp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Rectangular shape with only the top corners rounded used to display an expanded collection with other views
|
||||||
|
* placed immediately below this which can be shown immediately next to it, with no visible separation.
|
||||||
|
*/
|
||||||
|
private val expandedCollectionShape = RoundedCornerShape(topStart = 8.dp, topEnd = 8.dp)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays an individual [TabCollection].
|
||||||
|
*
|
||||||
|
* @param collection [TabCollection] to display.
|
||||||
|
* @param expanded Whether the collection is expanded to show it's containing tabs or not.
|
||||||
|
* @param menuItems List of [CollectionMenuItem] to be shown in a menu.
|
||||||
|
* @param onToggleCollectionExpanded Invoked when the user clicks on the collection.
|
||||||
|
* @param onCollectionShareTabsClicked Invoked when the user clicks to share the collection.
|
||||||
|
* @param onCollectionMenuOpened Invoked when the user clicks to open a menu for the collection.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
@Suppress("LongParameterList")
|
||||||
|
fun Collection(
|
||||||
|
collection: TabCollection,
|
||||||
|
expanded: Boolean,
|
||||||
|
menuItems: List<CollectionMenuItem>,
|
||||||
|
onToggleCollectionExpanded: (TabCollection, Boolean) -> Unit,
|
||||||
|
onCollectionShareTabsClicked: (TabCollection) -> Unit,
|
||||||
|
onCollectionMenuOpened: () -> Unit,
|
||||||
|
) {
|
||||||
|
var isMenuExpanded by remember(collection) { mutableStateOf(false) }
|
||||||
|
val isExpanded by remember(collection) { mutableStateOf(expanded) }
|
||||||
|
|
||||||
|
Card(
|
||||||
|
modifier = Modifier
|
||||||
|
.semantics(mergeDescendants = true) {}
|
||||||
|
.clickable { onToggleCollectionExpanded(collection, !isExpanded) }
|
||||||
|
.height(48.dp),
|
||||||
|
shape = if (isExpanded) expandedCollectionShape else collapsedCollectionShape,
|
||||||
|
backgroundColor = FirefoxTheme.colors.layer2,
|
||||||
|
elevation = 5.dp, // This needs to match the elevation of TabInCollection for matching shadows.
|
||||||
|
) {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight(),
|
||||||
|
verticalAlignment = Alignment.CenterVertically,
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(drawable.ic_tab_collection),
|
||||||
|
contentDescription = null,
|
||||||
|
modifier = Modifier.padding(
|
||||||
|
start = 16.dp,
|
||||||
|
end = 8.dp // (24.dp - 16.dp) hardcoded in ExpandableListHeader
|
||||||
|
),
|
||||||
|
tint = Paint().apply {
|
||||||
|
color = Color(collection.getIconColor(LocalContext.current))
|
||||||
|
blendMode = BlendMode.SrcIn
|
||||||
|
}.color,
|
||||||
|
)
|
||||||
|
|
||||||
|
ExpandableListHeader(
|
||||||
|
headerText = collection.title,
|
||||||
|
expanded = isExpanded,
|
||||||
|
) {
|
||||||
|
if (isExpanded) {
|
||||||
|
Row {
|
||||||
|
IconButton(
|
||||||
|
onClick = { onCollectionShareTabsClicked(collection) }
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(drawable.ic_share),
|
||||||
|
contentDescription = stringResource(string.share_button_content_description),
|
||||||
|
tint = FirefoxTheme.colors.iconPrimary,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
isMenuExpanded = !isMenuExpanded
|
||||||
|
onCollectionMenuOpened()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
painter = painterResource(drawable.ic_menu),
|
||||||
|
contentDescription = stringResource(
|
||||||
|
string.collection_menu_button_content_description
|
||||||
|
),
|
||||||
|
tint = FirefoxTheme.colors.iconPrimary,
|
||||||
|
)
|
||||||
|
|
||||||
|
CollectionMenu(
|
||||||
|
showMenu = isMenuExpanded,
|
||||||
|
menuItems = menuItems,
|
||||||
|
onDismissRequest = { isMenuExpanded = false },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
private fun CollectionDarkPreview() {
|
||||||
|
FirefoxTheme(Theme.Dark) {
|
||||||
|
Collection(
|
||||||
|
collection = collectionPreview,
|
||||||
|
expanded = false,
|
||||||
|
menuItems = emptyList(),
|
||||||
|
onToggleCollectionExpanded = { _, _ -> },
|
||||||
|
onCollectionShareTabsClicked = {},
|
||||||
|
onCollectionMenuOpened = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
private fun CollectionDarkExpandedPreview() {
|
||||||
|
FirefoxTheme(Theme.Dark) {
|
||||||
|
Collection(
|
||||||
|
collection = collectionPreview,
|
||||||
|
expanded = true,
|
||||||
|
menuItems = emptyList(),
|
||||||
|
onToggleCollectionExpanded = { _, _ -> },
|
||||||
|
onCollectionShareTabsClicked = {},
|
||||||
|
onCollectionMenuOpened = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
private fun CollectionLightPreview() {
|
||||||
|
FirefoxTheme(Theme.Light) {
|
||||||
|
Collection(
|
||||||
|
collection = collectionPreview,
|
||||||
|
expanded = false,
|
||||||
|
menuItems = emptyList(),
|
||||||
|
onToggleCollectionExpanded = { _, _ -> },
|
||||||
|
onCollectionShareTabsClicked = {},
|
||||||
|
onCollectionMenuOpened = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
private fun CollectionLightExpandedPreview() {
|
||||||
|
FirefoxTheme(Theme.Light) {
|
||||||
|
Collection(
|
||||||
|
collection = collectionPreview,
|
||||||
|
expanded = true,
|
||||||
|
menuItems = emptyList(),
|
||||||
|
onToggleCollectionExpanded = { _, _ -> },
|
||||||
|
onCollectionShareTabsClicked = {},
|
||||||
|
onCollectionMenuOpened = {},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val collectionPreview = object : TabCollection {
|
||||||
|
override val id: Long = 1L
|
||||||
|
override val tabs: List<Tab> = emptyList()
|
||||||
|
override val title: String = "Collection 1"
|
||||||
|
|
||||||
|
override fun restore(
|
||||||
|
context: Context,
|
||||||
|
engine: Engine,
|
||||||
|
restoreSessionId: Boolean,
|
||||||
|
): List<RecoverableTab> = emptyList()
|
||||||
|
|
||||||
|
override fun restoreSubset(
|
||||||
|
context: Context,
|
||||||
|
engine: Engine,
|
||||||
|
tabs: List<Tab>,
|
||||||
|
restoreSessionId: Boolean,
|
||||||
|
): List<RecoverableTab> = emptyList()
|
||||||
|
}
|
@ -0,0 +1,210 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
package org.mozilla.fenix.home.collections
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.res.Configuration
|
||||||
|
import androidx.compose.foundation.background
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||||
|
import androidx.compose.material.DropdownMenu
|
||||||
|
import androidx.compose.material.DropdownMenuItem
|
||||||
|
import androidx.compose.material.MaterialTheme
|
||||||
|
import androidx.compose.material.Text
|
||||||
|
import androidx.compose.runtime.Composable
|
||||||
|
import androidx.compose.runtime.DisposableEffect
|
||||||
|
import androidx.compose.runtime.Immutable
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.platform.LocalConfiguration
|
||||||
|
import androidx.compose.ui.platform.LocalContext
|
||||||
|
import androidx.compose.ui.res.stringResource
|
||||||
|
import androidx.compose.ui.tooling.preview.Preview
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import mozilla.components.browser.state.selector.normalTabs
|
||||||
|
import mozilla.components.browser.state.state.recover.RecoverableTab
|
||||||
|
import mozilla.components.concept.engine.Engine
|
||||||
|
import mozilla.components.feature.tab.collections.Tab
|
||||||
|
import mozilla.components.feature.tab.collections.TabCollection
|
||||||
|
import org.mozilla.fenix.R.string
|
||||||
|
import org.mozilla.fenix.compose.inComposePreview
|
||||||
|
import org.mozilla.fenix.ext.components
|
||||||
|
import org.mozilla.fenix.theme.FirefoxTheme
|
||||||
|
import org.mozilla.fenix.theme.Theme
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menu shown for a [org.mozilla.fenix.home.collections.Collection].
|
||||||
|
*
|
||||||
|
* @see [DropdownMenu]
|
||||||
|
*
|
||||||
|
* @param showMenu Whether this is currently open and visible to the user.
|
||||||
|
* @param menuItems List of options shown.
|
||||||
|
* @param onDismissRequest Called when the user chooses a menu option or requests to dismiss the menu.
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun CollectionMenu(
|
||||||
|
showMenu: Boolean,
|
||||||
|
menuItems: List<CollectionMenuItem>,
|
||||||
|
onDismissRequest: () -> Unit,
|
||||||
|
) {
|
||||||
|
DisposableEffect(LocalConfiguration.current.orientation) {
|
||||||
|
onDispose { onDismissRequest() }
|
||||||
|
}
|
||||||
|
|
||||||
|
// DropdownMenu uses the medium shape from MaterialTheme.
|
||||||
|
// Override it's corner radius to be the same 8.dp as in mozac_browser_menu_corner_radius
|
||||||
|
MaterialTheme(shapes = MaterialTheme.shapes.copy(medium = RoundedCornerShape(8.dp))) {
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = showMenu,
|
||||||
|
onDismissRequest = { onDismissRequest() },
|
||||||
|
modifier = Modifier
|
||||||
|
.background(color = FirefoxTheme.colors.layer2),
|
||||||
|
) {
|
||||||
|
for (item in menuItems) {
|
||||||
|
DropdownMenuItem(
|
||||||
|
onClick = {
|
||||||
|
onDismissRequest()
|
||||||
|
item.onClick()
|
||||||
|
},
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = item.title,
|
||||||
|
color = item.color,
|
||||||
|
maxLines = 1,
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.align(Alignment.CenterVertically)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A menu item for collections.
|
||||||
|
*
|
||||||
|
* @property title The menu item title.
|
||||||
|
* @property color The color that should be set for the title.
|
||||||
|
* @property onClick Invoked when the user clicks on the menu item.
|
||||||
|
*/
|
||||||
|
@Immutable
|
||||||
|
data class CollectionMenuItem(
|
||||||
|
val title: String,
|
||||||
|
val color: Color,
|
||||||
|
val onClick: () -> Unit,
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs and returns the default list of menu options for a [TabCollection].
|
||||||
|
*
|
||||||
|
* @param collection [TabCollection] for which the menu will be shown.
|
||||||
|
* Might serve as an argument for the callbacks for when the user interacts with certain menu options.
|
||||||
|
* @param onOpenTabsTapped Invoked when the user chooses to open the tabs from [collection].
|
||||||
|
* @param onRenameCollectionTapped Invoked when the user chooses to rename the [collection].
|
||||||
|
* @param onAddTabTapped Invoked when the user chooses to add tabs to [collection].
|
||||||
|
* @param onDeleteCollectionTapped Invoked when the user chooses to delete [collection].
|
||||||
|
*/
|
||||||
|
@Composable
|
||||||
|
fun getMenuItems(
|
||||||
|
collection: TabCollection,
|
||||||
|
onOpenTabsTapped: (TabCollection) -> Unit,
|
||||||
|
onRenameCollectionTapped: (TabCollection) -> Unit,
|
||||||
|
onAddTabTapped: (TabCollection) -> Unit,
|
||||||
|
onDeleteCollectionTapped: (TabCollection) -> Unit,
|
||||||
|
): List<CollectionMenuItem> {
|
||||||
|
return listOfNotNull(
|
||||||
|
CollectionMenuItem(
|
||||||
|
title = stringResource(string.collection_open_tabs),
|
||||||
|
color = FirefoxTheme.colors.textPrimary
|
||||||
|
) {
|
||||||
|
onOpenTabsTapped(collection)
|
||||||
|
},
|
||||||
|
CollectionMenuItem(
|
||||||
|
title = stringResource(string.collection_rename),
|
||||||
|
color = FirefoxTheme.colors.textPrimary
|
||||||
|
) {
|
||||||
|
onRenameCollectionTapped(collection)
|
||||||
|
},
|
||||||
|
|
||||||
|
if (hasOpenTabs()) {
|
||||||
|
CollectionMenuItem(
|
||||||
|
title = stringResource(string.add_tab),
|
||||||
|
color = FirefoxTheme.colors.textPrimary
|
||||||
|
) {
|
||||||
|
onAddTabTapped(collection)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
},
|
||||||
|
|
||||||
|
CollectionMenuItem(
|
||||||
|
title = stringResource(string.collection_delete),
|
||||||
|
color = FirefoxTheme.colors.textWarning
|
||||||
|
) {
|
||||||
|
onDeleteCollectionTapped(collection)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
private fun hasOpenTabs() = when (inComposePreview) {
|
||||||
|
true -> true
|
||||||
|
false -> LocalContext.current.components.core.store.state.normalTabs.isNotEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES)
|
||||||
|
private fun CollectionMenuDarkPreview() {
|
||||||
|
FirefoxTheme(Theme.Dark) {
|
||||||
|
CollectionMenu(
|
||||||
|
showMenu = true,
|
||||||
|
menuItems = getMenuItems(
|
||||||
|
collection = collectionPreview,
|
||||||
|
onOpenTabsTapped = {},
|
||||||
|
onRenameCollectionTapped = {},
|
||||||
|
onAddTabTapped = {},
|
||||||
|
onDeleteCollectionTapped = {}
|
||||||
|
),
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO)
|
||||||
|
private fun CollectionMenuLightPreview() {
|
||||||
|
FirefoxTheme(Theme.Light) {
|
||||||
|
CollectionMenu(
|
||||||
|
showMenu = true,
|
||||||
|
menuItems = getMenuItems(
|
||||||
|
collection = collectionPreview,
|
||||||
|
onOpenTabsTapped = {},
|
||||||
|
onRenameCollectionTapped = {},
|
||||||
|
onAddTabTapped = {},
|
||||||
|
onDeleteCollectionTapped = {}
|
||||||
|
),
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val collectionPreview = object : TabCollection {
|
||||||
|
override val id: Long = 1L
|
||||||
|
override val tabs: List<Tab> = emptyList()
|
||||||
|
override val title: String = "Collection 1"
|
||||||
|
|
||||||
|
override fun restore(
|
||||||
|
context: Context,
|
||||||
|
engine: Engine,
|
||||||
|
restoreSessionId: Boolean,
|
||||||
|
): List<RecoverableTab> = emptyList()
|
||||||
|
|
||||||
|
override fun restoreSubset(
|
||||||
|
context: Context,
|
||||||
|
engine: Engine,
|
||||||
|
tabs: List<Tab>,
|
||||||
|
restoreSessionId: Boolean,
|
||||||
|
): List<RecoverableTab> = emptyList()
|
||||||
|
}
|
@ -1,98 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
- License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
||||||
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:id="@+id/item_collection"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:layout_marginHorizontal="@dimen/home_item_horizontal_margin"
|
|
||||||
android:layout_marginTop="12dp"
|
|
||||||
android:background="@drawable/card_list_row_background"
|
|
||||||
android:clickable="true"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:elevation="@dimen/home_item_elevation"
|
|
||||||
android:focusable="true"
|
|
||||||
android:foreground="?android:attr/selectableItemBackground">
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/collection_icon"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:importantForAccessibility="no"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:srcCompat="@drawable/ic_tab_collection"
|
|
||||||
app:tint="@null" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/collection_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginStart="24dp"
|
|
||||||
android:layout_marginEnd="8dp"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:gravity="start"
|
|
||||||
android:maxLines="1"
|
|
||||||
android:minLines="1"
|
|
||||||
android:textAppearance="@style/Header14TextStyle"
|
|
||||||
app:layout_constrainedWidth="true"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/collection_icon"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/chevron"
|
|
||||||
app:layout_constraintHorizontal_bias="0.0"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="packed"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/collection_icon"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/collection_icon"
|
|
||||||
tools:text="@tools:sample/lorem/random" />
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/chevron"
|
|
||||||
android:layout_width="24dp"
|
|
||||||
android:layout_height="24dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
app:srcCompat="@drawable/ic_chevron"
|
|
||||||
android:contentDescription="@string/tab_menu"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/collection_icon"
|
|
||||||
app:layout_constraintEnd_toStartOf="@+id/collection_share_button"
|
|
||||||
app:layout_constraintStart_toEndOf="@+id/collection_title"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/collection_icon" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/collection_share_button"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/share_button_content_description"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/collection_icon"
|
|
||||||
app:layout_constraintEnd_toStartOf="@id/collection_overflow_button"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/collection_icon"
|
|
||||||
app:srcCompat="@drawable/ic_share"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<ImageButton
|
|
||||||
android:id="@+id/collection_overflow_button"
|
|
||||||
android:layout_width="48dp"
|
|
||||||
android:layout_height="48dp"
|
|
||||||
android:background="?android:attr/selectableItemBackgroundBorderless"
|
|
||||||
android:contentDescription="@string/collection_menu_button_content_description"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="@id/collection_icon"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="@id/collection_icon"
|
|
||||||
app:srcCompat="@drawable/ic_menu"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/selected_border"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:alpha="0"
|
|
||||||
android:background="@drawable/session_border"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
Loading…
Reference in New Issue