【发布时间】:2019-03-16 10:45:25
【问题描述】:
我刚刚开始使用 Flutter 开发 Android 应用程序,并且我正在学习。
有关当前项目的详细信息: 我正在创建一个骰子模拟器,用户可以在其中点击绘制的骰子来掷骰子。我添加了振动效果,吐司也。现在我想让用户使用滑块修改骰子的大小。
我在文档中找到了slider class。 我还咨询了stackoverflow中的this线程。不过,我无法完全掌握这个概念。我将不胜感激。
问题:
所说的滑块确实呈现了它应该是的样子,但我似乎无法拖动它。
main.dart
import 'package:flutter/material.dart';
import 'package:do_dice/dice2D.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
void showToastText(int a) {
Fluttertoast
.cancel(); //to clear all scheduled toast call ; this is to make the toast cal seem instant responsive.
Fluttertoast.showToast(
msg: '$a',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.black87,
textColor: Colors.yellow,
fontSize: 14.0,
);
}
void main() {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Color.fromRGBO(0, 0, 0, 0.0), //status bar is transparent
),
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ROLL THE DICE',
theme: ThemeData(
brightness: Brightness.dark,
),
home: MyHomePage(title: 'ROLL THE DICE'),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Dice2D dice1 = new Dice2D(
size: 300.0,
borderWidth: 5.0,
displayInt: 2,
);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(
child: Text(
widget.title,
)),
),
body: Column(
children: <Widget>[
SliderDiceSize(
minValue: 100.0,
maxValue: 300.0,
title: "Set the size of dice:",
dice: dice1,
titleColor: Colors.yellow,
),
SliderBorderWidth(titleColor: Colors.yellow,title: "Set the border width of dice:",dice: dice1,minValue: 1.0,maxValue: 10.0,),
Expanded(child: Center(child: dice1)),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
//function to display the number on dice as a toast
showToastText(dice1.getDisplay());
},
backgroundColor: Colors.yellow,
tooltip: "Show the number.",
child: Icon(Icons.message),
),
);
}
}
dice2D.dart
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:vibration/vibration.dart';
void vibrateDiceRolling() {
Vibration.cancel();
Vibration.vibrate(duration: 50); //default is 500 ms
}
void showToastRolling() {
Fluttertoast
.cancel(); //to clear all scheduled toast call ; this is to make the toast call seem instant responsive.
Fluttertoast.showToast(
msg: "Roger that!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.black87,
textColor: Colors.white70,
fontSize: 14.0,
);
}
class paintDice2D extends StatelessWidget {
@override
@required
final int display;
@required
final double borderWidth;
@required
final Color diceColor;
@required
final double diceSize;
paintDice2D(
{Key key, this.diceSize, this.display, this.borderWidth, this.diceColor})
: super(key: key);
Widget drawEmptyBox() {
return Center(
child: Container(),
);
}
Widget drawCircleDot() {
return Center(
child: Container(
decoration: BoxDecoration(shape: BoxShape.circle, color: diceColor),
),
);
}
Widget build(BuildContext context) {
double divSize = (diceSize - 2 * borderWidth) / 3;
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
border: Border.all(
color: diceColor, width: borderWidth, style: BorderStyle.solid),
),
height: diceSize,
width: diceSize,
child: Row(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 3 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(), // condition == true ? {code for true } : {code for false}
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child:
(display == 6) == true ? drawCircleDot() : drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 2 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(),
),
],
),
Column(
children: <Widget>[
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 1 || display == 3 || display == 5) == true
? drawCircleDot()
: drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: drawEmptyBox(),
),
],
),
Column(
children: <Widget>[
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 2 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child:
(display == 6) == true ? drawCircleDot() : drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 3 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(),
),
],
),
],
),
);
}
}
class Dice2D extends StatefulWidget {
@override
@required
double size;
@required
double borderWidth;
@required
int displayInt;
Dice2D({
Key key,
this.size,
this.borderWidth,
this.displayInt,
}) : super(key: key);
int getDisplay() {
return this.displayInt;
}
Dice2DState createState() {
return new Dice2DState();
}
}
class Dice2DState extends State<Dice2D> {
@override
Widget build(BuildContext context) {
int nextDisplay = Random().nextInt(6) + 1;
void rollDice() {
setState(() {
widget.displayInt = nextDisplay;
nextDisplay = Random().nextInt(6) + 1;
showToastRolling();
vibrateDiceRolling();
});
}
return FlatButton(
onPressed: () {
rollDice();
},
padding: EdgeInsets.all(0.0),
child: paintDice2D(
display: widget.displayInt,
borderWidth: widget.borderWidth,
diceSize: widget.size,
diceColor: Colors.yellow,
),
);
}
}
class SliderDiceSize extends StatefulWidget {
@required final String title;
@required Dice2D dice;
@required final double minValue;
@required final double maxValue;
@required final Color titleColor;
SliderDiceSize({Key key, this.title, this.dice, this.titleColor, this.maxValue, this.minValue}):super(key:key);
@override
SliderDiceSizeState createState() {
return new SliderDiceSizeState();
}
}
class SliderDiceSizeState extends State<SliderDiceSize> {
void setDiceSize(double a) {
setState(() {
int diceint = widget.dice.getDisplay(); //**
widget.dice.displayInt = diceint; //**
widget.dice.size = a; //**
});
}
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
widget.title,
style: TextStyle(color: widget.titleColor, fontSize: 16.0),
),
),
Container(
child: new Slider(
value: widget.dice.size, //**
onChanged: (double value) => setDiceSize(value), //**
max: widget.maxValue,
min: widget.minValue,
activeColor: Colors.grey,
inactiveColor: Colors.white12,
),
),
],
);
}
}
class SliderBorderWidth extends StatefulWidget {
@required
final String title;
@required
Dice2D dice;
@required final double minValue;
@required final double maxValue;
@required final Color titleColor;
SliderBorderWidth(
{Key key,
this.dice,
this.title,
this.minValue,
this.maxValue,
this.titleColor});
@override
SliderBorderWidthState createState() {
return new SliderBorderWidthState();
}
}
class SliderBorderWidthState extends State<SliderBorderWidth> {
void setBorderWidth(double a) {
setState(() {
int diceint = widget.dice.getDisplay(); //**
widget.dice.borderWidth = a; //**
});}
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
widget.title,
style: TextStyle(color: widget.titleColor, fontSize: 16.0),
),
),
Container(
child: new Slider(
value: widget.dice.borderWidth, //**
onChanged: (double value) => setBorderWidth(value), //**
max: widget.maxValue,
min: widget.minValue,
activeColor: Colors.grey,
inactiveColor: Colors.white12,
),
),
],
);
}
}
编辑
以下是使用回调函数的新完整代码。我已经使用 ~~ 标记了更新的代码行。 之前滑块无法拖动的问题再次弹出。代码中的注释标记了我对导致问题的行的怀疑。
main.dart
导入'package:flutter/material.dart';
import 'package:do_dice/dice2D.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
void showToastText(int a) {
Fluttertoast
.cancel(); //to clear all scheduled toast call ; this is to make the toast cal seem instant responsive.
Fluttertoast.showToast(
msg: '$a',
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.black87,
textColor: Colors.yellow,
fontSize: 14.0,
);
}
void main() {
SystemChrome.setSystemUIOverlayStyle(
SystemUiOverlayStyle(
statusBarColor: Color.fromRGBO(0, 0, 0, 0.0), //status bar is transparent
),
);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'ROLL THE DICE',
theme: ThemeData(
brightness: Brightness.dark,
),
home: MyHomePage(title: 'ROLL THE DICE'),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
Dice2D dice1 = new Dice2D(
size: 300.0,
borderWidth: 5.0,
displayInt: 2,
);
//~~ added this function to serve as callback
updateDiceSize(Dice2D dice,double size){
setState((){
dice.size = size;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Center(
child: Text(
widget.title,
)),
),
body: Column(
children: <Widget>[
SliderDiceSize(updateDiceSizeCallback: updateDiceSize(dice1,dice1.size), //~~passing the callback
minValue: 100.0,
maxValue: 300.0,
title: "Set the size of dice:",
dice: dice1,
titleColor: Colors.yellow,
),
Expanded(child: Center(child: dice1)),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
//function to display the number on dice as a toast
showToastText(dice1.getDisplay());
},
backgroundColor: Colors.yellow,
tooltip: "Show the number.",
child: Icon(Icons.message),
),
);
}
}
Dice2D.dart
import 'package:flutter/material.dart';
import 'dart:math';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:vibration/vibration.dart';
void vibrateDiceRolling() {
Vibration.cancel();
Vibration.vibrate(duration: 50); //default is 500 ms
}
void showToastRolling() {
Fluttertoast
.cancel(); //to clear all scheduled toast call ; this is to make the toast call seem instant responsive.
Fluttertoast.showToast(
msg: "Roger that!",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: Colors.black87,
textColor: Colors.white70,
fontSize: 14.0,
);
}
class PaintDice2D extends StatelessWidget {
@override
@required
final int display;
@required
final double borderWidth;
@required
final Color diceColor;
@required
final double diceSize;
PaintDice2D(
{Key key, this.diceSize, this.display, this.borderWidth, this.diceColor})
: super(key: key);
Widget drawEmptyBox() {
return Center(
child: Container(),
);
}
Widget drawCircleDot() {
return Center(
child: Container(
decoration: BoxDecoration(shape: BoxShape.circle, color: diceColor),
),
);
}
Widget build(BuildContext context) {
double divSize = (diceSize - 2 * borderWidth) / 3;
return Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(10.0)),
border: Border.all(
color: diceColor, width: borderWidth, style: BorderStyle.solid),
),
height: diceSize,
width: diceSize,
child: Row(
children: <Widget>[
Column(
children: <Widget>[
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 3 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(), // condition == true ? {code for true } : {code for false}
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child:
(display == 6) == true ? drawCircleDot() : drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 2 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(),
),
],
),
Column(
children: <Widget>[
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 1 || display == 3 || display == 5) == true
? drawCircleDot()
: drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: drawEmptyBox(),
),
],
),
Column(
children: <Widget>[
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 2 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child:
(display == 6) == true ? drawCircleDot() : drawEmptyBox(),
),
Container(
width: divSize,
height: divSize,
padding: EdgeInsets.all(divSize / 5),
child: (display == 3 ||
display == 4 ||
display == 5 ||
display == 6) ==
true
? drawCircleDot()
: drawEmptyBox(),
),
],
),
],
),
);
}
}
class Dice2D extends StatefulWidget {
@override
@required
double size;
@required
double borderWidth;
@required
int displayInt;
Dice2D({
Key key,
this.size,
this.borderWidth,
this.displayInt,
}) : super(key: key);
int getDisplay() {
return this.displayInt;
}
Dice2DState createState() {
return new Dice2DState();
}
}
class Dice2DState extends State<Dice2D> {
@override
Widget build(BuildContext context) {
int nextDisplay = Random().nextInt(6) + 1;
void rollDice() {
setState(() {
widget.displayInt = nextDisplay;
nextDisplay = Random().nextInt(6) + 1;
showToastRolling();
vibrateDiceRolling();
});
}
return FlatButton(
onPressed: () {
rollDice();
},
padding: EdgeInsets.all(0.0),
child: PaintDice2D(
display: widget.displayInt,
borderWidth: widget.borderWidth,
diceSize: widget.size,
diceColor: Colors.yellow,
),
);
}
}
class SliderDiceSize extends StatefulWidget {
@required final String title;
@required Dice2D dice;
@required final double minValue;
@required final double maxValue;
@required final Color titleColor;
@required Function updateDiceSizeCallback; //~~
SliderDiceSize({Key key, this.title, this.dice, this.titleColor, this.maxValue, this.minValue,this.updateDiceSizeCallback}):super(key:key); //~~
@override
SliderDiceSizeState createState() {
return new SliderDiceSizeState();
}
}
class SliderDiceSizeState extends State<SliderDiceSize> {
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(8.0),
child: new Text(
widget.title,
style: TextStyle(color: widget.titleColor, fontSize: 16.0),
),
),
Container(
child: new Slider(
value: widget.dice.size,
onChanged: (double value) => widget.updateDiceSizeCallback, //~~ I believe something needs to change here for slider to be able to drag.
max: widget.maxValue,
min: widget.minValue,
activeColor: Colors.grey,
inactiveColor: Colors.white12,
),
),
],
);
}
}
因为这是我在这里的第一个问题,我为混乱的代码和变量名道歉。
【问题讨论】:
-
你能分享完整的代码/回购吗?也许我可以稍后再检查。
-
我包含了完整的代码。顺便说一句,我在 SliderDiceSizeState 类(由 ** 标记)中搞砸了一点,并以某种方式让滑块能够拖动。但是新的问题出现了。当滑块被拖动时,它不会更新 Dice2D 对象的状态,但是当点击骰子本身(Dice2DState 中的函数 rolldice())时,它会根据滑块设置的值设置它的新大小。我应该编辑问题本身吗?
-
我在答案中添加了一个示例。也许这会让事情更清楚。