ListWheelScrollView 进入和退出子项的淡入淡出效果

问题描述 投票:0回答:1

从下面的 GIF 中可以看出,每当子进程退出父进程时

Container
,子进程就会消失且没有动画,这给用户留下了不好的印象。 如何为进入和退出的子进程添加平滑过渡出口?

Chat GPT 给出了一个看似逻辑正确的答案,但它给出了同样突然的效果。

聊天 GPT 代码:-

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Smooth Transition in ListWheelScrollView')),
        body: TransitionListWheel(),
      ),
    );
  }
}

class TransitionListWheel extends StatefulWidget {
  @override
  _TransitionListWheelState createState() => _TransitionListWheelState();
}

class _TransitionListWheelState extends State<TransitionListWheel> {
  FixedExtentScrollController _scrollController;
  double itemHeight = 100.0; // Height of each item in the list
  int itemCount = 20;

  @override
  void initState() {
    super.initState();
    _scrollController = FixedExtentScrollController();
    _scrollController.addListener(_handleScroll);
  }

  @override
  void dispose() {
    _scrollController.removeListener(_handleScroll);
    _scrollController.dispose();
    super.dispose();
  }

  void _handleScroll() {
    setState(() {
      // Trigger a rebuild to update the transition animations
    });
  }

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        height: itemHeight * 5, // Visible height of the list
        child: ListWheelScrollView.useDelegate(
          controller: _scrollController,
          itemExtent: itemHeight,
          physics: FixedExtentScrollPhysics(),
          childDelegate: ListWheelChildBuilderDelegate(
            builder: (context, index) {
              final double scrollOffset = _scrollController.offset;
              final double itemScrollOffset = scrollOffset % itemHeight;

              // Calculate transition values for entering and exiting animations
              final double enteringScale = 1.0 - (itemScrollOffset / itemHeight);
              final double exitingScale = itemScrollOffset / itemHeight;

              return AnimatedBuilder(
                animation: _scrollController,
                builder: (context, child) {
                  return Transform.scale(
                    scale: (enteringScale + exitingScale).clamp(0.6, 1.0), // Adjust the range as needed
                    child: child,
                  );
                },
                child: Center(
                  child: Container(
                    width: 200,
                    height: 80,
                    color: Colors.blue,
                    child: Center(
                      child: Text(
                        'Item $index',
                        style: TextStyle(color: Colors.white),
                      ),
                    ),
                  ),
                ),
              );
            },
            childCount: itemCount,
          ),
        ),
      ),
    );
  }
}

我使用的代码:-

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'List',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      debugShowCheckedModeBanner: false,
      home: const List(),
    );
  }
}

class List extends StatefulWidget {
  const List({Key? key}) : super(key: key);
  @override
  _ListState createState() => _ListState();
}

class _ListState extends State<List> {
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
       
        body: Center(
          child: SizedBox(
            height: 500,
            child: ListWheelScrollView(
                itemExtent: 100,
                physics: const FixedExtentScrollPhysics(),
                onSelectedItemChanged: (value) {
                  
                },
                children: [
                  for (int i = 0; i < 5; i++) ...[
                    Container(
                      color: Colors.green,
                      height: 50,
                      width: 50,
                    )
                  ]
                ]),
          ),
        ));
  }
}
android flutter dart listview flutter-animation
1个回答
0
投票

我认为这个包可以解决您的问题。 https://pub.dev/packages/clickable_list_wheel_view

示例:

import 'package:clickable_list_wheel_view/clickable_list_wheel_widget.dart';
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: Material(
        child: MyHomePage(),
      ),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final _scrollController = FixedExtentScrollController();

  static const double _itemHeight = 60;
  static const int _itemCount = 100;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: ClickableListWheelScrollView(
          scrollController: _scrollController,
          itemHeight: _itemHeight,
          itemCount: _itemCount,
          onItemTapCallback: (index) {
            print("onItemTapCallback index: $index");
          },
          child: ListWheelScrollView.useDelegate(
            controller: _scrollController,
            itemExtent: _itemHeight,
            physics: FixedExtentScrollPhysics(),
            overAndUnderCenterOpacity: 0.5,
            perspective: 0.002,
            onSelectedItemChanged: (index) {
              print("onSelectedItemChanged index: $index");
            },
            childDelegate: ListWheelChildBuilderDelegate(
              builder: (context, index) => _child(index),
              childCount: _itemCount,
            ),
          ),
        ),
      ),
    );
  }

  Widget _child(int index) {
    return SizedBox(
      height: _itemHeight,
      child: ListTile(
        leading: Icon(
            IconData(int.parse("0xe${index + 200}"),
                fontFamily: 'MaterialIcons'),
            size: 50),
        title: Text('Heart Shaker'),
        subtitle: Text('Description here'),
      ),
    );
  }
}

我无法将其发布在这里,因为 gif 尺寸很大。您可以从我共享的链接中看到此代码的输出:https://raw.githubusercontent.com/cilestal/clickable_list_wheel_view/master/example/example.gif

我希望我有所帮助。享受你的工作。

© www.soinside.com 2019 - 2024. All rights reserved.