簡體   English   中英

如何更改 Flutter/Dart 中按鈕的樣式和位置?

[英]How to change the style and location of buttons in Flutter/Dart?

我有一個代碼:

 // New Game route class NewGameRoute extends StatelessWidget { const NewGameRoute({key}); @override Widget build(BuildContext context) { return const MaterialApp( debugShowCheckedModeBanner: false, title: 'New Game', home: ListFromCSV1(), ); } } class ListFromCSV1 extends StatefulWidget { const ListFromCSV1({Key? key}): super(key: key); @override _ListFromCSVState1 createState() => _ListFromCSVState1(); } class _ListFromCSVState1 extends State<ListFromCSV1> { List<List<dynamic>> _listData = [ [""] ]; int _listCount = 0; bool _isFirstLoad = true; String assetPath = "files/main.jpg"; @override initState() { _loadCSV(); } // This function is only triggered at init, so we only load csv once void _loadCSV() async { String _rawData = await rootBundle.loadString("files/Text.csv"); _listData = const CsvToListConverter().convert(_rawData); } // This function is triggered when my button is pressed void _nextCSV() { setState(() { _listData = _listData; _listCount < _listData.length - 1? _isFirstLoad? _isFirstLoad = false: _listCount++: _listCount; // assetPath = _listData[_listCount][1] == ""? "files/main.jpg": _listData[_listCount][1]; assetPath = _listData[_listCount][1] == ""? assetPath: _listData[_listCount][1]; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('New Game'), ), body: Container( height: MediaQuery.of(context).size.height, decoration: BoxDecoration( image: DecorationImage( image: AssetImage(assetPath), fit: BoxFit.cover)), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ // const SizedBox(height: 30), ClipRRect( borderRadius: BorderRadius.circular(4), child: Stack( children: <Widget>[ Positioned.fill( child: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('files/sheet.jpg'), fit: BoxFit.cover)), ), ), Text( _listData[_listCount][0] ), ], ), ), // const SizedBox(height: 30), ClipRRect( borderRadius: BorderRadius.circular(4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextButton( style: TextButton.styleFrom( padding: const EdgeInsets.all(16.0), primary: Colors.white, textStyle: const TextStyle(fontSize: 20), ), // onPressed: () {}, onPressed: _nextCSV, child: const Text('OK'), ), TextButton( style: TextButton.styleFrom( padding: const EdgeInsets.all(16.0), primary: Colors.white, textStyle: const TextStyle(fontSize: 20), ), onPressed: () {}, // onPressed: _nextCSV, child: const Text('Hide'), ), ], ), ), ClipRRect( borderRadius: BorderRadius.circular(4), child: Stack( children: <Widget>[ Positioned.fill( child: Container( decoration: const BoxDecoration( gradient: LinearGradient( colors: <Color>[ Color(0xFF0D47A1), Color(0xFF1976D2), Color(0xFF42A5F5), ], ), ), ), ), TextButton( style: TextButton.styleFrom( padding: const EdgeInsets.all(16.0), primary: Colors.white, textStyle: const TextStyle(fontSize: 20), ), onPressed: _nextCSV, child: const Text('Show'), ), ], ), ), // const SizedBox(height: 30), ], ), ), ); } }

它看起來像這樣:

在此處輸入圖像描述

我需要它看起來像這樣:

在此處輸入圖像描述

  1. 如何使 sheet.jpg 圖像用作 OK 和 Hide 按鈕的背景? 現在它是純文本背景。

  2. 如何使 OK 和 Hide 按鈕與 Hide 按鈕具有相同的樣式? 我了解我需要使用以下代碼:

    邊界半徑:BorderRadius.circular(4),孩子:堆棧(孩子:[ Positioned.fill(孩子:容器(裝飾:const BoxDecoration(漸變:LinearGradient(colors:[顏色(0xFF0D47A1),顏色(0xFF1976D2),顏色(0xFF42A5F5) , ], ), ), ), ),

但是我對小部件的孩子感到困惑,這就是為什么代碼根本不想被執行。

這只是一個樣式問題,所以不要看類和函數。 謝謝你。

Edit1.I 希望這些按鈕具有來自 sheet.jpg 的背景,而屏幕的 rest 具有來自 main.jpg 的背景以及稍后取自 csv 文件的背景。

但如果我使用這段代碼:

 class ListFromCSV extends StatefulWidget { const ListFromCSV({Key? key}): super(key: key); @override _ListFromCSVState createState() => _ListFromCSVState(); } class _ListFromCSVState extends State<ListFromCSV> { List<List<dynamic>> _listData = [ [""] ]; int _listCount = 0; bool _isFirstLoad = true; String assetPath = "assets/files/main.jpeg"; @override void initState() { _loadCSV(); } // This function is only triggered at init, so we only load csv once void _loadCSV() async { String rawData = await rootBundle.loadString("assets/files/Text.csv"); _listData = const CsvToListConverter().convert(rawData); assetPath = _listData[_listCount][1] == ""? "assets/files/main.jpeg": _listData[_listCount][1]; } // This function is triggered when my button is pressed void _nextCSV() { setState(() { _listData = _listData; _listCount < _listData.length - 1? _isFirstLoad? _isFirstLoad = false: _listCount++: _listCount; assetPath = _listData[_listCount][1] == ""? assetPath: _listData[_listCount][1]; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('New Game'), ), body: Container( height: MediaQuery.of(context).size.height, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/files/sheet.jpeg"), fit: BoxFit.cover)), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( decoration: BoxDecoration( border: Border.all(color: Colors.yellow, width: 3) ), child: Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(4), child: Stack( children: <Widget>[ Positioned.fill( child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage(assetPath), fit: BoxFit.cover)), ), ), Text(_listData[_listCount][0]), ], ), ), ClipRRect( borderRadius: BorderRadius.circular(4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextButton( style: TextButton.styleFrom( side: BorderSide(color: Colors.yellow, width: 3), padding: const EdgeInsets.all(16.0), primary: Colors.white, backgroundColor: Colors.transparent, textStyle: const TextStyle(fontSize: 20), ), // onPressed: () {}, onPressed: _nextCSV, child: const Text('OK'), ), TextButton( style: TextButton.styleFrom( side: BorderSide(color: Colors.yellow, width: 3), padding: const EdgeInsets.all(16.0), primary: Colors.white, backgroundColor: Colors.transparent, textStyle: const TextStyle(fontSize: 20), ), onPressed: () {}, // onPressed: _nextCSV, child: const Text('Hide'), ), ], ), ), ], ), ), // your other widgets ], ), ), ); } }

它看起來像這樣:

在此處輸入圖像描述

我想要這個:

在此處輸入圖像描述

我知道我必須用 sheet.jpg 將現有按鈕包裝在容器中。 但是我一直丟失標點符號,這使得代碼根本不想運行。

編輯2。 如何使 sheet.jpg 不僅作為 OK 和 Hide 按鈕的背景,而且還作為它們之間的空間? 我示意性地描述了這一點:

在此處輸入圖像描述

我試圖將這些按鈕“提升”到一個容器中。 但是當我這樣做時:

 child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage('files/sheet.jpg'), fit: BoxFit.cover)), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ImageButton(label: 'OK', onButtonTap: _nextCSV), ImageButton(label: 'Hide', onButtonTap: () {}), ], ), ),

我收到一個錯誤:“A RenderFlex 在右側溢出了 46 個像素”

希望這對您有所幫助。 我創建了一個名為 ImageButton 的類似按鈕的小部件。

 class ListFromCSV extends StatefulWidget { const ListFromCSV({Key? key}): super(key: key); @override _ListFromCSVState createState() => _ListFromCSVState(); } class _ListFromCSVState extends State<ListFromCSV> { List<List<dynamic>> _listData = [ [""] ]; int _listCount = 0; bool _isFirstLoad = true; String assetPath = "assets/files/main.jpeg"; @override void initState() { _loadCSV(); } // This function is only triggered at init, so we only load csv once void _loadCSV() async { String rawData = await rootBundle.loadString("assets/files/Text.csv"); _listData = const CsvToListConverter().convert(rawData); assetPath = _listData[_listCount][1] == ""? "assets/files/main.jpeg": _listData[_listCount][1]; } // This function is triggered when my button is pressed void _nextCSV() { setState(() { _listData = _listData; _listCount < _listData.length - 1? _isFirstLoad? _isFirstLoad = false: _listCount++: _listCount; assetPath = _listData[_listCount][1] == ""? assetPath: _listData[_listCount][1]; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('New Game'), ), body: Container( height: MediaQuery.of(context).size.height, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/files/sheet.jpeg"), fit: BoxFit.cover)), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(4), child: Stack( children: <Widget>[ Positioned.fill( child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage(assetPath), fit: BoxFit.cover)), ), ), Text(_listData[_listCount][0]), ], ), ), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ ImageButton(label: 'OK', onButtonTap: _nextCSV), ImageButton(label: 'Hide', onButtonTap: () {}), ], ), ], ), // your other widgets ], ), ), ); } } class ImageButton extends StatelessWidget { const ImageButton({Key? key, required this.label, required this.onButtonTap}): super(key: key); final String label; final Function onButtonTap; @override Widget build(BuildContext context) { return InkWell( onTap: () => onButtonTap(), child: Container( // customize you button shape and size and design margin: const EdgeInsets.all(8), padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 32), decoration: const BoxDecoration( borderRadius: BorderRadius.all(Radius.circular(2)), image: DecorationImage( image: AssetImage("assets/files/main.jpeg"), // you can also pass the image dynamically with variable created for the widget. fit: BoxFit.cover)), child: Center( child: Text( label, style: const TextStyle( color: Colors.white, // you can get dominant colour on image and change the text color accordingly or apply shadows to the text fontWeight: FontWeight.w500, fontSize: 16), ), ), ), ); } }

您還可以創建一個新的 dart 文件並將 ImageButton 小部件代碼移動到該文件並導入並在您想要的任何地方使用它。 它將減少代碼行數並增加代碼的可重用性。

如果我理解正確,您可以將圖像添加到您的代碼中,然后以這種方式將其用於您的目的:請參閱此處 flutter 文檔

對於第二個問題,為了添加邊框,您需要使用容器以及容器內部的盒子裝飾和其他東西,但這取決於您想要的結果,請查看此處Stack 指

您可以像這樣將按鈕的背景指定為透明。

 class ListFromCSV extends StatefulWidget { const ListFromCSV({Key? key}): super(key: key); @override _ListFromCSVState createState() => _ListFromCSVState(); } class _ListFromCSVState extends State<ListFromCSV> { List<List<dynamic>> _listData = [ [""] ]; int _listCount = 0; bool _isFirstLoad = true; String assetPath = "assets/files/main.jpeg"; @override void initState() { _loadCSV(); } // This function is only triggered at init, so we only load csv once void _loadCSV() async { String rawData = await rootBundle.loadString("assets/files/Text.csv"); _listData = const CsvToListConverter().convert(rawData); assetPath = _listData[_listCount][1] == ""? "assets/files/main.jpeg": _listData[_listCount][1]; } // This function is triggered when my button is pressed void _nextCSV() { setState(() { _listData = _listData; _listCount < _listData.length - 1? _isFirstLoad? _isFirstLoad = false: _listCount++: _listCount; assetPath = _listData[_listCount][1] == ""? assetPath: _listData[_listCount][1]; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('New Game'), ), body: Container( height: MediaQuery.of(context).size.height, decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/files/sheet.jpeg"), fit: BoxFit.cover)), child: Column( mainAxisSize: MainAxisSize.min, children: <Widget>[ Container( decoration: BoxDecoration( border: Border.all(color: Colors.yellow, width: 3) ), child: Column( children: [ ClipRRect( borderRadius: BorderRadius.circular(4), child: Stack( children: <Widget>[ Positioned.fill( child: Container( decoration: BoxDecoration( image: DecorationImage( image: AssetImage(assetPath), fit: BoxFit.cover)), ), ), Text(_listData[_listCount][0]), ], ), ), ClipRRect( borderRadius: BorderRadius.circular(4), child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextButton( style: TextButton.styleFrom( side: BorderSide(color: Colors.yellow, width: 3), padding: const EdgeInsets.all(16.0), primary: Colors.white, backgroundColor: Colors.transparent, textStyle: const TextStyle(fontSize: 20), ), // onPressed: () {}, onPressed: _nextCSV, child: const Text('OK'), ), TextButton( style: TextButton.styleFrom( side: BorderSide(color: Colors.yellow, width: 3), padding: const EdgeInsets.all(16.0), primary: Colors.white, backgroundColor: Colors.transparent, textStyle: const TextStyle(fontSize: 20), ), onPressed: () {}, // onPressed: _nextCSV, child: const Text('Hide'), ), ], ), ), ], ), ), // your other widgets ], ), ), ); } }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM