Try recreating Skype Desktop’s chat box.

import 'dart:math'; import 'package:flutter/material.dart'; class Theme { static final Color primaryTextColor = Colors.grey.shade700; static final Color secondaryTextColor = Colors.grey; } class SkypePage extends StatefulWidget { @override _SkypePageState createState() => _SkypePageState(); } class _SkypePageState extends State<SkypePage> { final double leftWidth = 300.0; Widget _leftCol() { return Padding( padding: const EdgeInsets.all(4.0), child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Row( children: [ MainAvatarRow(), ], ), Row( children: [ Flexible( flex: 8, child: TextField( maxLines: 1, decoration: InputDecoration( contentPadding: EdgeInsets.all(0), hintText: 'People, groups & messages', prefixIcon: Icon(Icons.search), border: OutlineInputBorder( borderSide: BorderSide(color: Theme.secondaryTextColor))), ), ), Flexible( child: IconButton( icon: Icon(Icons.dialpad_outlined), onPressed: () {})) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ LabelButton(label: 'Chats', icon: Icons.message), LabelButton(label: 'Calls', icon: Icons.phone), LabelButton(label: 'Contacts', icon: Icons.contact_page_outlined), LabelButton( label: 'Notifications', icon: Icons.notification_important_outlined), ], ), Divider(), Row( mainAxisAlignment: MainAxisAlignment.center, children: [ LabelButtonRow( icon: Icons.video_call_outlined, label: 'Meet Now'), SizedBox(width: 4.0), LabelButtonRow(icon: Icons.note_add_outlined, label: 'New Chat') ], ), SizedBox(height: 8.0), Text( 'CHATS', style: TextStyle(fontSize: 16.0, color: Theme.primaryTextColor), ), Expanded( child: ListView( children: [ ...List.generate(15, (index) { return ListTile( contentPadding: EdgeInsets.zero, title: Row( children: [ AvatarRow( name: 'Name ${index + 1}', message: 'hello', ), ], ), ); }) ], ), ), ], ), ); } Widget _rightCol() { return Column( children: [ Row( children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Name 1', style: TextStyle( fontSize: 18.0, color: Theme.primaryTextColor)), Row( children: [ Text('Last seen days ago', style: TextStyle(color: Theme.secondaryTextColor)), Text(' | ', style: TextStyle(color: Theme.secondaryTextColor)), Icon(Icons.image, color: Theme.secondaryTextColor), Text('Gallery', style: TextStyle(color: Theme.secondaryTextColor)), Text(' | ', style: TextStyle(color: Theme.secondaryTextColor)), Icon(Icons.search, color: Theme.secondaryTextColor), Text('Find', style: TextStyle(color: Theme.secondaryTextColor)), ], ), ], ), Spacer(), RoundButton(icon: Icons.video_call_outlined), RoundButton(icon: Icons.call), RoundButton(icon: Icons.person_add), ], ), Divider( color: Theme.secondaryTextColor, thickness: 1, ), SingleChildScrollView( child: ChatBox(), ), Row( children: [ Flexible( flex: 8, child: TextField( maxLines: 1, decoration: InputDecoration( fillColor: Colors.grey, contentPadding: EdgeInsets.all(0), hintText: 'Type a message', prefixIcon: Icon(Icons.emoji_emotions_outlined), border: OutlineInputBorder( borderSide: BorderSide(color: Theme.secondaryTextColor))), ), ), Spacer(), Flexible(child: RoundButton(icon: Icons.folder_open)), Flexible(child: RoundButton(icon: Icons.contact_mail_outlined)), Flexible(child: RoundButton(icon: Icons.mic)), Flexible(child: RoundButton(icon: Icons.more_horiz_outlined)), ], ) ], ); } @override Widget build(BuildContext context) { return Scaffold( body: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( width: leftWidth, height: double.infinity, decoration: BoxDecoration( color: Colors.grey.shade100, border: Border( right: BorderSide( color: Theme.secondaryTextColor, width: 1, ))), child: _leftCol()), Expanded( child: Container( padding: EdgeInsets.all(16.0), height: double.infinity, color: Colors.white, child: _rightCol()), ), ], ), ); } } class Avatar extends StatelessWidget { final String? image; final double? size; const Avatar({Key? key, this.size, this.image}) : super(key: key); @override Widget build(BuildContext context) { return Container( width: size ?? 36, height: size ?? 36, child: ClipRRect( borderRadius: BorderRadius.circular(36.0), child: Image.network( image ?? 'https://cdn.pixabay.com/photo/2014/11/30/14/11/cat-551554_960_720.jpg', fit: BoxFit.fill, ), )); } } class AvatarRow extends StatelessWidget { final Avatar? avatar; final String? name; final String? message; const AvatarRow({Key? key, this.name, this.message, this.avatar}) : super(key: key); @override Widget build(BuildContext context) { return Expanded( child: Container( //padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ avatar ?? Avatar(), SizedBox(width: 16), Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(name ?? 'Name', style: TextStyle(color: Theme.primaryTextColor)), Text(message ?? 'hello', style: TextStyle(color: Theme.secondaryTextColor)), ], ), Spacer(), Text('${Random().nextInt(12) + 1}/${Random().nextInt(20) + 1}/2021', style: TextStyle(color: Theme.secondaryTextColor)) ], ), ), ); } } class MainAvatarRow extends StatelessWidget { @override Widget build(BuildContext context) { return Expanded( child: Container( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.center, children: [ Avatar( image: 'https://cdn.pixabay.com/photo/2014/04/13/20/49/cat-323262__340.jpg'), SizedBox(width: 16), Text('TL Templates', style: TextStyle(color: Theme.primaryTextColor)), SizedBox(width: 16), Text('\$0.00', style: TextStyle(color: Theme.primaryTextColor.withOpacity(0.5))), Spacer(), IconButton(icon: Icon(Icons.more_horiz_outlined), onPressed: () {}) ], ), ), ); } } class LabelButton extends StatelessWidget { final IconData? icon; final VoidCallback? onPressed; final String? label; const LabelButton({Key? key, @required this.icon, this.onPressed, this.label}) : super(key: key); @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ IconButton( icon: Icon(icon!, color: Theme.primaryTextColor, size: 18.0), onPressed: onPressed ?? () {}), Text( label!, style: TextStyle(color: Theme.primaryTextColor), ) ], ); } } class LabelButtonRow extends StatelessWidget { final IconData? icon; final VoidCallback? onPressed; final String? label; const LabelButtonRow( {Key? key, @required this.icon, this.onPressed, this.label}) : super(key: key); @override Widget build(BuildContext context) { return Container( padding: EdgeInsets.zero, decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.circular(16.0), ), child: Row( children: [ IconButton( icon: Icon(icon!, color: Theme.primaryTextColor, size: 18.0), onPressed: onPressed ?? () {}), Text( label!, style: TextStyle(color: Theme.primaryTextColor), ), IconButton( icon: Icon(Icons.keyboard_arrow_down_outlined, color: Theme.primaryTextColor, size: 18.0), onPressed: onPressed ?? () {}) ], ), ); } } class RoundButton extends StatelessWidget { final IconData? icon; final VoidCallback? onPressed; const RoundButton({Key? key, @required this.icon, this.onPressed}) : super(key: key); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB(8.0, 0, 8.0, 0), child: Container( decoration: BoxDecoration(color: Colors.grey.shade100, shape: BoxShape.circle), child: IconButton( icon: Icon(icon!, color: Theme.primaryTextColor, size: 18.0), onPressed: onPressed ?? () {}), ), ); } } class ChatBox extends StatefulWidget { @override _ChatBoxState createState() => _ChatBoxState(); } class _ChatBoxState extends State<ChatBox> { @override Widget build(BuildContext context) { return Container( height: MediaQuery.of(context).size.height - 150, padding: EdgeInsets.fromLTRB(36.0, 16.0, 36.0, 16.0), child: Column( mainAxisAlignment: MainAxisAlignment.end, children: [ Row( mainAxisAlignment: MainAxisAlignment.start, children: [ Avatar(), SizedBox(width: 8.0), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Name, 8:30PM', style: TextStyle(color: Theme.secondaryTextColor), ), Container( padding: EdgeInsets.all(8.0), decoration: BoxDecoration( color: Colors.blueAccent, borderRadius: BorderRadius.circular(8.0)), child: Text('Hello\nMy test message')), ], ), ], ), SizedBox(height: 16.0), Row( mainAxisAlignment: MainAxisAlignment.end, children: [ Container( padding: EdgeInsets.all(8.0), decoration: BoxDecoration( color: Colors.grey.shade200, borderRadius: BorderRadius.circular(8.0)), child: Text('Hello')), ], ), ], ), ); } }