【问题标题】:Force scroll to a widget when its visibility is true in flutter当小部件的可见性在颤动中为真时强制滚动到小部件
【发布时间】:2022-02-09 16:07:42
【问题描述】:

我的应用正在显示我的用户附近的汽车修理工信息。我有一个我写的谷歌地图小部件,包装在一个可见性小部件中。在用户单击按钮以显示地图之前,地图将保持不可见。这很好用,但是地图出现在屏幕的末尾,有时用户看不到它出现了。我想强制滚动向下以确保用户单击按钮后可以看到地图。 我尝试使用 VisibilityDetector 包来做到这一点,当小部件明显强制向下滚动时我使用回调,但这不起作用。

下面是我使用的简化代码(对不起,如果它仍然太长,但想给你完整的图片)

import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:flutter/material.dart';
import 'package:car_of_your_dreams/Services/mySQL_setup.dart';
import 'package:car_of_your_dreams/widgets/Manufacturers.dart';
import 'package:car_of_your_dreams/widgets/CarModels.dart';
import 'package:car_of_your_dreams/Services/carModelsLists.dart';
import 'package:car_of_your_dreams/widgets/carGoodandBadThings.dart';
import 'package:car_of_your_dreams/widgets/googleMaps.dart';
import 'package:visibility_detector/visibility_detector.dart';

class ShowLocation extends StatelessWidget {
  @override

  Widget build(BuildContext context) {
    return Material(
      child: Scaffold(
        backgroundColor: Colors.greenAccent,
        body: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            Padding(
              padding: const EdgeInsets.all(20.0),
              child: Row(
                mainAxisAlignment: MainAxisAlignment.end,
                children: [
                  ElevatedButton(onPressed:(){

                    Navigator.pushNamed(context, '1');
                  },
                      style: ButtonStyle(backgroundColor:MaterialStateProperty.all<Color>(Colors.lightGreen) ),
                      child: Text("Back to Home")),
                ],
              ),
            ),
            Text('Choose a car to know its rating, mechanics and more!', style: TextStyle(
              color: Colors.black,
              fontWeight: FontWeight.w700,
              fontSize: 33,
            ),),
            Expanded(child: CarDropDown())
          ],
        )
      )
    );

  }
}
class CarDropDown extends StatefulWidget {

  @override

  _CarDropDownState createState() => _CarDropDownState();
}
class _CarDropDownState extends State<CarDropDown> {
  final ScrollController _controller = ScrollController();
  Manufacturers? selectedManu;
  List<CarModel>?modelsforManu = [];
  bool isVisible = false;
  bool firstMapViz = false;
  bool secondMapViz = false;
  CarModel? selectedModel;
  var dropdownValue;
  var dropdownModel;
  var dropdownYear;
  String? agency;
  String? agencyWebSite;
  String? agencyPhone;
  String? agencyRating;
  String? maintenanceCost;
  String? carRating;
  String? firstMechanicName;
  String? firstMechanicPhone;
  String? firstMechanicLocation;
  String? secondMechanicName;
  String? secondMechanicPhone;
  String? secondMechanicLocation;
  num? latFirst;
  num? longFirst;
  num? latSecond;
  num? longSecond;
  late List<Manufacturers> cars;
  dynamic mechss;
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    cars =[Manufacturers('Toyota', mToyota),Manufacturers('JEEP', mJEEP), Manufacturers('KIA', mKIA), Manufacturers('FIAT', mFIAT), Manufacturers('Hyundai', mHyundai), Manufacturers('Mercedes', mMercedes),Manufacturers('BMW', mBMW), Manufacturers('SEAT', mSEAT), Manufacturers('VolksWagen', mVolksWagen), Manufacturers('Peugeot', mPeugeot), Manufacturers('Nissan', mNissan), Manufacturers('Suzuki', mSuzuki),];
  }
  @override


  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.start,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: [
        Row(children: <Widget>[
          Padding(
            padding: const EdgeInsets.all(10.0),
            child: DropdownButton<Manufacturers>(
                value: dropdownValue,
                hint:Text('Manufacturer', style: TextStyle(fontWeight: FontWeight.w700)),
                icon: Icon(Icons.precision_manufacturing_outlined),
                style:TextStyle(color: Colors.black) ,
                onChanged: (Manufacturers? newValue) {
                  setState(() {
                    dropdownValue = newValue;
                    selectedManu = dropdownValue;
                    dropdownModel = null;
                    modelsforManu= selectedManu?.models;
                    isVisible = false;
                    mechss = null;
                  });
                },
                items: cars.map((Manufacturers item){
                  return DropdownMenuItem<Manufacturers>(
                    value: item,
                    child: Container(
                        color: Colors.greenAccent,
                        child: Text(item.name)),
                  );
                }
                ).toList()
            ),
          ),

          Padding(
            padding: const EdgeInsets.all(10.0),
            child: DropdownButton<CarModel>(
                value: dropdownModel,
                hint:Text('Model', style: TextStyle(fontWeight: FontWeight.w700)),
                icon: Icon(Icons.category),
                style:TextStyle(color: Colors.black) ,
                onChanged: (CarModel? newValue) {
                  setState(() {
                    dropdownModel = newValue;
                    isVisible = false;
                    mechss = null;
                  });
                },
                items: modelsforManu?.map((CarModel item){
                  return DropdownMenuItem<CarModel>(
                    value: item,
                    child: Container(
                        color: Colors.greenAccent,
                        child: Text(item.name)),
                  );
                }
                ).toList()
            ),
          ),
        ElevatedButton(onPressed: () async {
          var carFetchedData= await MySQL().extractCarDetails(selectedManu?.name);
          var carBest = await MySQL().extractBestWorst(selectedManu?.name, dropdownModel.name);
          print(carBest);
          if(carBest=="no data, something went wrong"){
            print("only updating agency details");
          } else {
             
 mechss = await MySQL().getMechanicsForMyCar(selectedManu?.name, dropdownModel.name, dropdownYear);


          setState(() {
            isVisible = true;
            agency = carFetchedData['Agency'];
            agencyWebSite = carFetchedData['Site'];
            agencyPhone = carFetchedData['Phone'];
            agencyRating = carFetchedData['Agency_Rating'];
            maintenanceCost = carBest== "no data, something went wrong"? 'no data yet': carBest['HundredK'];
            carRating = carBest== "no data, something went wrong"? 'not rated yet': carBest['Rating_all'];
            
            if(mechss!="no mechanics aslan") {
              firstMechanicName = mechss[0]['mechanic'];
              firstMechanicPhone = mechss[0]['phone'];
                          firstMechanicLocation = mechss[0]['location'];
                     latFirst = num.tryParse(mechss[0]['Latitude'])?.toDouble();
              longFirst = num.tryParse(mechss[0]['Longitude'])?.toDouble();
                   }
             if(mechss is List && mechss.asMap().containsKey(1)){
                secondMechanicName = mechss[1]['mechanic'];
                secondMechanicPhone = mechss[1]['phone'];
                       secondMechanicLocation = mechss[1]['location'];
                       latSecond = num.tryParse(mechss[1]['Latitude'])?.toDouble();
                longSecond = num.tryParse(mechss[1]['Longitude'])?.toDouble();
                   } else{
               secondMechanicName = "";
               secondMechanicPhone = "";
                      secondMechanicLocation = "";
                      latSecond = 0;
               longSecond = 0;
                    }
            if(mechss=="no mechanics aslan"){
              firstMechanicName = "";
              firstMechanicPhone = "";
              firstMechanicLocation ="";
                     secondMechanicName = "";
              secondMechanicPhone = "";
              secondMechanicLocation = "";
                     latFirst = 0;
              longFirst = 0;
              latSecond = 0;
              longSecond = 0;
            };

          });

        },
          child: Text('Tell me all about this car!', style: TextStyle(fontSize: 20),),
        ),

        Visibility(
          visible: isVisible,
          child: Container(
            height: MediaQuery.of(context).size.height/1.5,
            alignment: Alignment.topLeft,
            padding: EdgeInsets.fromLTRB(15, 10, 10, 10),
            child: Scrollbar(
              isAlwaysShown: true,
              child: ListView.builder(
    itemCount: 1,
itemBuilder: (BuildContext context, int index){
return Column(
  mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RichText(text: TextSpan(text: 'Agency: ', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.white, fontWeight:FontWeight.w500 ) ),
    children:<TextSpan>[
      TextSpan(text: agency, style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.purple, fontWeight:FontWeight.w500 ) )),
    ])
),
  RichText(text: TextSpan(text: 'Agency web site: ', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.white, fontWeight:FontWeight.w500 ) ),
  children:<TextSpan>[
  TextSpan(text: agencyWebSite, style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.purple, fontWeight:FontWeight.w500 ) )),
    TextSpan(text: ' Phone: ', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.white, fontWeight:FontWeight.w500 ) ),),
    TextSpan(text: agencyPhone, style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.purple, fontWeight:FontWeight.w500 ) )),
  ])),
  RichText(text: TextSpan(text: 'Agency Rating:', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.white, fontWeight:FontWeight.w500 ) ),
      children:<TextSpan>[
          TextSpan(text: '$agencyRating /5', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.purple, fontWeight:FontWeight.w500 ) ))
      ])
  ),

  RichText(text: TextSpan(text: 'Car Rating:', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.white, fontWeight:FontWeight.w500 ) ),
      children:<TextSpan>[
          TextSpan(text:'$carRating /5', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.purple, fontWeight:FontWeight.w500 ) ))
      ])
  ),

  
  RichText(text: TextSpan(text: 'Best Mechanics for the car:', style: GoogleFonts.lato(textStyle:TextStyle(fontSize: 30, color: Colors.white, fontWeight:FontWeight.w500 ) ),
  ),),
  
  Scrollbar(
    isAlwaysShown: true,
    child: SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: DataTable(
          columns: [
              DataColumn(label: Text(
                  'Name',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),
              DataColumn(label: Text(
                  'Workshop',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),
              DataColumn(label: Text(
                  'Phone',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),
              DataColumn(label: Text(
                  'Phone2',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),
              DataColumn(label: Text(
                  'Specialty',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),
              DataColumn(label: Text(
                  'Location',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),
              DataColumn(label: Text(
                  'Map',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)
              )),

          ],
          rows: [
              DataRow(cells: [
                DataCell(Text(' $firstMechanicName')),
                DataCell(Text('$firstMechanicWorkshop')),
                DataCell(Text('$firstMechanicPhone')),
                DataCell(Text('$firstMechanicPhone2')),
                DataCell(Text('$firstSpecialty')),
                DataCell(Text('$firstMechanicLocation')),
                DataCell(ElevatedButton( onPressed: () {
                  setState(() {
                    firstMapViz = true;
                    secondMapViz = false;

                  });

                  },
                    child:Text('location on map'))),
              ]),
              DataRow(cells: [
                DataCell(Text(' $secondMechanicName')),
                DataCell(Text('$secondMechanicWorkshop')),
                DataCell(Text('$secondMechanicPhone')),
                DataCell(Text('$secondMechanicPhone2')),
                DataCell(Text('$secondSpecialty')),
                DataCell(Text('$secondMechanicLocation')),
                DataCell(ElevatedButton( onPressed: () {
                  setState(() {
                    firstMapViz = false;
                    secondMapViz = true;
                  });
                },
                    child:Text('location on map'))),
              ]),
          ]
      ),
    ),
  ),
  VisibilityDetector (
    key: ObjectKey("map2"),
    onVisibilityChanged: (VisibilityInfo info) {
      _controller.jumpTo(_controller.position.maxScrollExtent);
    },
    child: Visibility(
      key: ObjectKey("map2"),
          visible: secondMapViz,
      child: Container(
        height: 300,
        child: GoogleMap(latSecond,longSecond,"${Random().nextInt(100)}",secondMechanicName! ),
      ),
    ),
  ),
  Visibility(
    visible: firstMapViz,
    child: Container(
      height: 300,
      child: GoogleMap(latFirst,longFirst,"${Random().nextInt(100)}", firstMechanicName!),
    ),
  ),
],
);

}
),
            ),
          ),
        )
      ],
    );
  }


}

【问题讨论】:

    标签: flutter scrollbar visibility


    【解决方案1】:

    首先,你需要在 ListView 中设置控制器

     ListView.builder(
        controller: _controller,
     )
    

    完成添加项目后使用_controller.jumpTo(_controller.position.maxScrollExtent);

    【讨论】:

    • 谢谢!在 listView 中添加一个控制器会响应,但它还没有给出我想要的响应。现在如果我向下滚动到地图,代码会阻止我向上,它总是跳到最后,但是当我按下按钮时,它不会自动向下滚动
    猜你喜欢
    • 2023-03-06
    • 2019-05-23
    • 2021-11-28
    • 2020-08-02
    • 1970-01-01
    • 2016-07-09
    • 1970-01-01
    • 2020-12-14
    • 2021-12-18
    相关资源
    最近更新 更多