我对 Flutter 还很陌生,我正在尝试开发一个音乐应用程序。我的问题是:我对主页(和其他页面)上的应用栏和导航栏的外观进行了设计。现在我有了应用栏,但我想添加如图所示的导航栏。设计这种设计在Flutter中可以吗?因为我没有找到任何方法来实现这一点。这就是主页现在的样子。主屏幕的外观下面我将提供整个主屏幕代码。
import 'dart:convert';
import 'package:aurora_music_v01/screens/login_screen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:http/http.dart' as http;
import 'package:version/version.dart';
import 'package:url_launcher/url_launcher.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
late bool isDarkMode;
bool isWelcomeBackVisible = true;
bool isAuroraMusicVisible = false;
User? user;
Version? latestVersion;
@override
void initState() {
super.initState();
user = FirebaseAuth.instance.currentUser;
Future.delayed(const Duration(milliseconds: 1500), () {
setState(() {
isWelcomeBackVisible = false;
});
});
Future.delayed(const Duration(milliseconds: 2500), () {
setState(() {
isAuroraMusicVisible = true;
});
});
checkForNewVersion();
}
Future<void> checkForNewVersion() async {
try {
final response = await http.get(Uri.parse('api_github_link'));
if (response.statusCode == 200) {
final data = jsonDecode(response.body);
final versionString = data['tag_name'];
final regex = RegExp(r'^v?(\d+\.\d+\.\d+(-\S+)?)$');
final match = regex.firstMatch(versionString);
if (match!= null && match.groupCount > 0) {
final versionString = match.group(1)!;
setState(() {
latestVersion = Version.parse(versionString);
});
}
}
} catch (e) {
print('Error fetching latest version: $e');
}
}
void launchURL(String url) async {
if (await canLaunch(url)) {
try {
await launch(url);
} catch (e) {
print('Error launching URL: $e');
}
} else {
throw 'Could not launch $url';
}
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
isDarkMode = MediaQuery.of(context).platformBrightness == Brightness.dark;
}
@override
Widget build(BuildContext context) {
final regex = RegExp(r'^v?(\d+\.\d+\.\d+)(-[a-zA-Z]+)?$');
final match = regex.firstMatch('v0.0.5-alpha');
final currentVersion = Version.parse(match!.group(1)!);
final isUpdateAvailable = latestVersion!= null && latestVersion!.compareTo(currentVersion) > 0;
if (isUpdateAvailable) {
Future.delayed(Duration.zero, () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('New version available'),
content: const Text('A new version of Aurora Music is available. Would you like to download it now?'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: const Text('Cancel'),
),
TextButton(
onPressed: () async {
Navigator.pop(context);
await launch('github_link');
},
child: const Text('Download'),
),
],
);
},
);
});
}
return user == null
? LoginPage()
: Stack(
children: [
Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.transparent,
image: DecorationImage(
image: AssetImage(isDarkMode
? 'assets/images/background/dark_back.jpg'
: 'assets/images/background/light_back.jpg'),
fit: BoxFit.cover,
),
),
),
AppBar(
backgroundColor: Colors.transparent,
elevation: 0.0,
toolbarHeight: 230,
automaticallyImplyLeading: false,
title: Center(
child: Stack(
children: [
AnimatedOpacity(
opacity: isWelcomeBackVisible? 1.0 : 0.0,
duration: const Duration(seconds: 1),
child: const Text(
' Welcome Back',
style: TextStyle(
fontFamily: 'Outfit',
fontStyle: FontStyle.normal,
color: Colors.white,
fontSize: 34,
fontWeight: FontWeight.normal),
),
),
AnimatedOpacity(
opacity: isAuroraMusicVisible? 1.0 : 0.0,
duration: const Duration(seconds: 1),
child: const Text(
' Aurora Music',
style: TextStyle(
fontFamily: 'Outfit',
fontStyle: FontStyle.normal,
color: Colors.white,
fontSize: 34,
fontWeight: FontWeight.normal),
),
),
],
),
),
),
const SizedBox(
height: 50,
),
const Center(
child: Text(
'App is under construction. Come back later!',
style: TextStyle(
fontFamily: 'Outfit',
fontStyle: FontStyle.normal,
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.normal),
),
),
Align(
alignment: Alignment.bottomCenter,
child: ElevatedButton(
onPressed: () async {
await FirebaseAuth.instance.signOut();
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => LoginPage()),
);
},
child: Text(
'Log out',
style: TextStyle(
fontFamily: 'Outfit',
fontStyle: FontStyle.normal,
color: Color.fromARGB(255, 123, 14, 213),
fontSize: 18,
fontWeight: FontWeight.normal,
),
),
),
),
],
);
}
}
要获得这样的输出,请将欢迎写回容器中并在 Row 小部件中执行此操作,给它 MainAxisalignment: center 并添加您想要的背景颜色和字体颜色到文本中,并且对于以下导航使用应该使用这种代码(例如代码)
body: DefaultTabController(
length: 5, // Add one more tab for the RoadMap
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start, // Align tabs to the start
mainAxisAlignment: MainAxisAlignment.start, // Align tabs to the start
children: [
TabBar(
tabAlignment: TabAlignment.center,
isScrollable: true,
indicatorSize: TabBarIndicatorSize.tab,
tabs: [
Tab(text: 'Index'),
Tab(text: 'Programs'),
Tab(text: 'RoadMap'),
Tab(text: 'Interview'),
Tab(text: 'Description'),
],
),
Expanded(
child: TabBarView(
children: [
IndexPage(),
ProgramsPage(),
RoadMapPage(),
InterviewPage(),
DescriptionPage(),
],
),
),
],
如果您想创建与图像中显示的内容相同的内容,那么您首先使用 sizedbox 在 welocom 返回容器和此导航之间留出空间,然后在行小部件中编写用于发现的文本,然后为“For You”使用按钮样式通过给它边框半径“ borderRadius: BorderRadius.circular(18.0) ”,对于其他两个使用容器并给 MainAxisAllignment:spacearound 添加图像中显示的空间