ios 半透明容器在 Flutter

bqf10yzr  于 2023-05-23  发布在  iOS
关注(0)|答案(1)|浏览(149)

我对这个设计很感兴趣。我希望当用户向下滚动练习列表时,在练习列表的底部(总是在那里-喜欢固定在容器底部上方一定高度的地方),是带有可扩展FAB的开始按钮。围绕带有FAB的开始按钮的容器应该是半透明的,并且还具有边界半径。非常感谢您的帮助提前!
What it looks like right now
What I want it to look like
我的代码:

import 'package:flutter/material.dart';
import 'package:workout_app/Screens/Components/Widgets/footer.dart';

class workout_page extends StatefulWidget {
  @override
  _WorkoutPageState createState() => _WorkoutPageState();
}

class _WorkoutPageState extends State<workout_page>
    with TickerProviderStateMixin {
  late TabController _tabController;
  late PageController _pageController;

  List<Map<String, dynamic>> workoutMap = [
    {
      'name': 'My First Workout',
      'exercises': [
        {
          'name': 'Bicep Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Preacher Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Bicep Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Preacher Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Bicep Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Preacher Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Bicep Curl',
          'musclesworked': ['bicep', 'tricep']
        },
        {
          'name': 'Preacher Curl',
          'musclesworked': ['bicep', 'tricep']
        }
      ]
    },
  ];

  @override
  void initState() {
    super.initState();
    _tabController = TabController(length: workoutMap.length + 1, vsync: this);
    _pageController = PageController();
  }

  TextEditingController _newTabController = TextEditingController();

  void _addTab() {
    setState(() {
      String newTabName = _newTabController.text;
      Map<String, dynamic> newTab = {
        'name': newTabName,
        'exercises': [],
      };
      workoutMap.add(newTab);
      _newTabController.clear();
      _tabController = TabController(
        length: workoutMap.length + (workoutMap.length < 4 ? 1 : 0),
        vsync: this,
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    var size = MediaQuery.of(context).size;
    return Container(
      decoration: BoxDecoration(color: Color.fromARGB(255, 67, 67, 67)),
      child: DefaultTabController(
        length: workoutMap.length + (workoutMap.length < 4 ? 1 : 0),
        child: Scaffold(
          backgroundColor: Color.fromRGBO(79, 79, 79, 1),
          body: Stack(
            children: [
              CustomScrollView(
                physics: NeverScrollableScrollPhysics(),
                slivers: [
                  SliverAppBar(
                    expandedHeight: 30,
                    titleSpacing: 15,
                    pinned: true,
                    elevation: 0,
                    backgroundColor: Color.fromARGB(255, 19, 19, 19),
                    centerTitle: false,
                    bottom: PreferredSize(
                        preferredSize: const Size.fromHeight(0),
                        child: Column(children: [
                          TabBar(
                            controller: _tabController,
                            onTap: (index) {
                              if (index == _tabController.length - 1 &&
                                  workoutMap.length < 4) {
                                _tabController
                                    .animateTo(_tabController.previousIndex);
                              } else {
                                _tabController.animateTo(index);
                                _pageController.jumpToPage(index);
                              }
                            },
                            tabs: [
                              ...workoutMap.map(
                                  (tab) => Tab(text: tab['name'] as String)),
                              if (workoutMap.length < 4)
                                Container(
                                  width: 40,
                                  height: 40,
                                  alignment: Alignment.center,
                                  child: IconButton(
                                    icon: Icon(Icons.add),
                                    onPressed: () {
                                      showDialog(
                                        context: context,
                                        builder: (context) => AlertDialog(
                                          title: Text('Add Tab'),
                                          content: TextField(
                                            controller: _newTabController,
                                            decoration: InputDecoration(
                                              hintText: 'Enter tab name',
                                            ),
                                          ),
                                          actions: [
                                            TextButton(
                                              child: Text('Cancel'),
                                              onPressed: () {
                                                Navigator.pop(context);
                                              },
                                            ),
                                            TextButton(
                                              child: Text('Add'),
                                              onPressed: () {
                                                _addTab();
                                                Navigator.pop(context);
                                              },
                                            ),
                                          ],
                                        ),
                                      );
                                    },
                                  ),
                                ),
                            ],
                          ),
                        ])),
                  ),
                  SliverToBoxAdapter(
                      child: Container(
                    height: size.height * .6,
                    child: PageView(
                      controller: _pageController,
                      onPageChanged: (index) {
                        if (index == _tabController.length - 1 &&
                            workoutMap.length < 4) {
                          _pageController.jumpToPage(_tabController.index);
                        } else {
                          _tabController.animateTo(index);
                        }
                      },
                      children: [
                        ...workoutMap.map(
                          (tab) => Container(
                              width: size.width,
                              height: size.height * .6,
                              decoration: BoxDecoration(
                                  color: Color.fromARGB(255, 41, 41, 41)),
                              child: Column(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  children: [
                                    tab['exercises'].length == 0
                                        ? Column(
                                            mainAxisAlignment:
                                                MainAxisAlignment.center,
                                            children: <Widget>[
                                              Icon(
                                                Icons
                                                    .sentiment_very_dissatisfied,
                                                size: size.width *
                                                    .3, // You can adjust the size as per your need
                                                color: Colors
                                                    .white, // You can adjust the color as per your need
                                              ),
                                              SizedBox(height: 10),
                                              Text(
                                                'This folder is empty. Add some workouts',
                                                style: TextStyle(
                                                    color: Colors.white),
                                                textAlign: TextAlign.center,
                                              ),
                                            ],
                                          )
                                        : Expanded(
                                            child: ListView.builder(
                                              itemCount:
                                                  tab['exercises'].length,
                                              itemBuilder: (context, index) {
                                                return Container(
                                                    margin: EdgeInsets.only(
                                                        bottom: 10.0,
                                                        left: 10,
                                                        right: 10),
                                                    decoration: BoxDecoration(
                                                        color: Colors.black,
                                                        borderRadius:
                                                            BorderRadius
                                                                .circular(
                                                                    10.0)),
                                                    child: Column(children: [
                                                      Container(
                                                        height:
                                                            size.height * .15,
                                                        decoration:
                                                            BoxDecoration(
                                                          color: Color.fromARGB(
                                                              255, 94, 94, 94),
                                                          borderRadius:
                                                              BorderRadius
                                                                  .circular(
                                                                      10.0),
                                                        ),
                                                        child: Stack(
                                                          children: [
                                                            Positioned(
                                                              top: 10,
                                                              left: 10,
                                                              child: Container(
                                                                width:
                                                                    size.width *
                                                                        .4,
                                                                child:
                                                                    ClipRRect(
                                                                  borderRadius:
                                                                      BorderRadius
                                                                          .circular(
                                                                              10.0),
                                                                  child: Image
                                                                      .network(
                                                                    'https://i.giphy.com/media/14kdiJUblbWBXy/giphy.gif', // Replace with your GIF URL
                                                                  ),
                                                                ),
                                                              ),
                                                            ),
                                                            Positioned(
                                                              top: 10,
                                                              left: size.width *
                                                                      .4 +
                                                                  20,
                                                              child: Column(
                                                                  crossAxisAlignment:
                                                                      CrossAxisAlignment
                                                                          .start, // Add this line
                                                                  children: [
                                                                    Text(
                                                                      tab['exercises']
                                                                              [
                                                                              index]
                                                                          [
                                                                          'name'],
                                                                      style: TextStyle(
                                                                          color: Colors
                                                                              .black,
                                                                          fontSize:
                                                                              20,
                                                                          fontWeight:
                                                                              FontWeight.bold),
                                                                    ),
                                                                    Text(
                                                                      (tab['exercises'][index]['musclesworked']
                                                                              as List)
                                                                          .join(
                                                                              ', '), // join the list into a string
                                                                      style: TextStyle(
                                                                          fontSize:
                                                                              16), // adjust style as needed
                                                                    )
                                                                  ]),
                                                            ),
                                                          ],
                                                        ),
                                                      ),
                                                      SizedBox(height: 10),
                                                      Row(children: [
                                                        Spacer(),
                                                        Text(
                                                          '3 Sets', // Replace with your sets, reps, and weight data
                                                          style: TextStyle(
                                                              color:
                                                                  Colors.white),
                                                          textAlign:
                                                              TextAlign.center,
                                                        ),
                                                        Spacer(),
                                                        Text(
                                                          '4 reps', // Replace with your sets, reps, and weight data
                                                          style: TextStyle(
                                                              color:
                                                                  Colors.white),
                                                          textAlign:
                                                              TextAlign.center,
                                                        ),
                                                        Spacer(),
                                                        Text(
                                                          '30 kg', // Replace with your sets, reps, and weight data
                                                          style: TextStyle(
                                                              color:
                                                                  Colors.white),
                                                          textAlign:
                                                              TextAlign.center,
                                                        ),
                                                        Spacer()
                                                      ]),
                                                      SizedBox(height: 10),
                                                    ]));
                                              },
                                            ),
                                          ),
                                    SizedBox(height: 10),
                                    Row(
                                      mainAxisAlignment:
                                          MainAxisAlignment.center,
                                      children: [
                                        Spacer(),
                                        Container(
                                          decoration: BoxDecoration(
                                            color:
                                                Color.fromARGB(255, 0, 255, 8),
                                            borderRadius:
                                                BorderRadius.circular(10.0),
                                          ),
                                          height: size.height * .08,
                                          width: size.width * .5,
                                          child: Column(
                                            mainAxisAlignment:
                                                MainAxisAlignment.center,
                                            children: <Widget>[
                                              Text('Start',
                                                  style:
                                                      TextStyle(fontSize: 30)),
                                            ],
                                          ),
                                        ),
                                        SizedBox(width: 20),
                                        ExpandableFab(),
                                        Spacer(),
                                      ],
                                    ),
                                    SizedBox(height: 10),
                                  ])),
                        )
                      ],
                    ),
                  ))
                ],
              ),
              Footer(tab: 'Workout'),
            ],
          ),
        ),
      ),
    );
  }
}

class CustomScrollPhysics extends ScrollPhysics {
  final TabController tabController;

  CustomScrollPhysics({required this.tabController, ScrollPhysics? parent})
      : super(parent: parent);

  @override
  CustomScrollPhysics applyTo(ScrollPhysics? ancestor) {
    return CustomScrollPhysics(tabController: tabController, parent: ancestor);
  }

  @override
  double applyPhysicsToUserOffset(ScrollMetrics position, double offset) {
    if ((tabController.index == tabController.length - 2 && offset > 0)) {
      return 0.0;
    }
    return offset;
  }
}

class ExpandableFab extends StatefulWidget {
  @override
  _ExpandableFabState createState() => _ExpandableFabState();
}

class _ExpandableFabState extends State<ExpandableFab>
    with SingleTickerProviderStateMixin {
  late AnimationController _animationController;
  late Animation<double> _animation;
  bool _isExpanded = false;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(milliseconds: 200),
    );
    _animation =
        Tween<double>(begin: 0.0, end: 1.0).animate(_animationController);
  }

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

  void _toggleExpanded() {
    setState(() {
      _isExpanded = !_isExpanded;
      if (_isExpanded) {
        _animationController.forward();
      } else {
        _animationController.reverse();
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.end,
      children: [
        if (_isExpanded) _buildOptionButton(Icons.dangerous, 'Dangerous'),
        if (_isExpanded) _buildOptionButton(Icons.delete, 'Delete'),
        if (_isExpanded) _buildOptionButton(Icons.edit, 'Edit'),
        FloatingActionButton(
          heroTag: 'Blah',
          onPressed: _toggleExpanded,
          tooltip: _isExpanded ? 'Close' : 'Open',
          backgroundColor: Color.fromARGB(255, 100, 100, 100),
          child: AnimatedBuilder(
            animation: _animationController,
            builder: (context, child) {
              return Transform.rotate(
                angle: _animation.value * 0.5 * 3.1415,
                child: Icon(
                  _isExpanded ? Icons.close : Icons.add,
                ),
              );
            },
          ),
        ),
      ],
    );
  }

  Widget _buildOptionButton(IconData iconData, String tooltip) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8.0),
      child: FloatingActionButton(
        backgroundColor: Color.fromARGB(255, 100, 100, 100),
        heroTag: tooltip,
        onPressed: () {},
        tooltip: tooltip,
        child: Icon(iconData),
      ),
    );
  }
}
yacmzcpb

yacmzcpb1#

尝试

Color.fromARGB(255, 67, 67, 67).withOpacity(0.5)

根据您的喜好自定义withOpacity(xx)

相关问题