Material UI:SwipeableDrawer滑动边缘关闭时不显示问题
SwipeableDrawer滑动边缘关闭时不显示的解决方法
问题描述
我尝试为SwipeableDrawer添加滑动边缘,期望该边缘在抽屉关闭时也能显示,方便用户点击或滑动打开抽屉。但实际应用中,抽屉关闭时边缘完全隐藏,只有通过Open按钮打开抽屉后才会出现。使用的是@material-ui/core,仅移除了官方示例中不存在的Skeleton组件,代码如下:
import * as React from "react"; import PropTypes from "prop-types"; import { Global } from "@emotion/react"; import { styled } from "@material-ui/core/styles"; import CssBaseline from "@material-ui/core/CssBaseline"; import { grey } from "@material-ui/core/colors"; import Button from "@material-ui/core/Button"; import Box from "@material-ui/core/Box"; import Typography from "@material-ui/core/Typography"; import SwipeableDrawer from "@material-ui/core/SwipeableDrawer"; const drawerBleeding = 56; const Root = styled("div")(({ theme }) => ({ height: "100%", backgroundColor: theme.palette.mode === "light" ? grey[100] : theme.palette.background.default, })); const StyledBox = styled(Box)(({ theme }) => ({ backgroundColor: theme.palette.mode === "light" ? "#fff" : grey[800], })); const Puller = styled(Box)(({ theme }) => ({ width: 30, height: 6, backgroundColor: theme.palette.mode === "light" ? grey[300] : grey[900], borderRadius: 3, position: "absolute", top: 8, left: "calc(50% - 15px)", })); function SwipeableEdgeDrawer(props) { const { window } = props; const [open, setOpen] = React.useState(false); const toggleDrawer = (newOpen) => () => { setOpen(newOpen); }; const container = window !== undefined ? () => window().document.body : undefined; return ( <Root> <CssBaseline /> <Global styles={{ ".MuiDrawer-root > .MuiPaper-root": { height: `calc(50% - ${drawerBleeding}px)`, overflow: "visible", }, }} /> <Button className="btn-round" color="danger" onClick={toggleDrawer(true)}> Open </Button> <SwipeableDrawer container={container} anchor="bottom" open={open} onClose={toggleDrawer(false)} onOpen={toggleDrawer(true)} swipeAreaWidth={drawerBleeding} disableSwipeToOpen={false} ModalProps={{ keepMounted: true, }} > <StyledBox sx={{ position: "absolute", top: -drawerBleeding, borderTopLeftRadius: 8, borderTopRightRadius: 8, visibility: "visible", right: 0, left: 0, }} > <Puller /> <Typography sx={{ p: 2, color: "text.secondary" }}> 51 results </Typography> </StyledBox> <StyledBox sx={{ px: 2, pb: 2, height: "100%", overflow: "auto", }} ></StyledBox> </SwipeableDrawer> </Root> ); } SwipeableEdgeDrawer.propTypes = { window: PropTypes.func, }; export default SwipeableEdgeDrawer;
解决方案
问题核心是:抽屉关闭时,SwipeableDrawer内部的Paper元素会被隐藏,导致放在内部的滑动边缘(Puller)也随之消失。只需将滑动边缘组件移到Drawer外部,同时保留滑动触发功能即可:
修改后的完整代码
import * as React from "react"; import PropTypes from "prop-types"; import { Global } from "@emotion/react"; import { styled } from "@material-ui/core/styles"; import CssBaseline from "@material-ui/core/CssBaseline"; import { grey } from "@material-ui/core/colors"; import Button from "@material-ui/core/Button"; import Box from "@material-ui/core/Box"; import Typography from "@material-ui/core/Typography"; import SwipeableDrawer from "@material-ui/core/SwipeableDrawer"; const drawerBleeding = 56; const Root = styled("div")(({ theme }) => ({ height: "100%", backgroundColor: theme.palette.mode === "light" ? grey[100] : theme.palette.background.default, })); const StyledBox = styled(Box)(({ theme }) => ({ backgroundColor: theme.palette.mode === "light" ? "#fff" : grey[800], })); const Puller = styled(Box)(({ theme }) => ({ width: 30, height: 6, backgroundColor: theme.palette.mode === "light" ? grey[300] : grey[900], borderRadius: 3, position: "absolute", top: 8, left: "calc(50% - 15px)", cursor: "pointer" })); // 单独定义抽屉顶部的边缘组件 const DrawerEdge = styled(Box)(({ theme }) => ({ position: "fixed", bottom: `calc(50% - ${drawerBleeding}px)`, borderTopLeftRadius: 8, borderTopRightRadius: 8, right: 0, left: 0, backgroundColor: theme.palette.mode === "light" ? "#fff" : grey[800], cursor: "pointer" })); function SwipeableEdgeDrawer(props) { const { window } = props; const [open, setOpen] = React.useState(false); const toggleDrawer = (newOpen) => () => { setOpen(newOpen); }; const container = window !== undefined ? () => window().document.body : undefined; return ( <Root> <CssBaseline /> <Global styles={{ ".MuiDrawer-root > .MuiPaper-root": { height: `calc(50% - ${drawerBleeding}px)`, overflow: "visible", }, }} /> <Button className="btn-round" color="danger" onClick={toggleDrawer(true)}> Open </Button> {/* 把滑动边缘移到Drawer外部,始终显示 */} <DrawerEdge onClick={toggleDrawer(true)}> <Puller /> <Typography sx={{ p: 2, color: "text.secondary" }}> 51 results </Typography> </DrawerEdge> <SwipeableDrawer container={container} anchor="bottom" open={open} onClose={toggleDrawer(false)} onOpen={toggleDrawer(true)} swipeAreaWidth={drawerBleeding} disableSwipeToOpen={false} ModalProps={{ keepMounted: true, }} > <StyledBox sx={{ px: 2, pb: 2, height: "100%", overflow: "auto", }} ></StyledBox> </SwipeableDrawer> </Root> ); } SwipeableEdgeDrawer.propTypes = { window: PropTypes.func, }; export default SwipeableEdgeDrawer;
关键改动说明
- 将滑动边缘移到Drawer外部:单独定义
DrawerEdge组件并放在SwipeableDrawer同级位置,确保抽屉关闭时边缘仍能显示 - 添加点击触发事件:给
DrawerEdge绑定onClick事件,点击即可打开抽屉 - 保留滑动触发功能:保留
swipeAreaWidth和ModalProps.keepMounted配置,确保用户仍能通过滑动区域打开抽屉
内容的提问来源于stack exchange,提问作者AG_HIHI
相关产品推荐
相关产品推荐

