0% found this document useful (0 votes)
16 views

lab1

Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
16 views

lab1

Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 27

ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІВЕРСИТЕТ

Кафедра комп'ютерних наук та системного аналізу

ЗВІТ
з дисципліни «Розробка крос-платформних мобільних застосунків»
з лабораторної роботи №1
тема: “Створення користувацьких інтерфейсів за допомогою Flutter. Написання
першого додатку для Flutter в Інтернеті”

Перевірив: Виконав:
к.т.н., доцент студент 3 курсу, КМ-2205
Григорій ЗАСПА Богдан ФЕДОРЕНКО

Черкаси 2024 н.р.


Тема: “Створення користувацьких інтерфейсів за допомогою Flutter. Написання
першого додатку для Flutter в Інтернеті”.
Мета роботи: Навчитись розробляти прості користувацькі інтерфейси за
допомогою Flutter. Навчитись писати перші додатки для Flutter в Інтернеті.

Завдання
1. Зробити програми за туторіалами Building user interfaces with Flutter
https://docs.flutter.dev/ui#bringing-it-all-together
2. Зробити програми за туторіалами Write your first Flutter app on the web -
адаптувати до мобільного
https://docs.flutter.dev/get-started/codelab-web

Хід роботи
Код програми
import 'package:flutter/material.dart';

void main() {
runApp(
const Center(
child: Text(
'Hello, world!',
textDirection: TextDirection.ltr,
),
),
);
}

1
Результат

import 'package:flutter/material.dart';

class MyAppBar extends StatelessWidget {


const MyAppBar({required this.title, super.key});

// Fields in a Widget subclass are always marked "final".

final Widget title;

@override
Widget build(BuildContext context) {
return Container(
height: 56, // in logical pixels
padding: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(color: Colors.blue[500]),
// Row is a horizontal, linear layout.
child: Row(
children: [
const IconButton(
icon: Icon(Icons.menu),

2
tooltip: 'Navigation menu',
onPressed: null, // null disables the button
),
// Expanded expands its child
// to fill the available space.
Expanded(
child: title,
),
const IconButton(
icon: Icon(Icons.search),
tooltip: 'Search',
onPressed: null,
),
],
),
);
}
}

class MyScaffold extends StatelessWidget {


const MyScaffold({super.key});

@override
Widget build(BuildContext context) {
// Material is a conceptual piece
// of paper on which the UI appears.
return Material(
// Column is a vertical, linear layout.
child: Column(
children: [

3
MyAppBar(
title: Text(
'Example title',
style: Theme.of(context) //
.primaryTextTheme
.titleLarge,
),
),
const Expanded(
child: Center(
child: Text('Hello, world!'),
),
),
],
),
);
}
}

void main() {
runApp(
const MaterialApp(
title: 'My app', // used by the OS task switcher
home: SafeArea(
child: MyScaffold(),
),
),
);
}

4
Результат

import 'package:flutter/material.dart';

void main() => runApp(const SignUpApp());

class SignUpApp extends StatelessWidget {


const SignUpApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => const SignUpScreen(),
},
);
}
}
5
class SignUpScreen extends StatelessWidget {
const SignUpScreen({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
body: const Center(
child: SizedBox(
width: 400,
child: Card(
child: SignUpForm(),
),
),
),
);
}
}

class SignUpForm extends StatefulWidget {


const SignUpForm({super.key});

@override
State<SignUpForm> createState() => _SignUpFormState();
}

class _SignUpFormState extends State<SignUpForm> {


final _firstNameTextController = TextEditingController();
final _lastNameTextController = TextEditingController();

6
final _usernameTextController = TextEditingController();

double _formProgress = 0;

@override
Widget build(BuildContext context) {
return Form(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
LinearProgressIndicator(value: _formProgress),
Text('Sign up', style: Theme.of(context).textTheme.headlineMedium),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _firstNameTextController,
decoration: const InputDecoration(hintText: 'First name'),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _lastNameTextController,
decoration: const InputDecoration(hintText: 'Last name'),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _usernameTextController,

7
decoration: const InputDecoration(hintText: 'Username'),
),
),
TextButton(
style: ButtonStyle(
foregroundColor: WidgetStateProperty.resolveWith((states) {
return states.contains(WidgetState.disabled)
? null
: Colors.white;
}),
backgroundColor: WidgetStateProperty.resolveWith((states) {
return states.contains(WidgetState.disabled)
? null
: Colors.blue;
}),
),
onPressed: null,
child: const Text('Sign up'),
),
],
),
);
}
}
Результат

8
import 'package:flutter/material.dart';

void main() => runApp(const SignUpApp());

class SignUpApp extends StatelessWidget {


const SignUpApp({super.key});

@override
Widget build(BuildContext context) {
return MaterialApp(
routes: {
'/': (context) => const SignUpScreen(),
'/welcome': (context) => const WelcomeScreen(),
},
);
}
9
}

class SignUpScreen extends StatelessWidget {


const SignUpScreen({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.grey[200],
body: const Center(
child: SizedBox(
width: 400,
child: Card(
child: SignUpForm(),
),
),
),
);
}
}

class WelcomeScreen extends StatelessWidget {


const WelcomeScreen({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text(
'Welcome!',

10
style: Theme.of(context).textTheme.displayMedium,
),
),
);
}
}

class SignUpForm extends StatefulWidget {


const SignUpForm({super.key});

@override
State<SignUpForm> createState() => _SignUpFormState();
}

class _SignUpFormState extends State<SignUpForm> {


final _firstNameTextController = TextEditingController();
final _lastNameTextController = TextEditingController();
final _usernameTextController = TextEditingController();

double _formProgress = 0;

void _updateFormProgress() {
var progress = 0.0;
final controllers = [
_firstNameTextController,
_lastNameTextController,
_usernameTextController
];

for (final controller in controllers) {

11
if (controller.value.text.isNotEmpty) {
progress += 1 / controllers.length;
}
}

setState(() {
_formProgress = progress;
});
}

void _showWelcomeScreen() {
Navigator.of(context).pushNamed('/welcome');
}

@override
Widget build(BuildContext context) {
return Form(
onChanged: _updateFormProgress,
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
AnimatedProgressIndicator(value: _formProgress),
Text('Sign up', style: Theme.of(context).textTheme.headlineMedium),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _firstNameTextController,
decoration: const InputDecoration(hintText: 'First name'),
),
),

12
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _lastNameTextController,
decoration: const InputDecoration(hintText: 'Last name'),
),
),
Padding(
padding: const EdgeInsets.all(8),
child: TextFormField(
controller: _usernameTextController,
decoration: const InputDecoration(hintText: 'Username'),
),
),
TextButton(
style: ButtonStyle(
foregroundColor: WidgetStateProperty.resolveWith((states) {
return states.contains(WidgetState.disabled)
? null
: Colors.white;
}),
backgroundColor: WidgetStateProperty.resolveWith((states) {
return states.contains(WidgetState.disabled)
? null
: Colors.blue;
}),
),
onPressed: _formProgress == 1 ? _showWelcomeScreen : null,
child: const Text('Sign up'),
),

13
],
),
);
}
}

class AnimatedProgressIndicator extends StatefulWidget {


final double value;

const AnimatedProgressIndicator({
super.key,
required this.value,
});

@override
State<AnimatedProgressIndicator> createState() {
return _AnimatedProgressIndicatorState();
}
}

class _AnimatedProgressIndicatorState extends State<AnimatedProgressIndicator>


with SingleTickerProviderStateMixin {
late AnimationController _controller;
late Animation<Color?> _colorAnimation;
late Animation<double> _curveAnimation;

@override
void initState() {
super.initState();
_controller = AnimationController(

14
duration: const Duration(milliseconds: 1200),
vsync: this,
);

final colorTween = TweenSequence([


TweenSequenceItem(
tween: ColorTween(begin: Colors.red, end: Colors.orange),
weight: 1,
),
TweenSequenceItem(
tween: ColorTween(begin: Colors.orange, end: Colors.yellow),
weight: 1,
),
TweenSequenceItem(
tween: ColorTween(begin: Colors.yellow, end: Colors.green),
weight: 1,
),
]);

_colorAnimation = _controller.drive(colorTween);
_curveAnimation = _controller.drive(CurveTween(curve: Curves.easeIn));
}

@override
void didUpdateWidget(AnimatedProgressIndicator oldWidget) {
super.didUpdateWidget(oldWidget);
_controller.animateTo(widget.value);
}

@override

15
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (context, child) => LinearProgressIndicator(
value: _curveAnimation.value,
valueColor: _colorAnimation,
backgroundColor: _colorAnimation.value?.withOpacity(0.4),
),
);
}
}
Результат

16
import 'package:flutter/material.dart';

class Counter extends StatefulWidget {


// This class is the configuration for the state.
// It holds the values (in this case nothing) provided
// by the parent and used by the build method of the
// State. Fields in a Widget subclass are always marked
// "final".

const Counter({super.key});

@override
State<Counter> createState() => _CounterState();
}

class _CounterState extends State<Counter> {


int _counter = 0;

void _increment() {
setState(() {
// This call to setState tells the Flutter framework
// that something has changed in this State, which
// causes it to rerun the build method below so that
// the display can reflect the updated values. If you
// change _counter without calling setState(), then
// the build method won't be called again, and so
// nothing would appear to happen.
_counter++;
});
}
17
@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called,
// for instance, as done by the _increment method above.
// The Flutter framework has been optimized to make
// rerunning build methods fast, so that you can just
// rebuild anything that needs updating rather than
// having to individually changes instances of widgets.
return Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _increment,
child: const Text('Increment'),
),
const SizedBox(width: 16),
Text('Count: $_counter'),
],
);
}
}

void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(
child: Counter(),
),
18
),
),
);
}
Результат

import 'package:flutter/material.dart';

class Product {
const Product({required this.name});

final String name;


}

typedef CartChangedCallback = Function(Product product, bool inCart);

class ShoppingListItem extends StatelessWidget {


ShoppingListItem({
required this.product,
required this.inCart,
required this.onCartChanged,
}) : super(key: ObjectKey(product));

19
final Product product;
final bool inCart;
final CartChangedCallback onCartChanged;

Color _getColor(BuildContext context) {


// The theme depends on the BuildContext because different
// parts of the tree can have different themes.
// The BuildContext indicates where the build is
// taking place and therefore which theme to use.

return inCart //
? Colors.black54
: Theme.of(context).primaryColor;
}

TextStyle? _getTextStyle(BuildContext context) {


if (!inCart) return null;

return const TextStyle(


color: Colors.black54,
decoration: TextDecoration.lineThrough,
);
}

@override
Widget build(BuildContext context) {
return ListTile(
onTap: () {
onCartChanged(product, inCart);
},

20
leading: CircleAvatar(
backgroundColor: _getColor(context),
child: Text(product.name[0]),
),
title: Text(
product.name,
style: _getTextStyle(context),
),
);
}
}

class ShoppingList extends StatefulWidget {


const ShoppingList({required this.products, super.key});

final List<Product> products;

// The framework calls createState the first time


// a widget appears at a given location in the tree.
// If the parent rebuilds and uses the same type of
// widget (with the same key), the framework re-uses
// the State object instead of creating a new State object.

@override
State<ShoppingList> createState() => _ShoppingListState();
}

class _ShoppingListState extends State<ShoppingList> {


final _shoppingCart = <Product>{};

21
void _handleCartChanged(Product product, bool inCart) {
setState(() {
// When a user changes what's in the cart, you need
// to change _shoppingCart inside a setState call to
// trigger a rebuild.
// The framework then calls build, below,
// which updates the visual appearance of the app.

if (!inCart) {
_shoppingCart.add(product);
} else {
_shoppingCart.remove(product);
}
});
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Shopping List'),
),
body: ListView(
padding: const EdgeInsets.symmetric(vertical: 8),
children: widget.products.map((product) {
return ShoppingListItem(
product: product,
inCart: _shoppingCart.contains(product),
onCartChanged: _handleCartChanged,
);

22
}).toList(),
),
);
}
}

void main() {
runApp(const MaterialApp(
title: 'Shopping App',
home: ShoppingList(
products: [
Product(name: 'Eggs'),
Product(name: 'Flour'),
Product(name: 'Chocolate chips'),
],
),
));
}
Результат

23
import 'package:flutter/material.dart';

class MyButton extends StatelessWidget {


const MyButton({super.key});

@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
print('MyButton was tapped!');
},
child: Container(
height: 50,
padding: const EdgeInsets.all(8),
margin: const EdgeInsets.symmetric(horizontal: 8),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
color: Colors.lightGreen[500],
),
child: const Center(
child: Text('Engage'),
),
),
);
}
}

void main() {
runApp(
const MaterialApp(
home: Scaffold(
body: Center(

24
child: MyButton(),
),
),
),
);
}
Результат

Запуск Dart DevTools

Встановлення точки зупинки

25
ВИСНОВОК
У ході виконання лабораторної роботи з дисципліни "Розробка крос-
платформних мобільних застосунків", ми успішно виконали поставлені завдання.
Ми навчились розробляти прості користувацькі інтерфейси за допомогою Flutter.
Навчились писати перші додатки для Flutter в Інтернеті.

26

You might also like