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

Flutter中如何模糊PageView Builder的前后Widget

实现PageView卡片模糊效果问题

需求

想要实现:PageView中当前显示的天气卡片保持清晰,左右两侧的卡片呈现模糊效果。

问题

已完成天气卡片(WeatherCard)和PageView的搭建,测试时尝试给未聚焦卡片添加模糊,但出现异常:

切换页面时,当前激活的卡片和上一张卡片会被模糊,下一张卡片无法实现模糊效果。

当前效果

切换页面时,当前卡片与上一张卡片均处于模糊状态,下一张卡片无模糊效果。


解决方案

问题核心在于原代码仅用index == currentPage的布尔值判断卡片状态,模糊逻辑搞反,且未利用PageView的滚动进度动态调整相邻卡片的模糊度。以下是修复后的代码:

修改后的page_view_gallary.dart

class PageviewGallery extends StatefulWidget {
  @override
  _PageviewGalleryState createState() => _PageviewGalleryState();
}

class _PageviewGalleryState extends State<PageviewGallery> {
  final List<Map<String, dynamic>> cardData = [
    {
      "location": "Los Angeles, CA, USA",
      "temperature": 15,
      "localTimeEpoch": 1675101764,
      "weatherState1": "Strong Winds",
      "weatherState2": "Cloudy"
    },
    {
      "location": "San Andreas, CA, USA",
      "temperature": 15,
      "localTimeEpoch": 1675101764,
      "weatherState1": "Strong Winds",
      "weatherState2": "Cloudy"
    },
    {
      "location": "Los Angeles, CA, USA",
      "temperature": 15,
      "localTimeEpoch": 1675101764,
      "weatherState1": "Strong Winds",
      "weatherState2": "Cloudy"
    },
    {
      "location": "Los Angeles, CA, USA",
      "temperature": 15,
      "localTimeEpoch": 1675101764,
      "weatherState1": "Strong Winds",
      "weatherState2": "Cloudy"
    },
    {
      "location": "Los Angeles, CA, USA",
      "temperature": 15,
      "localTimeEpoch": 1675101764,
      "weatherState1": "Strong Winds",
      "weatherState2": "Cloudy"
    },
  ];

  final PageController ctrl = PageController(
    viewportFraction: 0.5,
  );

  double currentPage = 0.0;

  @override
  void initState() {
    super.initState();
    ctrl.addListener(() {
      setState(() {
        currentPage = ctrl.page ?? 0.0;
      });
    });
  }

  @override
  void dispose() {
    ctrl.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: ExpandablePageView.builder(
          controller: ctrl,
          itemCount: cardData.length,
          physics: const BouncingScrollPhysics(),
          itemBuilder: (context, int index) {
            return _buildStoryPage(index);
          },
        ),
      ),
    );
  }

  Widget _buildStoryPage(int index) {
    // 根据卡片与当前滚动位置的差值,动态计算模糊度
    double blurAmount = 0.0;
    final double diff = (currentPage - index).abs();
    
    if (diff >= 1) {
      // 非相邻卡片,应用固定模糊值
      blurAmount = 5.0;
    } else {
      // 相邻卡片,根据滚动进度平滑调整模糊度
      blurAmount = diff * 5.0;
    }

    // 动态调整动画属性
    final double offset = diff * 20;
    final double top = 100 + diff * 100;
    final double bottom = 100 + diff * 100;

    return BackdropFilter(
      filter: ImageFilter.blur(sigmaX: blurAmount, sigmaY: blurAmount),
      child: AnimatedContainer(
        duration: const Duration(milliseconds: 300),
        curve: Curves.easeOutQuint,
        margin: EdgeInsets.only(top: top, bottom: bottom, right: 30),
        decoration: BoxDecoration(
          borderRadius: BorderRadius.circular(20),
          color: Colors.red,
          boxShadow: [
            BoxShadow(
              color: Colors.black87,
              blurRadius: diff * 30,
              offset: Offset(offset, offset),
            ),
          ],
        ),
        child: WeatherCard(
          location: cardData[index]["location"],
          temperature: cardData[index]["temperature"],
          localTimeEpoch: cardData[index]["localTimeEpoch"],
          weatherState1: cardData[index]["weatherState1"],
          weatherState2: cardData[index]["weatherState2"],
          isActive: index == currentPage.round(),
        ),
      ),
    );
  }
}

关键修改点

  1. 移除硬编码的isActive状态,改用滚动进度动态判断卡片激活状态
  2. 监听PageController的精确page值,实时获取滚动进度,实现平滑的模糊过渡
  3. 调整模糊逻辑:当前卡片模糊度为0,相邻卡片根据滚动进度动态变化,非相邻卡片固定模糊值
  4. 动画属性(位置、阴影)随滚动进度同步调整,提升过渡自然度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 03:35:42