Files
blog_app/lib/pages/home_page.dart
2025-11-16 22:10:53 +08:00

248 lines
5.5 KiB
Dart

import 'package:blog_app/apis/blog.dart';
import 'package:blog_app/layout/drawer.dart';
import 'package:blog_app/layout/menu.dart';
import 'package:blog_app/layout/nav_bar.dart';
import 'package:blog_app/models/blog.dart';
import 'package:blog_app/widget/search.dart';
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
const HomePage({super.key});
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
int _currentPageIndex = 0;
late PageController _pageController;
bool _isSearching = false;
final TextEditingController _searchController = TextEditingController();
final FocusNode _searchFocusNode = FocusNode();
List<BlogSearch> _searchResults = [];
String _searchQuery = '';
@override
void initState() {
super.initState();
_pageController = PageController(initialPage: _currentPageIndex);
}
@override
void dispose() {
_pageController.dispose();
_searchController.dispose();
_searchFocusNode.dispose();
super.dispose();
}
void _startSearch() {
setState(() {
_isSearching = true;
});
Future.delayed(Duration(milliseconds: 100), () {
_searchFocusNode.requestFocus();
});
}
void _exitSearch() {
setState(() {
_isSearching = false;
_searchController.clear();
_searchResults.clear();
_searchQuery = '';
});
FocusScope.of(context).unfocus();
}
void _clearSearch() {
_searchController.clear();
setState(() {
_searchResults.clear();
_searchQuery = '';
});
}
void _onSearchTextChanged(String query) async {
setState(() {
_searchQuery = query;
});
if (query.isEmpty) {
setState(() {
_searchResults.clear();
});
return;
}
final result = await searchBlog(query);
setState(() {
_searchResults = result;
});
}
Widget _buildLeading() {
if (_isSearching) {
return IconButton(
icon: Icon(Icons.arrow_back, color: Colors.white),
onPressed: _exitSearch,
);
}
return Builder(
builder:
(context) => IconButton(
icon: Icon(Icons.menu, color: Colors.white),
onPressed: () => Scaffold.of(context).openDrawer(),
),
);
}
Widget _buildAppBarTitle() {
if (_isSearching) {
return buildSearchField(
controller: _searchController,
focusNode: _searchFocusNode,
onChanged: _onSearchTextChanged,
);
}
return Text(
pages[_currentPageIndex].title,
style: TextStyle(color: Colors.white),
);
}
List<Widget> _buildAppBarActions() {
if (_isSearching) {
return [
if (_searchController.text.isNotEmpty)
IconButton(
icon: Icon(Icons.clear, color: Colors.white),
onPressed: _clearSearch,
),
];
} else {
return [
IconButton(
icon: Icon(Icons.search, color: Colors.white),
onPressed: _startSearch,
),
];
}
}
Widget _buildPageView() {
return _isSearching ? _buildSearchResults() : _buildNormalPageView();
}
Widget _buildNormalPageView() {
return PageView(
controller: _pageController,
onPageChanged: (index) {
setState(() {
_currentPageIndex = index;
if (_isSearching) {
_exitSearch();
}
});
},
children: pageWidgets,
);
}
Widget _buildSearchResults() {
if (_searchQuery.isEmpty) {
return buildSearchQueryEmpty();
}
if (_searchResults.isEmpty) {
return buildSearchResultEmpty(_searchQuery);
}
return buildSearchResultList(context, _searchResults);
}
void _onBottomNavTap(int index) {
setState(() {
_currentPageIndex = index;
if (_isSearching) {
_exitSearch();
}
});
_pageController.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
}
void onTapDrawerItem(int index) {
setState(() {
_currentPageIndex = index;
if (_isSearching) {
_exitSearch();
}
});
_pageController.animateToPage(
index,
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
);
Navigator.pop(context);
}
Widget _buildDrawerBody() {
return ListView(
padding: EdgeInsets.zero,
children: [
...List.generate(
pages.length,
(index) => buildDrawerItem(
context: context,
page: pages[index],
isSelected: index == _currentPageIndex,
onTap: () => onTapDrawerItem(index),
),
),
],
);
}
Widget _buildDrawer() {
return Drawer(
child: Container(
color: Colors.white,
child: Column(
children: [
buildDrawerHeader(context),
Expanded(child: _buildDrawerBody()),
],
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: _buildAppBarTitle(),
backgroundColor: Theme.of(context).colorScheme.primary,
elevation: 0,
leading: _buildLeading(),
actions: _buildAppBarActions(),
),
drawer: _buildDrawer(),
body: Padding(padding: EdgeInsets.all(10), child: _buildPageView()),
bottomNavigationBar: buildBottomNavigationBar(
context: context,
index: _currentPageIndex,
onTap: _onBottomNavTap,
),
);
}
}