Я только начал разработку приложений для Android, используя флаттер, и я учусь на этом.
Подробности о текущем проекте:
Я создаю симулятор игры в кости, в котором пользователь может нажать на нарисованные кости, чтобы бросить кости. Я добавил эффект вибрации, тост тоже. Теперь я хочу позволить пользователю изменять размер кубика с помощью ползунка.
Я нашел класс ползунка в документации.
Я также консультировался с этим потоком в stackoverflow. Тем не менее, я не могу полностью понять концепцию. Буду признателен за любую помощь.
Проблема:
Сказанный слайдер рендерится так, как он должен быть, но я не могу его перетащить.
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,
),
),
],
);
}
}
EDIT
Ниже приведен новый полный код с использованием функции обратного вызова. Я пометил обновленные строки кода, используя ~~.
Ранее проблема ползунка, неспособного перетащить, снова возникла. Мои подозрения в отношении линий, вызывающих проблемы, отмечены комментарием в коде.
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,
);
//~~ 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,
),
),
],
);
}
}
, так как это мой первый вопрос, прошу прощения за испорченный код и имена переменных.