-
-
Notifications
You must be signed in to change notification settings - Fork 175
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(ui): long press on an item to show context menu (#613)
* feat(ui): long press on an item to show context menu * feat(ui): add handy enter-exit transition to drop down menu * feat(ui): implement share action * feat(ui): polish the enter/exit transition * fix(ui): RTL walkaround * feat(ui): dropdown menu style tweaks * feat(ui): mark above as read & mark below as read * feat(fever): update read status by id set * fix: use `batchMarkAsRead` * fix: disable `onMarkAboveAsRead` for the first item
- Loading branch information
1 parent
db65c3d
commit 53523e4
Showing
12 changed files
with
939 additions
and
91 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
96 changes: 96 additions & 0 deletions
96
app/src/main/java/me/ash/reader/ui/component/menu/AnimatedDropdownMenu.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
package me.ash.reader.ui.component.menu | ||
|
||
import androidx.compose.animation.core.MutableTransitionState | ||
import androidx.compose.foundation.ScrollState | ||
import androidx.compose.foundation.layout.ColumnScope | ||
import androidx.compose.foundation.rememberScrollState | ||
import androidx.compose.material3.DropdownMenu | ||
import androidx.compose.material3.DropdownMenuItem | ||
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.Modifier | ||
import androidx.compose.ui.platform.LocalDensity | ||
import androidx.compose.ui.unit.DpOffset | ||
import androidx.compose.ui.unit.dp | ||
import androidx.compose.ui.window.Popup | ||
import androidx.compose.ui.window.PopupProperties | ||
|
||
/** | ||
* <a href="https://m3.material.io/components/menus/overview" class="external" target="_blank">Material Design dropdown menu</a>. | ||
* | ||
* Menus display a list of choices on a temporary surface. They appear when users interact with a | ||
* button, action, or other control. | ||
* | ||
* ![Dropdown menu image](https://developer.android.com/images/reference/androidx/compose/material3/menu.png) | ||
* | ||
* A [DropdownMenu] behaves similarly to a [Popup], and will use the position of the parent layout | ||
* to position itself on screen. Commonly a [DropdownMenu] will be placed in a [Box] with a sibling | ||
* that will be used as the 'anchor'. Note that a [DropdownMenu] by itself will not take up any | ||
* space in a layout, as the menu is displayed in a separate window, on top of other content. | ||
* | ||
* The [content] of a [DropdownMenu] will typically be [DropdownMenuItem]s, as well as custom | ||
* content. Using [DropdownMenuItem]s will result in a menu that matches the Material | ||
* specification for menus. Also note that the [content] is placed inside a scrollable [Column], | ||
* so using a [LazyColumn] as the root layout inside [content] is unsupported. | ||
* | ||
* [onDismissRequest] will be called when the menu should close - for example when there is a | ||
* tap outside the menu, or when the back key is pressed. | ||
* | ||
* [DropdownMenu] changes its positioning depending on the available space, always trying to be | ||
* fully visible. Depending on layout direction, first it will try to align its start to the start | ||
* of its parent, then its end to the end of its parent, and then to the edge of the window. | ||
* Vertically, it will try to align its top to the bottom of its parent, then its bottom to top of | ||
* its parent, and then to the edge of the window. | ||
* | ||
* An [offset] can be provided to adjust the positioning of the menu for cases when the layout | ||
* bounds of its parent do not coincide with its visual bounds. | ||
* | ||
* | ||
* @param expanded whether the menu is expanded or not | ||
* @param onDismissRequest called when the user requests to dismiss the menu, such as by tapping | ||
* outside the menu's bounds | ||
* @param modifier [Modifier] to be applied to the menu's content | ||
* @param offset [DpOffset] from the original position of the menu. The offset respects the | ||
* [LayoutDirection], so the offset's x position will be added in LTR and subtracted in RTL. | ||
* @param scrollState a [ScrollState] to used by the menu's content for items vertical scrolling | ||
* @param properties [PopupProperties] for further customization of this popup's behavior | ||
* @param content the content of this dropdown menu, typically a [DropdownMenuItem] | ||
*/ | ||
@Composable | ||
fun AnimatedDropdownMenu( | ||
expanded: Boolean, | ||
onDismissRequest: () -> Unit, | ||
modifier: Modifier = Modifier, | ||
offset: DpOffset = DpOffset(0.dp, 0.dp), | ||
scrollState: ScrollState = rememberScrollState(), | ||
properties: PopupProperties = PopupProperties(focusable = true), | ||
content: @Composable ColumnScope.() -> Unit | ||
) { | ||
val expandedState = remember { MutableTransitionState(false) } | ||
expandedState.targetState = expanded | ||
|
||
if (expandedState.currentState || expandedState.targetState || !expandedState.isIdle) { | ||
val density = LocalDensity.current | ||
val popupPositionProvider = remember(offset, density) { | ||
DropdownMenuPositionProvider( | ||
offset, | ||
density | ||
) | ||
} | ||
Popup( | ||
onDismissRequest = onDismissRequest, | ||
popupPositionProvider = popupPositionProvider, | ||
properties = properties | ||
) { | ||
DropdownMenuContent( | ||
expandedState = expandedState, | ||
scrollState = scrollState, | ||
modifier = modifier, | ||
content = content | ||
) | ||
} | ||
} | ||
} |
Oops, something went wrong.