feat:更新页面颜色
This commit is contained in:
@@ -1,28 +1 @@
|
|||||||
# This file configures the analyzer, which statically analyzes Dart code to
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
# check for errors, warnings, and lints.
|
|
||||||
#
|
|
||||||
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
|
||||||
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
|
||||||
# invoked from the command line by running `flutter analyze`.
|
|
||||||
|
|
||||||
# The following line activates a set of recommended lints for Flutter apps,
|
|
||||||
# packages, and plugins designed to encourage good coding practices.
|
|
||||||
include: package:flutter_lints/flutter.yaml
|
|
||||||
|
|
||||||
linter:
|
|
||||||
# The lint rules applied to this project can be customized in the
|
|
||||||
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
|
||||||
# included above or to enable additional rules. A list of all available lints
|
|
||||||
# and their documentation is published at https://dart.dev/lints.
|
|
||||||
#
|
|
||||||
# Instead of disabling a lint rule for the entire project in the
|
|
||||||
# section below, it can also be suppressed for a single line of code
|
|
||||||
# or a specific dart file by using the `// ignore: name_of_lint` and
|
|
||||||
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
|
||||||
# producing the lint.
|
|
||||||
rules:
|
|
||||||
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
|
||||||
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
|
||||||
|
|
||||||
# Additional information about this file can be found at
|
|
||||||
# https://dart.dev/guides/language/analysis-options
|
|
||||||
@@ -1,3 +1 @@
|
|||||||
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError
|
||||||
android.useAndroidX=true
|
|
||||||
android.enableJetifier=true
|
|
||||||
@@ -1,5 +1 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
|
||||||
zipStorePath=wrapper/dists
|
|
||||||
distributionUrl=https://mirrors.cloud.tencent.com/gradle/gradle-8.10.2-all.zip
|
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
|
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
|
||||||
import 'package:sweet_chat_app/pages/contacts_page.dart';
|
import 'package:sweet_chat_app/pages/contacts_page.dart';
|
||||||
|
import 'package:sweet_chat_app/pages/explore_page.dart';
|
||||||
import 'package:sweet_chat_app/pages/messages_page.dart';
|
import 'package:sweet_chat_app/pages/messages_page.dart';
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
@@ -19,6 +20,7 @@ class MyApp extends StatelessWidget {
|
|||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: ThemeData(
|
theme: ThemeData(
|
||||||
|
scaffoldBackgroundColor: const Color(0xFF120D25),
|
||||||
brightness: Brightness.light,
|
brightness: Brightness.light,
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
colorScheme: ColorScheme.light(
|
colorScheme: ColorScheme.light(
|
||||||
@@ -43,28 +45,21 @@ class _HomePageState extends State<HomePage> {
|
|||||||
int _index = 0;
|
int _index = 0;
|
||||||
|
|
||||||
final _pages = const [
|
final _pages = const [
|
||||||
Center(child: MessagePage()),
|
MessagePage(),
|
||||||
Center(child: ContactsPage()),
|
ContactsPage(),
|
||||||
Center(child: Text('⚙ Settings', style: TextStyle(fontSize: 26, color: Colors.white))),
|
ExplorePage(),
|
||||||
Center(child: Text('⚙ 我的', style: TextStyle(fontSize: 26, color: Colors.white))),
|
Center(child: Text('⚙ 我的', style: TextStyle(fontSize: 26))),
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return GlassScaffold(
|
return GlassScaffold(
|
||||||
background: Container(
|
|
||||||
decoration: const BoxDecoration(
|
|
||||||
gradient: LinearGradient(
|
|
||||||
begin: Alignment.topCenter,
|
|
||||||
end: Alignment.bottomCenter,
|
|
||||||
colors: [Color(0xFFFFFFFF), Color(0xFFF5F5F7)],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
statusBarStyle: GlassStatusBarStyle.auto,
|
statusBarStyle: GlassStatusBarStyle.auto,
|
||||||
bottomBar: GlassBottomBar(
|
bottomBar: GlassBottomBar(
|
||||||
selectedIndex: _index,
|
selectedIndex: _index,
|
||||||
onTabSelected: (i) => setState(() => _index = i),
|
onTabSelected: (i) => setState(() => _index = i),
|
||||||
|
selectedIconColor: Colors.purple.shade200,
|
||||||
|
unselectedIconColor: Colors.white,
|
||||||
tabs: const [
|
tabs: const [
|
||||||
GlassBottomBarTab(
|
GlassBottomBarTab(
|
||||||
icon: Icon(Icons.chat_bubble_outline),
|
icon: Icon(Icons.chat_bubble_outline),
|
||||||
|
|||||||
178
lib/pages/chat_page.dart
Normal file
178
lib/pages/chat_page.dart
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
|
||||||
|
|
||||||
|
class ChatMessage {
|
||||||
|
final String text;
|
||||||
|
final bool isMe;
|
||||||
|
final String? avatar;
|
||||||
|
|
||||||
|
ChatMessage({required this.text, required this.isMe, this.avatar});
|
||||||
|
}
|
||||||
|
|
||||||
|
class ChatPage extends StatefulWidget {
|
||||||
|
final String contactName;
|
||||||
|
final String avatarUrl;
|
||||||
|
|
||||||
|
const ChatPage({
|
||||||
|
super.key,
|
||||||
|
required this.contactName,
|
||||||
|
required this.avatarUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ChatPage> createState() => _ChatPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatPageState extends State<ChatPage> {
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
final ScrollController _scrollController = ScrollController();
|
||||||
|
|
||||||
|
late List<ChatMessage> _messages;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
|
||||||
|
_messages = [
|
||||||
|
ChatMessage(text: '在吗?', isMe: false, avatar: widget.avatarUrl),
|
||||||
|
ChatMessage(text: '在的,怎么啦 😊', isMe: true),
|
||||||
|
ChatMessage(text: '今晚一起吃饭吗?', isMe: false, avatar: widget.avatarUrl),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
void _sendMessage() {
|
||||||
|
final text = _controller.text.trim();
|
||||||
|
if (text.isEmpty) return;
|
||||||
|
|
||||||
|
setState(() {
|
||||||
|
_messages.add(ChatMessage(text: text, isMe: true));
|
||||||
|
});
|
||||||
|
|
||||||
|
_controller.clear();
|
||||||
|
|
||||||
|
Future.delayed(const Duration(milliseconds: 100), () {
|
||||||
|
_scrollController.animateTo(
|
||||||
|
_scrollController.position.maxScrollExtent,
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeOut,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildAvatar(String? url) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8, top: 4),
|
||||||
|
child: CircleAvatar(
|
||||||
|
radius: 18,
|
||||||
|
backgroundColor: Colors.grey[200],
|
||||||
|
backgroundImage: url != null ? NetworkImage(url) : null,
|
||||||
|
child:
|
||||||
|
url == null
|
||||||
|
? const Icon(Icons.person, size: 18, color: Colors.grey)
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: _buildAppBar(),
|
||||||
|
body: SafeArea(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(10),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(child: _buildMessage()),
|
||||||
|
SizedBox(height: 10),
|
||||||
|
_buildInput(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferredSizeWidget _buildAppBar() {
|
||||||
|
return AppBar(
|
||||||
|
backgroundColor: Color(0xFF120D25),
|
||||||
|
foregroundColor: Colors.white,
|
||||||
|
title: Text(
|
||||||
|
widget.contactName,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
centerTitle: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildMessage() {
|
||||||
|
return GlassCard(
|
||||||
|
child: ListView.separated(
|
||||||
|
controller: _scrollController,
|
||||||
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
return SizedBox(height: 10);
|
||||||
|
},
|
||||||
|
itemCount: _messages.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final msg = _messages[index];
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment:
|
||||||
|
msg.isMe ? MainAxisAlignment.end : MainAxisAlignment.start,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (!msg.isMe) _buildAvatar(msg.avatar),
|
||||||
|
Flexible(
|
||||||
|
child: GlassCard(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 10,
|
||||||
|
),
|
||||||
|
child: Text(
|
||||||
|
msg.text,
|
||||||
|
style: const TextStyle(fontSize: 16, color: Colors.white),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
if (msg.isMe) _buildAvatar("https://picsum.photos/id/1027/200"),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildInput() {
|
||||||
|
return SafeArea(
|
||||||
|
child: GlassContainer(
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextField(
|
||||||
|
controller: _controller,
|
||||||
|
onSubmitted: (_) => _sendMessage(),
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
hintText: '输入消息...',
|
||||||
|
hintStyle: TextStyle(color: Colors.white),
|
||||||
|
border: InputBorder.none,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: _sendMessage,
|
||||||
|
icon: const Icon(Icons.send, color: Colors.green),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,86 +40,26 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
|
|
||||||
void _loadFakeData() {
|
void _loadFakeData() {
|
||||||
contactList = [
|
contactList = [
|
||||||
ContactInfo(
|
ContactInfo(name: '张三', avatar: 'https://picsum.photos/id/1011/200'),
|
||||||
name: '张三',
|
ContactInfo(name: '李四', avatar: 'https://picsum.photos/id/1012/200'),
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/11.jpg',
|
ContactInfo(name: '王五', avatar: 'https://picsum.photos/id/1013/200'),
|
||||||
),
|
ContactInfo(name: '赵六', avatar: 'https://picsum.photos/id/1014/200'),
|
||||||
ContactInfo(
|
ContactInfo(name: '陈七', avatar: 'https://picsum.photos/id/1015/200'),
|
||||||
name: '李四',
|
ContactInfo(name: '刘八', avatar: 'https://picsum.photos/id/1016/200'),
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/12.jpg',
|
ContactInfo(name: '周九', avatar: 'https://picsum.photos/id/1017/200'),
|
||||||
),
|
ContactInfo(name: '吴十', avatar: 'https://picsum.photos/id/1018/200'),
|
||||||
ContactInfo(
|
ContactInfo(name: '欧阳峰', avatar: 'https://picsum.photos/id/1021/200'),
|
||||||
name: '王五',
|
ContactInfo(name: '诸葛青', avatar: 'https://picsum.photos/id/1022/200'),
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/13.jpg',
|
ContactInfo(name: '司马光', avatar: 'https://picsum.photos/id/1023/200'),
|
||||||
),
|
ContactInfo(name: '慕容复', avatar: 'https://picsum.photos/id/1024/200'),
|
||||||
ContactInfo(
|
ContactInfo(name: '安琪拉', avatar: 'https://picsum.photos/id/1031/200'),
|
||||||
name: '赵六',
|
ContactInfo(name: '亚瑟', avatar: 'https://picsum.photos/id/1032/200'),
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/14.jpg',
|
ContactInfo(name: '李白', avatar: 'https://picsum.photos/id/1033/200'),
|
||||||
),
|
ContactInfo(name: '韩信', avatar: 'https://picsum.photos/id/1034/200'),
|
||||||
ContactInfo(
|
ContactInfo(name: '孙尚香', avatar: 'https://picsum.photos/id/1035/200'),
|
||||||
name: '陈七',
|
ContactInfo(name: '鲁班', avatar: 'https://picsum.photos/id/1036/200'),
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/15.jpg',
|
ContactInfo(name: '妲己', avatar: 'https://picsum.photos/id/1037/200'),
|
||||||
),
|
ContactInfo(name: '甄姬', avatar: 'https://picsum.photos/id/1038/200'),
|
||||||
ContactInfo(
|
|
||||||
name: '刘八',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/16.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '周九',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/17.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '吴十',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/18.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '欧阳峰',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/21.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '诸葛青',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/22.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '司马光',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/23.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '慕容复',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/24.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '安琪拉',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/31.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '亚瑟',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/32.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '李白',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/33.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '韩信',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/34.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '孙尚香',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/35.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '鲁班',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/men/36.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '妲己',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/37.jpg',
|
|
||||||
),
|
|
||||||
ContactInfo(
|
|
||||||
name: '甄姬',
|
|
||||||
avatar: 'https://randomuser.me/api/portraits/women/38.jpg',
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
_handleList(contactList);
|
_handleList(contactList);
|
||||||
@@ -142,10 +82,18 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF2F2F7),
|
backgroundColor: Colors.transparent,
|
||||||
appBar: AppBar(
|
appBar: _buildAppBar(),
|
||||||
|
body: Column(
|
||||||
|
children: [_buildSearchBar(), Expanded(child: _buildAzListView())],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferredSizeWidget _buildAppBar() {
|
||||||
|
return AppBar(
|
||||||
automaticallyImplyLeading: false,
|
automaticallyImplyLeading: false,
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Color(0xFF120D25),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
title: const Text(
|
title: const Text(
|
||||||
@@ -153,13 +101,9 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF1C1C1E),
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
body: Column(
|
|
||||||
children: [_buildSearchBar(), Expanded(child: _buildAzListView())],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,7 +114,6 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
itemBuilder: (_, index) {
|
itemBuilder: (_, index) {
|
||||||
final c = contactList[index];
|
final c = contactList[index];
|
||||||
return Container(
|
return Container(
|
||||||
color: Colors.white,
|
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundImage: NetworkImage(c.avatar),
|
backgroundImage: NetworkImage(c.avatar),
|
||||||
@@ -178,7 +121,7 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
c.name,
|
c.name,
|
||||||
style: const TextStyle(fontSize: 16, color: Color(0xFF1C1C1E)),
|
style: const TextStyle(fontSize: 16, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -189,10 +132,10 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
height: 28,
|
height: 28,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
color: const Color(0xFFF2F2F7),
|
color: const Color(0xFF2B2744),
|
||||||
child: Text(
|
child: Text(
|
||||||
tag,
|
tag,
|
||||||
style: const TextStyle(fontSize: 13, color: Color(0xFF8E8E93)),
|
style: const TextStyle(fontSize: 13, color: Colors.grey),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -210,21 +153,16 @@ class _ContactsPageState extends State<ContactsPage> {
|
|||||||
Widget _buildSearchBar() {
|
Widget _buildSearchBar() {
|
||||||
return Container(
|
return Container(
|
||||||
height: 44,
|
height: 44,
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(color: Color(0xFF2F2A47)),
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
child: TextField(
|
child: TextField(
|
||||||
textAlignVertical: TextAlignVertical.center,
|
textAlignVertical: TextAlignVertical.center,
|
||||||
|
style: const TextStyle(color: Colors.white),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
|
isDense: true,
|
||||||
hintText: '搜索联系人',
|
hintText: '搜索联系人',
|
||||||
hintStyle: const TextStyle(fontSize: 15, color: Color(0xFF8E8E93)),
|
hintStyle: const TextStyle(fontSize: 15, color: Colors.white),
|
||||||
prefixIcon: const Icon(
|
prefixIcon: const Icon(Icons.search, size: 20, color: Colors.white),
|
||||||
Icons.search,
|
|
||||||
size: 20,
|
|
||||||
color: Color(0xFF8E8E93),
|
|
||||||
),
|
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 12),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
277
lib/pages/explore_page.dart
Normal file
277
lib/pages/explore_page.dart
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
|
||||||
|
|
||||||
|
class Comment {
|
||||||
|
final String nickname;
|
||||||
|
final String content;
|
||||||
|
|
||||||
|
Comment({required this.nickname, required this.content});
|
||||||
|
}
|
||||||
|
|
||||||
|
class Moment {
|
||||||
|
final String avatar;
|
||||||
|
final String nickname;
|
||||||
|
final String content;
|
||||||
|
final List<String> images;
|
||||||
|
|
||||||
|
bool liked;
|
||||||
|
int likeCount;
|
||||||
|
List<Comment> comments;
|
||||||
|
|
||||||
|
Moment({
|
||||||
|
required this.avatar,
|
||||||
|
required this.nickname,
|
||||||
|
required this.content,
|
||||||
|
this.images = const [],
|
||||||
|
this.liked = false,
|
||||||
|
this.likeCount = 0,
|
||||||
|
this.comments = const [],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ================= Explore Page =================
|
||||||
|
|
||||||
|
class ExplorePage extends StatefulWidget {
|
||||||
|
const ExplorePage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<ExplorePage> createState() => _ExplorePageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ExplorePageState extends State<ExplorePage> {
|
||||||
|
final List<Moment> _moments = [
|
||||||
|
Moment(
|
||||||
|
avatar: 'https://picsum.photos/100?random=1',
|
||||||
|
nickname: '张三',
|
||||||
|
content: '今天天气真不错 ☀️',
|
||||||
|
images: [
|
||||||
|
'https://picsum.photos/300?random=1',
|
||||||
|
'https://picsum.photos/300?random=2',
|
||||||
|
'https://picsum.photos/300?random=3',
|
||||||
|
'https://picsum.photos/300?random=4',
|
||||||
|
'https://picsum.photos/300?random=5',
|
||||||
|
],
|
||||||
|
likeCount: 12,
|
||||||
|
comments: [
|
||||||
|
Comment(nickname: '李四', content: '确实不错'),
|
||||||
|
Comment(nickname: '王五', content: '想去旅游'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Moment(
|
||||||
|
avatar: 'https://picsum.photos/100?random=2',
|
||||||
|
nickname: '李四',
|
||||||
|
content: 'Flutter 真香 🚀',
|
||||||
|
images: ['https://picsum.photos/300?random=6'],
|
||||||
|
likeCount: 8,
|
||||||
|
comments: [],
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
void _handleLike(int index) {
|
||||||
|
setState(() {
|
||||||
|
final m = _moments[index];
|
||||||
|
m.liked ? m.likeCount-- : m.likeCount++;
|
||||||
|
m.liked = !m.liked;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleComment(int index, String text) {
|
||||||
|
setState(() {
|
||||||
|
_moments[index].comments.add(Comment(nickname: '我', content: text));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
appBar: _buildAppBar(),
|
||||||
|
body: Padding(padding: const EdgeInsets.all(10), child: _buildMoment()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PreferredSizeWidget _buildAppBar() {
|
||||||
|
return AppBar(
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
backgroundColor: Color(0xFF120D25),
|
||||||
|
elevation: 0,
|
||||||
|
centerTitle: true,
|
||||||
|
title: const Text(
|
||||||
|
'朋友圈',
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {},
|
||||||
|
icon: const Icon(Icons.add, size: 22, color: Colors.white),
|
||||||
|
splashRadius: 20,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildMoment() {
|
||||||
|
return ListView.separated(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||||
|
),
|
||||||
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
return SizedBox(height: 10);
|
||||||
|
},
|
||||||
|
itemCount: _moments.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return MomentItem(
|
||||||
|
moment: _moments[index],
|
||||||
|
onLike: () => _handleLike(index),
|
||||||
|
onComment: (text) => _handleComment(index, text),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ================= Moment Item =================
|
||||||
|
|
||||||
|
class MomentItem extends StatefulWidget {
|
||||||
|
final Moment moment;
|
||||||
|
final VoidCallback onLike;
|
||||||
|
final Function(String) onComment;
|
||||||
|
|
||||||
|
const MomentItem({
|
||||||
|
super.key,
|
||||||
|
required this.moment,
|
||||||
|
required this.onLike,
|
||||||
|
required this.onComment,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MomentItem> createState() => _MomentItemState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MomentItemState extends State<MomentItem> {
|
||||||
|
final TextEditingController _controller = TextEditingController();
|
||||||
|
|
||||||
|
void _submit() {
|
||||||
|
if (_controller.text.trim().isEmpty) return;
|
||||||
|
widget.onComment(_controller.text.trim());
|
||||||
|
_controller.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final m = widget.moment;
|
||||||
|
|
||||||
|
return GlassCard(
|
||||||
|
padding: const EdgeInsets.all(12),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
CircleAvatar(backgroundImage: NetworkImage(m.avatar)),
|
||||||
|
const SizedBox(width: 10),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
m.nickname,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.purple,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 6),
|
||||||
|
Text(m.content, style: const TextStyle(color: Colors.white)),
|
||||||
|
|
||||||
|
if (m.images.isNotEmpty)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(top: 8),
|
||||||
|
child: LayoutBuilder(
|
||||||
|
builder: (context, constraints) {
|
||||||
|
final isSingle = m.images.length == 1;
|
||||||
|
final itemWidth =
|
||||||
|
isSingle ? 180.0 : (constraints.maxWidth - 8) / 3;
|
||||||
|
|
||||||
|
return Wrap(
|
||||||
|
spacing: 4,
|
||||||
|
runSpacing: 4,
|
||||||
|
children:
|
||||||
|
m.images.map((url) {
|
||||||
|
return ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
child: Image.network(
|
||||||
|
url,
|
||||||
|
width: itemWidth,
|
||||||
|
height: itemWidth,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Badge(
|
||||||
|
label: Text('${m.likeCount}'),
|
||||||
|
isLabelVisible: m.likeCount > 0,
|
||||||
|
offset: const Offset(0, 0),
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: widget.onLike,
|
||||||
|
icon: Icon(
|
||||||
|
m.liked ? Icons.favorite : Icons.favorite_border,
|
||||||
|
color: m.liked ? Colors.red : Colors.grey,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Badge(
|
||||||
|
label: Text('${m.comments.length}'),
|
||||||
|
isLabelVisible: m.comments.length > 0,
|
||||||
|
offset: const Offset(0, 0),
|
||||||
|
child: IconButton(
|
||||||
|
onPressed: () => {},
|
||||||
|
icon: Icon(Icons.comment, color: Colors.grey),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
if (m.comments.isNotEmpty)
|
||||||
|
Container(
|
||||||
|
width: double.infinity,
|
||||||
|
margin: const EdgeInsets.only(top: 6),
|
||||||
|
padding: const EdgeInsets.all(8),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(0xFF120D25),
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children:
|
||||||
|
m.comments
|
||||||
|
.map(
|
||||||
|
(c) => Text(
|
||||||
|
'${c.nickname}:${c.content}',
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
color: Colors.white,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:liquid_glass_widgets/liquid_glass_widgets.dart';
|
||||||
|
|
||||||
|
import 'chat_page.dart';
|
||||||
|
|
||||||
class MessagePage extends StatelessWidget {
|
class MessagePage extends StatelessWidget {
|
||||||
const MessagePage({super.key});
|
const MessagePage({super.key});
|
||||||
@@ -6,20 +9,20 @@ class MessagePage extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
backgroundColor: const Color(0xFFF5F5F7),
|
backgroundColor: Colors.transparent,
|
||||||
appBar: _buildAppBar(),
|
appBar: _buildAppBar(),
|
||||||
body: _buildMessageList(),
|
body: _buildMessageList(context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreferredSizeWidget _buildAppBar() {
|
PreferredSizeWidget _buildAppBar() {
|
||||||
return AppBar(
|
return AppBar(
|
||||||
backgroundColor: Colors.grey.shade200,
|
backgroundColor: Color(0xFF120D25),
|
||||||
elevation: 0,
|
elevation: 0,
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
leading: IconButton(
|
leading: IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(Icons.menu, size: 22),
|
icon: const Icon(Icons.menu, size: 22, color: Colors.white),
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
),
|
),
|
||||||
title: const Text(
|
title: const Text(
|
||||||
@@ -27,113 +30,106 @@ class MessagePage extends StatelessWidget {
|
|||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
color: Color(0xFF1C1C1E),
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(Icons.search, size: 22),
|
icon: const Icon(Icons.search, size: 22, color: Colors.white),
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {},
|
onPressed: () {},
|
||||||
icon: const Icon(Icons.add_circle_outline, size: 22),
|
icon: const Icon(Icons.add, size: 22, color: Colors.white),
|
||||||
splashRadius: 20,
|
splashRadius: 20,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildMessageList() {
|
Widget _buildMessageList(BuildContext context) {
|
||||||
return ListView.separated(
|
return ListView.separated(
|
||||||
|
padding: EdgeInsets.only(
|
||||||
|
left: 10,
|
||||||
|
right: 10,
|
||||||
|
top: 10,
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 80,
|
||||||
|
),
|
||||||
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
|
return SizedBox(height: 10);
|
||||||
|
},
|
||||||
itemCount: _messages.length,
|
itemCount: _messages.length,
|
||||||
separatorBuilder: (_, __) => const SizedBox(height: 0),
|
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
final msg = _messages[index];
|
final msg = _messages[index];
|
||||||
return Container(
|
return _buildMessageItem(context, msg);
|
||||||
decoration: const BoxDecoration(
|
},
|
||||||
color: Colors.white,
|
);
|
||||||
border: Border(
|
}
|
||||||
bottom: BorderSide(
|
|
||||||
color: Color(0xFFE5E5EA),
|
Widget _buildMessageItem(BuildContext context, Message msg) {
|
||||||
width: 0.6,
|
return GlassCard(
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
|
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 0),
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
|
onTap:
|
||||||
|
() => {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder:
|
||||||
|
(_) => const ChatPage(
|
||||||
|
contactName: '张三',
|
||||||
|
avatarUrl: 'https://picsum.photos/id/1012/200',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
leading: CircleAvatar(
|
leading: CircleAvatar(
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
backgroundImage: NetworkImage(msg['avatar']!),
|
backgroundImage: NetworkImage(msg.avatar),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
msg['name'].toString(),
|
msg.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
color: Color(0xFF1C1C1E),
|
color: Colors.white,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
msg['lastMsg'].toString(),
|
msg.lastMsg,
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontSize: 13, color: Color(0xFFAEAEB2)),
|
||||||
fontSize: 13,
|
|
||||||
color: Color(0xFF8E8E93),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
trailing: Text(
|
trailing: Text(
|
||||||
msg['time'].toString(),
|
msg.time,
|
||||||
style: const TextStyle(
|
style: const TextStyle(fontSize: 12, color: Color(0xFF8E8E93)),
|
||||||
fontSize: 12,
|
|
||||||
color: Color(0xFF8E8E93),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ✅ 假数据
|
class Message {
|
||||||
const List<Map<String, String>> _messages = [
|
final String name;
|
||||||
{
|
final String avatar;
|
||||||
'avatar': 'https://randomuser.me/api/portraits/men/32.jpg',
|
final String lastMsg;
|
||||||
'name': '小刘',
|
final String time;
|
||||||
'lastMsg': '今晚一起吃饭吗?',
|
|
||||||
'time': '12:30',
|
Message({
|
||||||
},
|
required this.name,
|
||||||
{
|
required this.avatar,
|
||||||
'avatar': 'https://randomuser.me/api/portraits/women/44.jpg',
|
required this.lastMsg,
|
||||||
'name': 'AI 助手',
|
required this.time,
|
||||||
'lastMsg': '已为你生成总结',
|
});
|
||||||
'time': '11:20',
|
}
|
||||||
},
|
|
||||||
{
|
List<Message> _messages = [
|
||||||
'avatar': 'https://randomuser.me/api/portraits/men/65.jpg',
|
Message(
|
||||||
'name': '产品经理',
|
avatar: 'https://picsum.photos/id/1012/200',
|
||||||
'lastMsg': '新版本评审定在周五',
|
name: '小刘',
|
||||||
'time': '昨天',
|
lastMsg: '今晚一起吃饭吗?',
|
||||||
},
|
time: '12:30',
|
||||||
{
|
),
|
||||||
'avatar': 'https://randomuser.me/api/portraits/men/32.jpg',
|
|
||||||
'name': '小刘',
|
|
||||||
'lastMsg': '今晚一起吃饭吗?',
|
|
||||||
'time': '12:30',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'avatar': 'https://randomuser.me/api/portraits/women/44.jpg',
|
|
||||||
'name': 'AI 助手',
|
|
||||||
'lastMsg': '已为你生成总结',
|
|
||||||
'time': '11:20',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'avatar': 'https://randomuser.me/api/portraits/men/65.jpg',
|
|
||||||
'name': '产品经理',
|
|
||||||
'lastMsg': '新版本评审定在周五',
|
|
||||||
'time': '昨天',
|
|
||||||
},
|
|
||||||
];
|
];
|
||||||
93
pubspec.yaml
93
pubspec.yaml
@@ -1,92 +1 @@
|
|||||||
name: sweet_chat_app
|
name: sweet_chat_app
|
||||||
description: "A new Flutter project."
|
|
||||||
# The following line prevents the package from being accidentally published to
|
|
||||||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|
||||||
|
|
||||||
# The following defines the version and build number for your application.
|
|
||||||
# A version number is three numbers separated by dots, like 1.2.43
|
|
||||||
# followed by an optional build number separated by a +.
|
|
||||||
# Both the version and the builder number may be overridden in flutter
|
|
||||||
# build by specifying --build-name and --build-number, respectively.
|
|
||||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
|
||||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion.
|
|
||||||
# Read more about iOS versioning at
|
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
|
||||||
version: 1.0.0+1
|
|
||||||
|
|
||||||
environment:
|
|
||||||
sdk: ^3.7.0
|
|
||||||
|
|
||||||
# Dependencies specify other packages that your package needs in order to work.
|
|
||||||
# To automatically upgrade your package dependencies to the latest versions
|
|
||||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
|
||||||
# dependencies can be manually updated by changing the version numbers below to
|
|
||||||
# the latest version available on pub.dev. To see which dependencies have newer
|
|
||||||
# versions available, run `flutter pub outdated`.
|
|
||||||
dependencies:
|
|
||||||
flutter:
|
|
||||||
sdk: flutter
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
|
||||||
# Use with the CupertinoIcons class for iOS style icons.
|
|
||||||
cupertino_icons: ^1.0.8
|
|
||||||
liquid_glass_widgets: ^0.16.1
|
|
||||||
azlistview: ^2.0.0
|
|
||||||
lpinyin: ^2.0.3
|
|
||||||
|
|
||||||
dev_dependencies:
|
|
||||||
flutter_test:
|
|
||||||
sdk: flutter
|
|
||||||
|
|
||||||
# The "flutter_lints" package below contains a set of recommended lints to
|
|
||||||
# encourage good coding practices. The lint set provided by the package is
|
|
||||||
# activated in the `analysis_options.yaml` file located at the root of your
|
|
||||||
# package. See that file for information about deactivating specific lint
|
|
||||||
# rules and activating additional ones.
|
|
||||||
flutter_lints: ^5.0.0
|
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
|
||||||
|
|
||||||
# The following section is specific to Flutter packages.
|
|
||||||
flutter:
|
|
||||||
|
|
||||||
# The following line ensures that the Material Icons font is
|
|
||||||
# included with your application, so that you can use the icons in
|
|
||||||
# the material Icons class.
|
|
||||||
uses-material-design: true
|
|
||||||
|
|
||||||
# To add assets to your application, add an assets section, like this:
|
|
||||||
# assets:
|
|
||||||
# - images/a_dot_burr.jpeg
|
|
||||||
# - images/a_dot_ham.jpeg
|
|
||||||
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
|
||||||
# https://flutter.dev/to/resolution-aware-images
|
|
||||||
|
|
||||||
# For details regarding adding assets from package dependencies, see
|
|
||||||
# https://flutter.dev/to/asset-from-package
|
|
||||||
|
|
||||||
# To add custom fonts to your application, add a fonts section here,
|
|
||||||
# in this "flutter" section. Each entry in this list should have a
|
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
|
||||||
# list giving the asset and other descriptors for the font. For
|
|
||||||
# example:
|
|
||||||
# fonts:
|
|
||||||
# - family: Schyler
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/Schyler-Regular.ttf
|
|
||||||
# - asset: fonts/Schyler-Italic.ttf
|
|
||||||
# style: italic
|
|
||||||
# - family: Trajan Pro
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/TrajanPro.ttf
|
|
||||||
# - asset: fonts/TrajanPro_Bold.ttf
|
|
||||||
# weight: 700
|
|
||||||
#
|
|
||||||
# For details regarding fonts from package dependencies,
|
|
||||||
# see https://flutter.dev/to/font-from-package
|
|
||||||
Reference in New Issue
Block a user