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

lab1

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
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
We take content rights seriously. If you suspect this is your content, claim it here.
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