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

如何制作类似ListView.builder的环形/径向列表视图以实现重量测量?

实现环形径向可滑动列表并更新重量变量

环形径向列表设计

要实现这种环形/径向的可滑动列表(功能类似ListView.builder)并支持滑动更新重量变量,可以基于Flutter的自定义布局和手势检测来实现,以下是具体方案:

核心思路

  • 自定义径向布局:通过三角函数计算每个列表项的环形位置,结合旋转变换实现环形排列效果。
  • 手势滑动交互:监听拖动手势,将滑动偏移量转换为环形旋转角度,再映射为重量变量的更新值。
  • 动态构建列表项:参考ListView.builder的懒加载逻辑,按需构建当前可见范围内的列表项,优化性能。

代码示例

import 'package:flutter/material.dart';
import 'dart:math';

class RadialListView extends StatefulWidget {
  final int itemCount;
  final Widget Function(BuildContext, int) itemBuilder;
  final ValueChanged<double> onWeightChanged;

  const RadialListView({
    super.key,
    required this.itemCount,
    required this.itemBuilder,
    required this.onWeightChanged,
  });

  @override
  State<RadialListView> createState() => _RadialListViewState();
}

class _RadialListViewState extends State<RadialListView> {
  double _rotationAngle = 0.0;
  final double _ringRadius = 220.0;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onPanUpdate: (details) {
        // 水平滑动偏移转换为旋转角度
        setState(() {
          _rotationAngle += details.delta.dx * 0.008;
        });
        // 将旋转角度映射为0-100的重量值,可根据需求调整映射规则
        double normalizedAngle = _rotationAngle % (2 * pi);
        double weight = (normalizedAngle / (2 * pi)) * 100;
        widget.onWeightChanged(weight);
      },
      child: Stack(
        alignment: Alignment.center,
        children: [
          // 按需构建可见列表项(简化版,大量item时可添加可见性判断)
          ...List.generate(widget.itemCount, (index) {
            double itemAngle = _rotationAngle + (index / widget.itemCount) * 2 * pi;
            double posX = _ringRadius * cos(itemAngle);
            double posY = _ringRadius * sin(itemAngle);
            return Transform.translate(
              offset: Offset(posX, posY),
              child: widget.itemBuilder(context, index),
            );
          }),
          // 中心定位指示器
          Container(
            width: 45,
            height: 45,
            decoration: const BoxDecoration(
              color: Colors.redAccent,
              shape: BoxShape.circle,
            ),
            child: const Center(child: Text("→", style: TextStyle(fontSize: 20))),
          ),
        ],
      ),
    );
  }
}

// 使用示例
class RadialListDemo extends StatefulWidget {
  const RadialListDemo({super.key});

  @override
  State<RadialListDemo> createState() => _RadialListDemoState();
}

class _RadialListDemoState extends State<RadialListDemo> {
  double _currentWeight = 0.0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("环形径向列表")),
      body: Column(
        children: [
          Expanded(
            child: RadialListView(
              itemCount: 25,
              itemBuilder: (context, index) {
                return Container(
                  width: 65,
                  height: 65,
                  decoration: BoxDecoration(
                    color: Colors.blue.shade100,
                    borderRadius: BorderRadius.circular(32),
                    border: Border.all(color: Colors.blue.shade300, width: 2),
                  ),
                  child: Center(child: Text("${index+1}", style: const TextStyle(fontSize: 16))),
                );
              },
              onWeightChanged: (weight) {
                setState(() {
                  _currentWeight = weight;
                });
              },
            ),
          ),
          Padding(
            padding: const EdgeInsets.all(18.0),
            child: Text("当前重量: ${_currentWeight.toStringAsFixed(1)}", style: const TextStyle(fontSize: 18)),
          ),
        ],
      ),
    );
  }
}

关键说明

  • 布局优化:如果列表项数量极大,可通过判断item角度是否在屏幕可见范围内,只渲染可见项,避免不必要的性能消耗。
  • 映射规则自定义:重量变量和旋转角度的对应关系可根据实际需求调整,比如反向映射、分段映射等。
  • 交互扩展:可以添加惯性滑动、边界限制等功能,提升滑动体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:39:34