根据屏幕尺寸动态调整ImageList列?

Sto*_*ker 13 reactjs material-ui

我尝试过使用ImageList组件而不是因为Grid我只需要带有标题的照片网格,这似乎是ImageList. 我的问题是,与网格不同,我无法为不同的屏幕尺寸传递断点道具(我觉得这很奇怪,因为这看起来很合乎逻辑),这样我就可以在不同的屏幕上获得不同的列数。根据屏幕尺寸调整列数的最佳方法是什么?

Nea*_*arl 11

ImageList使用CSS 网格,需要colprop来设置,但没有内置任何响应式 API。您可以将与显示设置为 的组件grid-template-columns交换,并使用prop来声明取决于屏幕尺寸的列模板值,但首先让定义一些断点:ImageListBoxgridsx

const theme = createTheme({
  breakpoints: {
    values: {
      mobile: 0,
      bigMobile: 350,
      tablet: 650,
      desktop: 900
    }
  }
});
Run Code Online (Sandbox Code Playgroud)

然后在组件中,您可以像这样开始使用它:

import ImageListItem, { imageListItemClasses } from "@mui/material/ImageListItem";
Run Code Online (Sandbox Code Playgroud)
<ThemeProvider theme={theme}>
  <Box
    sx={{
      display: "grid",
      gridTemplateColumns: {
        mobile: "repeat(1, 1fr)",
        bigMobile: "repeat(2, 1fr)",
        tablet: "repeat(3, 1fr)",
        desktop: "repeat(4, 1fr)"
      }
      // standard variant from here:
      // https://github.com/mui-org/material-ui/blob/3e679ac9e368aeb170d564d206d59913ceca7062/packages/mui-material/src/ImageListItem/ImageListItem.js#L42-L43
      [`& .${imageListItemClasses.root}`]: {
        display: "flex",
        flexDirection: "column"
      }
    }}
  >
    {itemData.map((item) => <ImageListItem {...}/>)}
  </Box>
</ThemeProvider>
Run Code Online (Sandbox Code Playgroud)

现场演示

Codesandbox 演示

参考

  • 删除“ImageList”作为“ImageListItem”的父级会使其表现得有点笨拙。例如,如果我将“ImageListItemBar”“position”设置为“below”,它将不会出现(隐藏在下一行下)。当然,我可以将这个“Box”的“rowGap”设置得足够高,这样它将再次显示文本,但在添加更多这些内容之后,我基本上开始从基础重新创建整个“ImageList”和“ImageListItem”。我将坚持我的解决方案,因为它允许我保留“ImageList”的内置功能。 (2认同)

小智 7

我使用 useMediaQuery 挂钩来获取 ImageList 组件的 cols 属性。

import { ImageList, ImageListItem, useMediaQuery } from '@mui/material';

function Gallery() {
const matches = useMediaQuery('(min-width:600px)');
return (
    <ImageList cols={matches ? 3 : 2} variant="masonry">
      <ImageListItem>
       ...
      </ImageListItem>
    </ImageList>
  );
}
Run Code Online (Sandbox Code Playgroud)


Sto*_*ker 2

我想出的这个解决方案是有效的,但对于网格处理开箱即用的东西来说似乎有很多行。ImageList 没有一些内置的响应式设计实现吗?

export function Example(props) {
    // not sure if there is a way to get something like this dictionary from React?
    const breakpoints = {
        xs: 0,
        sm: 600,
        md: 960,
        lg: 1280,
        xl: 1920
    }

    const getColumns = (width) => {
        if (width < breakpoints.sm) {
            return 2
        } else if (width < breakpoints.md) {
            return 3
        } else if (width < breakpoints.lg) {
            return 6
        } else if (width < breakpoints.xl) {
            return 7
        } else {
            return 8
        }
    }

    const [columns, setColumns] = useState(getColumns(window.innerWidth))
    const updateDimensions = () => {
        setColumns(getColumns(window.innerWidth))
    }

    useEffect(() => {
        window.addEventListener("resize", updateDimensions);
        return () => window.removeEventListener("resize", updateDimensions);
    }, []);

    return (
        <ImageList cols={columns}>
          {/* list items ... */}
        </ImageList>
    )
}
Run Code Online (Sandbox Code Playgroud)