Skip to content

Commit

Permalink
chat design finished
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexandra Makarova authored and Alexandra Makarova committed Nov 15, 2020
1 parent a3a08ed commit ef054c2
Show file tree
Hide file tree
Showing 11 changed files with 343 additions and 15 deletions.
Binary file added assets/fonts/Quicksand-Bold.ttf
Binary file not shown.
Binary file added assets/fonts/Quicksand-Light.ttf
Binary file not shown.
Binary file added assets/fonts/Quicksand-Regular.ttf
Binary file not shown.
File renamed without changes
6 changes: 4 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ class MyApp extends StatelessWidget {
title: 'Realtime Chat App',
theme: ThemeData(
primaryColor: Colors.blue[600],
accentColor: Colors.purple[400],
primaryColorLight: Color(0xff4D9EF6),
buttonColor: Colors.blue[400],
backgroundColor: Colors.grey[100],
fontFamily: "Quicksand",
),
initialRoute: 'login',
initialRoute: 'chat',
routes: appRoutes,
);
}
Expand Down
13 changes: 13 additions & 0 deletions lib/models/user.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class User {
bool online;
String email;
String name;
String userId;

User({
this.online,
this.email,
this.name,
this.userId,
});
}
148 changes: 145 additions & 3 deletions lib/pages/chat_page.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,154 @@
import 'dart:io';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../widgets/chat_message.dart';

class ChatPage extends StatefulWidget {
@override
_ChatPageState createState() => _ChatPageState();
}

class _ChatPageState extends State<ChatPage> with TickerProviderStateMixin {
final _textController = new TextEditingController();
final _focusNode = new FocusNode();

List<ChatMessage> _messages = [];

bool _userIsWriting = false;

class ChatPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('ChatPage'),
appBar: AppBar(
backgroundColor: Theme.of(context).backgroundColor,
title: Column(
children: <Widget>[
CircleAvatar(
child: Text(
'Te',
style: TextStyle(fontSize: 12),
),
backgroundColor: Colors.blue[100],
maxRadius: 14,
),
SizedBox(
height: 3,
),
Text(
'Vasya Pupkin',
style: TextStyle(color: Colors.black87, fontSize: 12),
)
],
),
centerTitle: true,
elevation: 1,
),
body: Container(
child: Column(
children: <Widget>[
Flexible(
child: ListView.builder(
physics: BouncingScrollPhysics(),
itemCount: _messages.length,
itemBuilder: (_, index) => _messages[index],
reverse: true,
),
),
Divider(
height: 1,
),
Container(
color: Theme.of(context).backgroundColor,
child: _inputChat(),
)
],
),
),
);
}

Widget _inputChat() {
return SafeArea(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 8),
child: Row(
children: <Widget>[
Flexible(
child: TextField(
controller: _textController,
onSubmitted: _handleSubmit,
onChanged: (text) {
setState(() {
if (text.trim().length > 0) {
_userIsWriting = true;
} else {
_userIsWriting = false;
}
});
},
decoration: InputDecoration.collapsed(hintText: 'Send message'),
focusNode: _focusNode,
),
),
Container(
margin: EdgeInsets.symmetric(horizontal: 4),
child: Platform.isIOS
? CupertinoButton(
child: Text('Send'),
onPressed: _userIsWriting
? () => _handleSubmit(_textController.text.trim())
: null,
)
: Container(
margin: EdgeInsets.symmetric(horizontal: 4.0),
child: IconTheme(
data:
IconThemeData(color: Theme.of(context).buttonColor),
child: IconButton(
highlightColor: Colors.transparent,
splashColor: Colors.transparent,
icon: Icon(Icons.send),
onPressed: _userIsWriting
? () => _handleSubmit(_textController.text.trim())
: null,
),
),
),
)
],
),
),
);
}

_handleSubmit(String text) {
if (text.length == 0) return;

print(text);
_textController.clear();
_focusNode.requestFocus();

final newMessage = new ChatMessage(
userId: '123',
text: text,
animationController: AnimationController(
vsync: this, duration: Duration(milliseconds: 200)),
);

_messages.insert(0, newMessage);
newMessage.animationController.forward();

setState(() {
_userIsWriting = false;
});
}

@override
void dispose() {
for (ChatMessage message in _messages) {
message.animationController.dispose();
}
super.dispose();
}
}
89 changes: 86 additions & 3 deletions lib/pages/users_page.dart
Original file line number Diff line number Diff line change
@@ -1,12 +1,95 @@
import 'package:flutter/material.dart';
import 'package:pull_to_refresh/pull_to_refresh.dart';
import '../models/user.dart';

class UsersPage extends StatefulWidget {
@override
_UsersPageState createState() => _UsersPageState();
}

class _UsersPageState extends State<UsersPage> {
RefreshController _refreshController =
RefreshController(initialRefresh: false);
final users = [
User(userId: '1', email: 'test1@test.com', name: 'Helen', online: true),
User(userId: '2', email: 'test2@test.com', name: 'Max', online: true),
User(userId: '3', email: 'test3@test.com', name: 'Michael', online: false),
];

class UsersPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Text('UsersPage'),
appBar: AppBar(
title: Text(
'Mi Nombre',
style: TextStyle(color: Colors.black87),
),
elevation: 1,
backgroundColor: Theme.of(context).backgroundColor,
leading: IconButton(
icon: Icon(
Icons.exit_to_app,
color: Colors.black87,
),
onPressed: () {},
),
actions: <Widget>[
Container(
margin: EdgeInsets.only(right: 10),
child: Icon(
Icons.check_circle,
color: Theme.of(context).buttonColor,
// Icons.check_circle,
// color: Theme.of(context).errorColor,
),
),
],
),
body: SmartRefresher(
controller: _refreshController,
child: _listViewUsers(),
enablePullDown: true,
onRefresh: _loadUsers,
header: WaterDropHeader(
complete: Icon(Icons.check, color: Theme.of(context).buttonColor),
waterDropColor: Theme.of(context).buttonColor,
),
),
);
}

ListView _listViewUsers() {
return ListView.separated(
physics: BouncingScrollPhysics(),
itemBuilder: (_, index) => _userListTile(users[index]),
separatorBuilder: (_, index) => Divider(),
itemCount: users.length,
);
}

ListTile _userListTile(User user) {
return ListTile(
title: Text(
user.name,
),
subtitle: Text(user.email),
leading: CircleAvatar(
child: Text(user.name.substring(0, 2)),
backgroundColor: Colors.blue[100],
),
trailing: Container(
width: 10,
height: 10,
decoration: BoxDecoration(
color:
user.online ? Colors.green[400] : Theme.of(context).errorColor,
borderRadius: BorderRadius.circular(100)),
),
);
}

_loadUsers() async {
await Future.delayed(Duration(milliseconds: 1000));
_refreshController.refreshCompleted();
}
}
74 changes: 74 additions & 0 deletions lib/widgets/chat_message.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import 'package:flutter/material.dart';

class ChatMessage extends StatelessWidget {
final String text;
final String userId;
final AnimationController animationController;

const ChatMessage(
{Key key,
@required this.text,
@required this.userId,
@required this.animationController})
: super(key: key);

@override
Widget build(BuildContext context) {
return FadeTransition(
opacity: animationController,
child: SizeTransition(
sizeFactor: CurvedAnimation(
parent: animationController,
curve: Curves.easeOut,
),
child: Container(
child: this.userId == '123' ? _myMessage() : _notMyMessage(),
),
),
);
}

Widget _myMessage() {
return Align(
alignment: Alignment.centerRight,
child: Container(
padding: EdgeInsets.all(8.0),
margin: EdgeInsets.only(
bottom: 5,
left: 50,
right: 5,
),
child: Text(
this.text,
style: TextStyle(color: Colors.black87),
),
decoration: BoxDecoration(
color: Color(0xffE4E5E8),
borderRadius: BorderRadius.circular(20),
),
),
);
}

Widget _notMyMessage() {
return Align(
alignment: Alignment.centerLeft,
child: Container(
padding: EdgeInsets.all(8.0),
margin: EdgeInsets.only(
bottom: 5,
left: 5,
right: 50,
),
child: Text(
this.text,
style: TextStyle(color: Colors.white),
),
decoration: BoxDecoration(
color: Color(0xff4D9EF6),
borderRadius: BorderRadius.circular(20),
),
),
);
}
}
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,13 @@ packages:
url: "https://pub.dartlang.org"
source: hosted
version: "1.8.0-nullsafety.1"
pull_to_refresh:
dependency: "direct main"
description:
name: pull_to_refresh
url: "https://pub.dartlang.org"
source: hosted
version: "1.6.2"
sky_engine:
dependency: transitive
description: flutter
Expand Down Expand Up @@ -151,3 +158,4 @@ packages:
version: "2.1.0-nullsafety.3"
sdks:
dart: ">=2.10.0-110 <2.11.0"
flutter: ">=0.1.4 <2.0.0"
Loading

0 comments on commit ef054c2

Please sign in to comment.