You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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;

关键改动说明

  1. 将滑动边缘移到Drawer外部:单独定义DrawerEdge组件并放在SwipeableDrawer同级位置,确保抽屉关闭时边缘仍能显示
  2. 添加点击触发事件:给DrawerEdge绑定onClick事件,点击即可打开抽屉
  3. 保留滑动触发功能:保留swipeAreaWidth和ModalProps.keepMounted配置,确保用户仍能通过滑动区域打开抽屉

内容的提问来源于stack exchange,提问作者AG_HIHI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:40:32