flutter 我如何使我的选项卡栏显示活动的颜色当用户点击它

v9tzhpje  于 2022-12-14  发布在  Flutter
关注(0)|答案(1)|浏览(106)

我在flutter选项卡栏中有4个选项卡。我使用的是银应用程序栏,选项卡栏位于银色应用程序栏的底部属性中。我在SingleChilScrollView中有4个不同大小的容器。单击每个选项卡时,屏幕滚动到特定容器。我有3个问题:
1.第一个是当我点击标签的时候,它会滚动容器,比我想要的要多一点。2我想要在屏幕上显示容器顶部(里面有文本)。
1.第二个问题(也是最重要的一个)是,当我单击选项卡时,它会将屏幕滚动到特定容器,但选项卡的活动颜色表现不正常(有时它会显示活动选项卡,有时则不会)。
1.当我调整网页屏幕大小时,选项卡没有滚动到准确的容器位置。
让我们假设一种情况,当用户点击第3个选项卡时,预期结果将是该选项卡将通过显示蓝线而激活,并且屏幕将滚动到第3个容器。获得的结果是屏幕滚动到第3个容器,但选项卡活动颜色(蓝色)无法正常工作。
预期的结果是:expected result
得到的结果是:gained result
可以运行的代码如下:

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

class ScrollContainerPage extends StatefulWidget {
  @override
  State<ScrollContainerPage> createState() => _ScrollContainerPageState();
}

class _ScrollContainerPageState extends State<ScrollContainerPage> {
  ScrollController _scrollController = ScrollController();
  List<GlobalKey> _globalKey = List.empty(growable: true);
  late final secondContainerPosition;
  late final thirdContainerPosition;
  late final fourthContainerPosition;
  bool initilized = false;
  @override
  void initState() {
    for (int i = 0; i < 4; i++) {
      _globalKey.add(GlobalKey());
    }
    super.initState();
  }
  getPosition() {
    RenderBox box2 =
        _globalKey[1].currentContext!.findRenderObject()! as RenderBox;
    Offset position2 = box2.localToGlobal(Offset.zero);

    if (!initilized) {
      secondContainerPosition = position2.dy;
    }
    RenderBox box3 =
        _globalKey[2].currentContext!.findRenderObject()! as RenderBox;
    Offset position3 = box3.localToGlobal(Offset.zero);
    if (!initilized) {
      thirdContainerPosition = position3.dy;
    }

    RenderBox box4 =
    _globalKey[3].currentContext!.findRenderObject()! as RenderBox;
    Offset position4 = box4.localToGlobal(Offset.zero);
    if (!initilized) {
      fourthContainerPosition = position4.dy;
    }
    initilized = true;
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 4,
        child: NestedScrollView(
          floatHeaderSlivers: false,
          headerSliverBuilder:
              (BuildContext context, bool innerBoxIsScrolled) {
            return  [
              SliverAppBar(
                leadingWidth: 200,
                centerTitle: true,
                //titleSpacing: 0,
                //expandedHeight: 200.0,
                backgroundColor: Colors.white,
                leading: const Icon(Icons.arrow_back_ios,color: Colors.black,),
                title: !kIsWeb? const Text("About us",
                  style: TextStyle(
                    color: Colors.black,
                    fontSize: 16.0,
                  ),
                ):
                SizedBox(
                  height: 40,
                  width: MediaQuery.of(context).size.width*0.5,
                  child: Center(
                    child: TextField(
                      cursorColor: const Color.fromRGBO(0, 79, 224, 1),
                      //maxLines: 5,
                      decoration: InputDecoration(
                        contentPadding: const EdgeInsets.symmetric(horizontal: 20),
                        prefixIcon: const Icon(Icons.search),
                        prefixIconColor: Colors.red,
                        border: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Color.fromRGBO(118, 118, 128, 1), width: 2),
                        ),
                        enabledBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Color.fromRGBO(118, 118, 128, 1), width: 1.5),
                        ),
                        focusedBorder: OutlineInputBorder(
                          borderRadius: BorderRadius.circular(20),
                          borderSide: const BorderSide(color: Color.fromRGBO(0, 79, 224, 1), width: 1.5),
                        ),
                      ),
                    ),
                  ),
                ),

                actions: kIsWeb?[

                  Container(
                    margin: const EdgeInsets.fromLTRB(12,12,80,12),
                    padding: const  EdgeInsets.symmetric(vertical: 5,horizontal: 30),
                    decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(20),
                      border: Border.all(color: const Color.fromRGBO(4, 80, 225, 1)),
                    ),
                    child: InkWell(
                      onTap: (){

                      },
                      child: Row(
                        children: const [
                          Icon(Icons.person_outline,
                            color: Color.fromRGBO(4, 80, 225, 1),
                          ),
                          SizedBox(width: 10,),
                          Text('Sign in',
                            style: TextStyle(
                              color:  Color.fromRGBO(4, 80, 225, 1),
                              fontSize: 14.0,
                              // fontWeight: FontWeight.w600,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ]:null,

                floating: !kIsWeb?true: false,
                pinned: true,
                snap: !kIsWeb?true: false,
                      bottom: TabBar(
                          indicatorColor: const Color.fromRGBO(0, 79, 224, 1),
                          tabs:  [
                            Tab(icon: GestureDetector(
                                onTap: (){
                                  setState(() {
                                    getPosition();
                                    _scrollController.animateTo(
                                        _scrollController.position.minScrollExtent,
                                        duration: const Duration(milliseconds: 500),
                                        curve: Curves.ease);
                                  });

                                },
                                child: const Text('scroll to red container', style: TextStyle(color: Colors.black),)),),
                            Tab(icon: GestureDetector(
                                onTap: (){
                                  setState(() {
                                    getPosition();
                                    _scrollController.animateTo(secondContainerPosition,
                                        // !kIsWeb ? 1140 : 1000,
                                        duration: const Duration(milliseconds: 500),
                                        curve: Curves.ease);
                                  });
                                },
                                child: const Text('scroll to yellow container', style: TextStyle(color: Colors.black),)),),
                            Tab(icon: GestureDetector(
                                onTap: (){
                                  setState(() {
                                    getPosition();
                                    _scrollController.animateTo(thirdContainerPosition,
                                        // !kIsWeb ? 3380 : 2000,
                                        duration: const Duration(milliseconds: 500),
                                        curve: Curves.ease);
                                  });
                                },
                                child: const Text('scroll to pink container', style: TextStyle(color: Colors.black),)),),
                            Tab(icon: GestureDetector(
                                onTap: (){
                                  setState(() {
                                    getPosition();
                                    _scrollController.animateTo(fourthContainerPosition,
                                        // _scrollController.position.maxScrollExtent,
                                        duration: const Duration(milliseconds: 500),
                                        curve: Curves.ease);
                                  });
                                },
                                child: const Text('scroll to orange container', style: TextStyle(color: Colors.black),)),),
                          ]
                      ),

              ),
            ];
          },
          body:
              SingleChildScrollView(
                controller: _scrollController,
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.stretch,
                  children: [
                    Container(
                        key: _globalKey[0],
                        height: 1000,
                        color: Colors.red,
                        child: const Text('red container')
                    ),
                    const SizedBox(
                      height: 30,
                    ),


                    Container(
                        key: _globalKey[1],
                        height: 1700,
                        color: Colors.yellow,
                        child: Text('yellow  Container')
                    ),
                    const SizedBox(
                      height: 30,
                    ),



                    Container(
                        key: _globalKey[2],
                        height: 3000,
                        color: Colors.pink,
                        child: Text('pink Container')
                    ),
                    const SizedBox(
                      height: 30,
                    ),



                    Container(
                      key: _globalKey[3],
                        height: 500,
                        color: Colors.orange,
                        child: Text('orange Container'),
                    ),
                    const SizedBox(
                      height: 30,
                    ),

                  ],
                ),
              ),

        ),
      ),
    );

  }
}
g52tjvyc

g52tjvyc1#

这里我已经解决了您的问题,您将GestureDetector添加到所有单独的选项卡中,这阻碍了实际TabBar上的点击区域,您需要做的是使用TabBar本身的onTap方法:

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

class ScrollContainerPage extends StatefulWidget {
  @override
  State<ScrollContainerPage> createState() => _ScrollContainerPageState();
}

class _ScrollContainerPageState extends State<ScrollContainerPage> {
  ScrollController _scrollController = ScrollController();
  List<GlobalKey> _globalKey = List.empty(growable: true);
  late final secondContainerPosition;
  late final thirdContainerPosition;
  late final fourthContainerPosition;
  bool initilized = false;
  @override
  void initState() {
    for (int i = 0; i < 4; i++) {
      _globalKey.add(GlobalKey());
    }
    super.initState();
  }

  getPosition() {
    RenderBox box2 =
        _globalKey[1].currentContext!.findRenderObject()! as RenderBox;
    Offset position2 = box2.localToGlobal(Offset.zero);

    if (!initilized) {
      secondContainerPosition = position2.dy;
    }
    RenderBox box3 =
        _globalKey[2].currentContext!.findRenderObject()! as RenderBox;
    Offset position3 = box3.localToGlobal(Offset.zero);
    if (!initilized) {
      thirdContainerPosition = position3.dy;
    }

    RenderBox box4 =
        _globalKey[3].currentContext!.findRenderObject()! as RenderBox;
    Offset position4 = box4.localToGlobal(Offset.zero);
    if (!initilized) {
      fourthContainerPosition = position4.dy;
    }
    initilized = true;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: DefaultTabController(
        length: 4,
        child: NestedScrollView(
          floatHeaderSlivers: false,
          headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) {
            return [
              SliverAppBar(
                leadingWidth: 200,
                centerTitle: true,
                //titleSpacing: 0,
                //expandedHeight: 200.0,
                backgroundColor: Colors.white,
                leading: const Icon(
                  Icons.arrow_back_ios,
                  color: Colors.black,
                ),
                title: !kIsWeb
                    ? const Text(
                        "About us",
                        style: TextStyle(
                          color: Colors.black,
                          fontSize: 16.0,
                        ),
                      )
                    : SizedBox(
                        height: 40,
                        width: MediaQuery.of(context).size.width * 0.5,
                        child: Center(
                          child: TextField(
                            cursorColor: const Color.fromRGBO(0, 79, 224, 1),
                            //maxLines: 5,
                            decoration: InputDecoration(
                              contentPadding:
                                  const EdgeInsets.symmetric(horizontal: 20),
                              prefixIcon: const Icon(Icons.search),
                              prefixIconColor: Colors.red,
                              border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(20),
                                borderSide: const BorderSide(
                                    color: Color.fromRGBO(118, 118, 128, 1),
                                    width: 2),
                              ),
                              enabledBorder: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(20),
                                borderSide: const BorderSide(
                                    color: Color.fromRGBO(118, 118, 128, 1),
                                    width: 1.5),
                              ),
                              focusedBorder: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(20),
                                borderSide: const BorderSide(
                                    color: Color.fromRGBO(0, 79, 224, 1),
                                    width: 1.5),
                              ),
                            ),
                          ),
                        ),
                      ),

                actions: kIsWeb
                    ? [
                        Container(
                          margin: const EdgeInsets.fromLTRB(12, 12, 80, 12),
                          padding: const EdgeInsets.symmetric(
                              vertical: 5, horizontal: 30),
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(20),
                            border: Border.all(
                                color: const Color.fromRGBO(4, 80, 225, 1)),
                          ),
                          child: InkWell(
                            onTap: () {},
                            child: Row(
                              children: const [
                                Icon(
                                  Icons.person_outline,
                                  color: Color.fromRGBO(4, 80, 225, 1),
                                ),
                                SizedBox(
                                  width: 10,
                                ),
                                Text(
                                  'Sign in',
                                  style: TextStyle(
                                    color: Color.fromRGBO(4, 80, 225, 1),
                                    fontSize: 14.0,
                                    // fontWeight: FontWeight.w600,
                                  ),
                                ),
                              ],
                            ),
                          ),
                        ),
                      ]
                    : null,

                floating: !kIsWeb ? true : false,
                pinned: true,
                snap: !kIsWeb ? true : false,
                bottom: TabBar(
                    indicatorColor: const Color.fromRGBO(0, 79, 224, 1),
                    onTap: (pos){ //added the onTap function with different functions for different pos values
                      if(pos==0){
                        setState(() {
                          getPosition();
                          _scrollController.animateTo(
                              _scrollController.position.minScrollExtent,
                              duration: const Duration(milliseconds: 500),
                              curve: Curves.ease);
                        });
                      }else if(pos==1){
                        setState(() {
                          getPosition();
                          _scrollController.animateTo(
                              secondContainerPosition,
                              // !kIsWeb ? 1140 : 1000,
                              duration: const Duration(milliseconds: 500),
                              curve: Curves.ease);
                        });
                      } else if(pos==2){
                        setState(() {
                          getPosition();
                          _scrollController.animateTo(
                              thirdContainerPosition,
                              // !kIsWeb ? 3380 : 2000,
                              duration: const Duration(milliseconds: 500),
                              curve: Curves.ease);
                        });
                      } else{
                          setState(() {
                            getPosition();
                            _scrollController.animateTo(
                                fourthContainerPosition,
                                // _scrollController.position.maxScrollExtent,
                                duration: const Duration(milliseconds: 500),
                                curve: Curves.ease);
                          });
                      }
                    },
                    tabs: [
                      Tab(
                        icon: const Text(
                          'scroll to red container',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      Tab(
                        icon: const Text(
                          'scroll to yellow container',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      Tab(
                        icon: const Text(
                          'scroll to pink container',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                      Tab(
                        icon: const Text(
                          'scroll to orange container',
                          style: TextStyle(color: Colors.black),
                        ),
                      ),
                    ]),
              ),
            ];
          },
          body: SingleChildScrollView(
            controller: _scrollController,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: [
                Container(
                    key: _globalKey[0],
                    height: 1000,
                    color: Colors.red,
                    child: const Text('red container')),
                const SizedBox(
                  height: 30,
                ),
                Container(
                    key: _globalKey[1],
                    height: 1700,
                    color: Colors.yellow,
                    child: Text('yellow  Container')),
                const SizedBox(
                  height: 30,
                ),
                Container(
                    key: _globalKey[2],
                    height: 3000,
                    color: Colors.pink,
                    child: Text('pink Container')),
                const SizedBox(
                  height: 30,
                ),
                Container(
                  key: _globalKey[3],
                  height: 500,
                  color: Colors.orange,
                  child: Text('orange Container'),
                ),
                const SizedBox(
                  height: 30,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}

相关问题