粘性标题效果
带有粘性标题的每个部分都应该是带有 SliverPinnedHeader 和 SliverList 的多条。然后将 pushPinnedChildren 设置为 true 应该会提供您正在寻找的粘性标题效果。
flutter - 如何将Gridview放在Column小部件中的Card小部件附近
正在尝试为我的应用创建用户界面。我需要这样设计:但是我最近的用户界面如下所示:在第二个屏幕截图中,我向下滚动是因为我的gridview小部件(具有4个卡式小部件)没有更接近其他小部件。其他小部件是:标题栏小部件,具有图形和子图小部件的卡片小部件。我将标题栏和图形卡小部件放在堆栈中以在上方显示它们。我将这两个组合的小部件与gridview小部件一起放在一列中。我用SingleChildScrollView小部件包装此列小部件,因为我希望页面可滚动。 因此,我的问题是:如何像第一个图像那样将gridview小部件放置得更靠近卡片小部件?这是我用于此UI的代码:
import 'package:flutter/material.dart'; import 'package:flutter_circular_chart/flutter_circular_chart.dart'; import 'package:intl/intl.dart'; import 'baskana_rapor_icon_icons.dart'; // ignore: must_be_immutable class MainPage extends StatelessWidget { List<Widget> widgets = new List(); List<CircularSegmentEntry> dataList = _loadData(); int _totalCount; Widget s1, s2, total; final formatter = new NumberFormat("#,##"); @override Widget build(BuildContext context) { widgets.add(_buildBody(context)); return Scaffold(body: _buildBody(context)); } Widget _buildBody(BuildContext context) { return LayoutBuilder( builder: (BuildContext context, BoxConstraints viewportConstraints) { return SingleChildScrollView( child: Column( crossAxisAlignment: CrossAxisAlignment.center, //mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Stack( children: <Widget>[ Container( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, ), _buildTitleBar(context), Positioned(bottom: 65, left: 35, child: _buildCard(context)), ], ), _buildGridButtons(context), ], ), ); }, ); } Widget _buildGridButtons(BuildContext context) { int itemWidth = 80; int itemHeight = 40; return SafeArea( child: Column( children: [ GridView.count( crossAxisCount: 2, childAspectRatio: (itemWidth / itemHeight), shrinkWrap: true, primary: true, children: [ GestureDetector( onTap: () { Navigator.pushNamed(context, '/MahalleRapor'); }, child: Card( color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(25), ), ), child: Stack( alignment: Alignment.center, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( BaskanaRaporIcon.mahalle_raporu, color: Colors.redAccent, size: 30, ), Text( 'Mahalle Raporu', style: TextStyle( color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold, ), ), SizedBox( height: 5, ) ], ), Positioned( bottom: 0, right: 1, left: 1, child: Divider( color: Colors.redAccent, endIndent: 45, indent: 50, thickness: 3, ), ), ], ), ), ), GestureDetector( onTap: () { Navigator.pushNamed(context, '/BirimRapor'); }, child: Card( color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(25), ), ), child: Stack( alignment: Alignment.center, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( BaskanaRaporIcon.birim_raporu, color: Colors.green[300], size: 30, ), Text( 'Birim Raporu', style: TextStyle( color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold, ), ), SizedBox( height: 5, ) ], ), Positioned( bottom: 0, right: 1, left: 1, child: Divider( color: Colors.green[300], endIndent: 45, indent: 50, thickness: 3, ), ), ], ), ), ), GestureDetector( onTap: () { Navigator.pushNamed(context, '/GelirGider'); }, child: Card( color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(25), ), ), child: Stack( alignment: Alignment.center, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( BaskanaRaporIcon.gelir_gider, color: Colors.yellow[700], size: 30, ), Text( 'Gelir / Gider', style: TextStyle( color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold, ), ), SizedBox( height: 5, ) ], ), Positioned( bottom: 0, right: 1, left: 1, child: Divider( color: Colors.yellow[700], endIndent: 45, indent: 50, thickness: 3, ), ), ], ), ), ), GestureDetector( onTap: () { Navigator.pushNamed(context, '/BaskanaMesaj'); }, child: Card( color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.all( Radius.circular(25), ), ), child: Stack( alignment: Alignment.center, children: [ Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Icon( BaskanaRaporIcon.baskana_msg, color: Colors.blueAccent, size: 30, ), Text( 'Başkana Mesaj', style: TextStyle( color: Colors.black87, fontSize: 20, fontWeight: FontWeight.bold, ), ), SizedBox( height: 5, ) ], ), Positioned( bottom: 0, right: 1, left: 1, child: Divider( color: Colors.blueAccent, endIndent: 45, indent: 50, thickness: 3, ), ), ], ), ), ), ], ) ], ), ); } // ignore: todo //TODO: Better implementation of UI final double buttonHeight = 50; Widget _buildCard(BuildContext context) { return Center( child: Container( height: 500 + buttonHeight, child: Stack( alignment: Alignment.center, overflow: Overflow.visible, children: [ Card( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(15), side: BorderSide(color: Colors.blueGrey, width: 0.5), ), child: Container( height: MediaQuery.of(context).size.height * .65, width: MediaQuery.of(context).size.width * .80, child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisSize: MainAxisSize.max, children: <Widget>[ Padding( padding: const EdgeInsets.all(8.0), child: Text( "Genel Durum", style: TextStyle( fontSize: 20, color: Colors.black, letterSpacing: 0.3, ), ), ), Divider( color: Colors.grey, thickness: 0.3, endIndent: 10, indent: 10, ), _buildChart(dataList), SizedBox( height: 20, ), _buildSubGraph(), SizedBox( height: 40, ), ], ), ), ), Positioned( //top: -buttonHeight /2, bottom: 27, child: _buildDetailsButton(context), ), ], ), ), ); } Widget _buildDetailsButton(BuildContext context) { return ButtonTheme( height: 50, minWidth: 100, child: RaisedButton( onPressed: () { Navigator.pushNamed(context, '/DetailPage'); }, color: Colors.white, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(30), ), child: Text("Detayları Gör"), ), ); } Row _buildSubGraph() { String s1 = formatter.format((dataList[1].value / _totalCount) * 100); String s0 = formatter.format((dataList[0].value / _totalCount) * 100); return Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ Column( //İşlemde children: [ Text( dataList[1].rankKey, style: TextStyle( fontSize: 18, color: Colors.black87, ), ), Container( decoration: BoxDecoration( color: dataList[1].color, borderRadius: BorderRadius.only( topRight: Radius.circular(5), bottomRight: Radius.circular(5), bottomLeft: Radius.circular(5), ), ), height: 50, width: 150, child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( '${dataList[1].value.toInt()}', style: TextStyle( color: Colors.white, fontSize: 20, ), ), SizedBox( width: 50, ), Flexible( child: Text( '%' + s1, style: TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w300, ), ), ), ], ), ), ], ), Column( //Sonuçlanan mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Text( dataList[0].rankKey, style: TextStyle( fontSize: 18, color: Colors.black87, ), ), Container( height: 50, width: 150, decoration: BoxDecoration( color: dataList[0].color, borderRadius: BorderRadius.only( topRight: Radius.circular(5), bottomRight: Radius.circular(5), bottomLeft: Radius.circular(5), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.center, children: [ Text( '${dataList[0].value.toInt()}', style: TextStyle( color: Colors.white, fontSize: 20, ), ), SizedBox( width: 50, ), Flexible( child: Text( '%' + s0, style: TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w300, ), ), ), ], ), ), ], ) ], ); } //Map<String, double> dataMap, List<Color> colorList,BuildContext context Widget _buildChart(List<CircularSegmentEntry> dataList) { _totalCount = _findTotalCount(dataList); s1 = _createText("TOPLAMDA", 20, Colors.grey[600], false); s1 = _createText("TALEP", 20, Colors.grey[600], false); total = _createText('$_totalCount', 24, Colors.black87, true); return Container( child: AnimatedCircularChart( size: Size(500, 250), initialChartData: <CircularStackEntry>[ CircularStackEntry( <CircularSegmentEntry>[ dataList[0], dataList[1], ], ), ], chartType: CircularChartType.Radial, startAngle: -90, holeRadius: 25, holeLabel: "TOPLAMDA \n\t\t\t\t\t\t\t $_totalCount \n\t\t\t TALEP", // $s1 \n\t\t\t\t\t\t\t $total \n\t\t\t $s2 ), ); } Widget _buildTitleBar(BuildContext context) { return Align( alignment: Alignment.topCenter, child: Column( children: <Widget>[ Container( height: MediaQuery.of(context).size.height * .247, decoration: BoxDecoration( color: Colors.blue, shape: BoxShape.rectangle, borderRadius: BorderRadius.vertical( bottom: Radius.circular(25), ), ), child: Row( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon( Icons.assessment, color: Colors.white, ), Text( "Genel Durum", style: TextStyle( color: Colors.white, fontSize: 28, fontWeight: FontWeight.bold, letterSpacing: 0.5, ), ), ], ), ), ], ), ); } } Widget _createText(String msg, double size, Color color, bool isBold) { return Text( msg, style: TextStyle( color: color, fontSize: size, fontWeight: isBold ? FontWeight.bold : FontWeight.normal, ), ); } int _findTotalCount(List<CircularSegmentEntry> dataList) { int result = 0; for (int i = 0; i < dataList.length; i++) { result += (dataList[i].value).toInt(); } return result; } List<CircularSegmentEntry> _loadData() { List<CircularSegmentEntry> dataList = []; CircularSegmentEntry chartData1 = new CircularSegmentEntry(150, Colors.greenAccent, rankKey: 'Sonuçlanan'); CircularSegmentEntry chartData2 = new CircularSegmentEntry(150, Colors.blue, rankKey: 'İşlemde'); dataList.add(chartData1); dataList.add(chartData2); return dataList; } 复制代码
额外的问题:如果我可以做些更有效的设计,您能告诉我吗?谢谢!
最佳答案
也许是由于堆栈中的这段代码而发生的。此容器占用您的全屏尺寸。这就是为什么您的GridView项目会在屏幕大小之后立即生成。尝试删除此容器或减小其高度。
Container( height: MediaQuery.of(context).size.height, width: MediaQuery.of(context).size.width, ), 复制代码
更新:你可以试试看我没有尝试过,但这也许会有所帮助
Stack( children: <Widget>[ Align( alignment: Alignment.topCenter, child: _buildTitleBar(context), ), Align( alignment: Alignment.topCenter, child: Container( margin: EdgeInsets.only(top: 100), child: _buildCard(context), ), ) ], )