Change home titlebar to scrollable

This commit is contained in:
stonegate 2020-04-30 01:32:45 +08:00
parent a758c2d96d
commit 69d2568513
6 changed files with 209 additions and 250 deletions

View File

@ -25,6 +25,29 @@ void callbackDispatcher() {
});
}
ThemeData lightTheme = ThemeData(
accentColorBrightness: Brightness.dark,
primaryColor: Colors.grey[100],
// accentColor: _accentSetColor,
primaryColorLight: Colors.white,
primaryColorDark: Colors.grey[300],
dialogBackgroundColor: Colors.white,
backgroundColor: Colors.grey[100],
appBarTheme: AppBarTheme(
color: Colors.grey[100],
elevation: 0,
),
textTheme: TextTheme(
bodyText2: TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal),
),
tabBarTheme: TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey[400],
),
);
class SettingState extends ChangeNotifier {
KeyValueStorage themeStorage = KeyValueStorage(themesKey);
KeyValueStorage accentStorage = KeyValueStorage(accentsKey);

View File

@ -12,80 +12,14 @@ import 'package:fluttertoast/fluttertoast.dart';
import '../../class/searchpodcast.dart';
import '../../class/subscribe_podcast.dart';
import '../../home/appbar/popupmenu.dart';
import '../../util/context_extension.dart';
import '../../webfeed/webfeed.dart';
import '../../.env.dart';
import '../nested_home.dart';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final _MyHomePageDelegate _delegate = _MyHomePageDelegate();
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
var _androidAppRetain = MethodChannel("android_app_retain");
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarIconBrightness:
Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
// statusBarColor: Theme.of(context).primaryColor,
),
child: Scaffold(
key: _scaffoldKey,
appBar: AppBar(
//elevation: 1.0,
centerTitle: true,
leading: IconButton(
tooltip: 'Add',
icon: const Icon(Icons.add_circle_outline),
onPressed: () async {
await showSearch<int>(
context: context,
delegate: _delegate,
);
},
),
title: Image(
image: Theme.of(context).brightness == Brightness.light
? AssetImage('assets/text.png')
: AssetImage('assets/text_light.png'),
height: 30,
),
actions: <Widget>[
PopupMenu(),
],
),
body: WillPopScope(
onWillPop: () async {
if (Platform.isAndroid) {
_androidAppRetain.invokeMethod('sendToBackground');
return false;
} else {
return true;
}
},
child: Home(),
),
),
);
}
}
class _MyHomePageDelegate extends SearchDelegate<int> {
class MyHomePageDelegate extends SearchDelegate<int> {
final String searchFieldLabel;
MyHomePageDelegate({this.searchFieldLabel})
: super(searchFieldLabel: searchFieldLabel);
static Future<List> getList(String searchText) async {
String apiKey = environment['apiKey'];
String url =
@ -329,89 +263,6 @@ class _SearchResultState extends State<SearchResult>
subscribeWorker.setSubscribeItem(item);
}
// savePodcast(String rss) async {
// if (mounted) setState(() => _adding = true);
// importOmpl.importState = ImportState.import;
// try {
// BaseOptions options = new BaseOptions(
// connectTimeout: 30000,
// receiveTimeout: 30000,
// );
// Response response = await Dio(options).get(rss);
// var dbHelper = DBHelper();
// String _realUrl = response.realUri.toString();
// bool _checkUrl = await dbHelper.checkPodcast(_realUrl);
// if (_checkUrl) {
// if (mounted) setState(() => _issubscribe = true);
// var _p = RssFeed.parse(response.data);
// print(_p.title);
// var dir = await getApplicationDocumentsDirectory();
// Response<List<int>> imageResponse = await Dio().get<List<int>>(
// _p.itunes.image.href,
// options: Options(responseType: ResponseType.bytes));
// img.Image image = img.decodeImage(imageResponse.data);
// img.Image thumbnail = img.copyResize(image, width: 300);
// String _uuid = Uuid().v4();
// File("${dir.path}/$_uuid.png")
// ..writeAsBytesSync(img.encodePng(thumbnail));
// String _imagePath = "${dir.path}/$_uuid.png";
// String _primaryColor = await getColor(File("${dir.path}/$_uuid.png"));
// String _author = _p.itunes.author ?? _p.author ?? '';
// String _provider = _p.generator ?? '';
// String _link = _p.link ?? '';
// PodcastLocal podcastLocal = PodcastLocal(
// _p.title,
// _p.itunes.image.href,
// _realUrl,
// _primaryColor,
// _author,
// _uuid,
// _imagePath,
// _provider,
// _link,
// description: _p.description);
// await groupList.subscribe(podcastLocal);
// if (_provider.contains('fireside')) {
// FiresideData data = FiresideData(_uuid, _link);
// await data.fatchData();
// }
// importOmpl.importState = ImportState.parse;
// await dbHelper.savePodcastRss(_p, _uuid);
// groupList.updatePodcast(podcastLocal.id);
// importOmpl.importState = ImportState.complete;
// } else {
// importOmpl.importState = ImportState.error;
// Fluttertoast.showToast(
// msg: 'Podcast subscribed already',
// gravity: ToastGravity.TOP,
// );
// await Future.delayed(Duration(seconds: 10));
// importOmpl.importState = ImportState.stop;
// }
// } catch (e) {
// importOmpl.importState = ImportState.error;
// Fluttertoast.showToast(
// msg: 'Network error, Subscribe failed',
// gravity: ToastGravity.TOP,
// );
// await Future.delayed(Duration(seconds: 5));
// importOmpl.importState = ImportState.stop;
// }
// }
return Container(
decoration: BoxDecoration(
border: Border(

View File

@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart' hide NestedScrollView;
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/class/download_state.dart';
import 'package:tsacdop/class/podcast_group.dart';
@ -21,6 +22,8 @@ import '../util/custompaint.dart';
import '../home/appbar/importompl.dart';
import '../home/audioplayer.dart';
import 'appbar/addpodcast.dart';
import 'appbar/popupmenu.dart';
import 'home_groups.dart';
import 'download_list.dart';
@ -30,6 +33,10 @@ class Home extends StatefulWidget {
}
class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
final MyHomePageDelegate _delegate =
MyHomePageDelegate(searchFieldLabel: 'Search podcast');
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
TabController _controller;
Decoration _getIndicator(BuildContext context) {
return UnderlineTabIndicator(
@ -41,6 +48,8 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
));
}
var _androidAppRetain = MethodChannel("android_app_retain");
@override
void initState() {
super.initState();
@ -58,83 +67,134 @@ class _HomeState extends State<Home> with SingleTickerProviderStateMixin {
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = (width - 20) / 3 + 140;
return SafeArea(
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Import(),
Expanded(
child: NestedScrollView(
innerScrollPositionKeyBuilder: () {
return Key('tab' + _controller.index.toString());
},
pinnedHeaderSliverHeightBuilder: () => 50,
headerSliverBuilder:
(BuildContext context, bool innerBoxScrolled) {
return <Widget>[
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return SizedBox(
height: height,
width: width,
child: ScrollPodcasts(),
);
return AnnotatedRegion<SystemUiOverlayStyle>(
value: SystemUiOverlayStyle(
systemNavigationBarIconBrightness:
Theme.of(context).accentColorBrightness,
statusBarIconBrightness: Theme.of(context).accentColorBrightness,
systemNavigationBarColor: Theme.of(context).primaryColor,
),
child: Scaffold(
key: _scaffoldKey,
body: WillPopScope(
onWillPop: () async {
if (Platform.isAndroid) {
_androidAppRetain.invokeMethod('sendToBackground');
return false;
} else {
return true;
}
},
child: SafeArea(
child: Stack(
children: <Widget>[
Column(
children: <Widget>[
Import(),
Expanded(
child: NestedScrollView(
innerScrollPositionKeyBuilder: () {
return Key('tab' + _controller.index.toString());
},
childCount: 1,
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(
indicator: _getIndicator(context),
isScrollable: true,
indicatorSize: TabBarIndicatorSize.tab,
pinnedHeaderSliverHeightBuilder: () => 50,
headerSliverBuilder:
(BuildContext context, bool innerBoxScrolled) {
return <Widget>[
SliverToBoxAdapter(
child: SizedBox(
height: 50.0,
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
IconButton(
tooltip: 'Add',
icon: const Icon(
Icons.add_circle_outline),
onPressed: () async {
await showSearch<int>(
context: context,
delegate: _delegate,
);
},
),
Image(
image: Theme.of(context).brightness ==
Brightness.light
? AssetImage('assets/text.png')
: AssetImage(
'assets/text_light.png'),
height: 30,
),
PopupMenu(),
],
),
),
),
SliverList(
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return SizedBox(
height: height,
width: width,
child: ScrollPodcasts(),
);
},
childCount: 1,
),
),
SliverPersistentHeader(
delegate: _SliverAppBarDelegate(
TabBar(
indicator: _getIndicator(context),
isScrollable: true,
indicatorSize: TabBarIndicatorSize.tab,
controller: _controller,
tabs: <Widget>[
Tab(
child: Text('Recent Update'),
),
Tab(
child: Text('Favorite'),
),
Tab(
child: Text('Download'),
)
],
),
),
pinned: true,
),
];
},
body: TabBarView(
controller: _controller,
tabs: <Widget>[
Tab(
child: Text('Recent Update'),
),
Tab(
child: Text('Favorite'),
),
Tab(
child: Text('Download'),
)
children: <Widget>[
NestedScrollViewInnerScrollPositionKeyWidget(
Key('tab0'), _RecentUpdate()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key('tab1'), _MyFavorite()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key('tab2'), _MyDownload()),
],
),
),
pinned: true,
),
];
},
body: TabBarView(
controller: _controller,
children: <Widget>[
NestedScrollViewInnerScrollPositionKeyWidget(
Key('tab0'), _RecentUpdate()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key('tab1'), _MyFavorite()),
NestedScrollViewInnerScrollPositionKeyWidget(
Key('tab2'), _MyDownload()),
Selector<AudioPlayerNotifier, bool>(
selector: (_, audio) => audio.playerRunning,
builder: (_, data, __) {
return Padding(
padding: EdgeInsets.only(bottom: data ? 60.0 : 0),
);
}),
],
),
),
Container(child: PlayerWidget()),
],
),
Selector<AudioPlayerNotifier, bool>(
selector: (_, audio) => audio.playerRunning,
builder: (_, data, __) {
return Padding(
padding: EdgeInsets.only(bottom: data ? 60.0 : 0),
);
}),
],
),
),
Container(child: PlayerWidget()),
],
),
);
));
}
}
@ -573,7 +633,7 @@ class _RecentUpdateState extends State<_RecentUpdate>
),
]),
)
: Center(child: CircularProgressIndicator());
: Center();
},
);
}

View File

@ -40,6 +40,14 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
_groupIndex = 0;
}
Widget _circleContainer(BuildContext context) => Container(
margin: EdgeInsets.symmetric(horizontal: 10),
height: 50,
width: 50,
decoration:
BoxDecoration(shape: BoxShape.circle, color: context.primaryColor),
);
@override
Widget build(BuildContext context) {
double _width = MediaQuery.of(context).size.width;
@ -137,16 +145,49 @@ class _ScrollPodcastsState extends State<ScrollPodcasts> {
),
),
Container(
height: 70,
color:
Theme.of(context).scaffoldBackgroundColor,
),
height: 70,
color:
Theme.of(context).scaffoldBackgroundColor,
child: Row(
children: <Widget>[
_circleContainer(context),
_circleContainer(context),
_circleContainer(context)
],
)),
],
)),
Container(
height: (_width - 20) / 3 + 40,
color: Theme.of(context).primaryColor,
margin: EdgeInsets.symmetric(horizontal: 15),
child: Center(
child: _groupIndex == 0
? Text.rich(TextSpan(
style: context.textTheme.headline6
.copyWith(height: 2),
children: [
TextSpan(
text: 'Welcome to Tsacdop\n',
style: context.textTheme.headline6
.copyWith(
color: context.accentColor)),
TextSpan(
text: 'Get started\n',
style: context.textTheme.headline6
.copyWith(
color: context.accentColor)),
TextSpan(text: 'Tap '),
WidgetSpan(
child:
Icon(Icons.add_circle_outline)),
TextSpan(text: ' to subscribe podcasts')
],
))
: Text('No podcast in this group',
style: TextStyle(
color: context.textTheme.bodyText2.color
.withOpacity(0.5)))),
),
],
),

View File

@ -2,7 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import 'package:tsacdop/class/settingstate.dart';
import 'package:tsacdop/home/appbar/addpodcast.dart';
import 'package:tsacdop/home/home.dart';
import 'package:tsacdop/util/pageroute.dart';
import 'fourthpage.dart';
import 'secondpage.dart';
@ -209,7 +209,7 @@ class _SlideIntroState extends State<SlideIntro> {
onTap: () {
if (widget.goto == Goto.home) {
Navigator.push(context,
SlideLeftRoute(page: MyHomePage()));
SlideLeftRoute(page: Home()));
Provider.of<SettingState>(context,
listen: false)
.saveShowIntro();

View File

@ -4,12 +4,12 @@ import 'package:flutter/services.dart';
import 'package:flutter_downloader/flutter_downloader.dart';
import 'class/podcast_group.dart';
import 'home/appbar/addpodcast.dart';
import 'class/audiostate.dart';
import 'class/settingstate.dart';
import 'class/download_state.dart';
import 'class/refresh_podcast.dart';
import 'class/subscribe_podcast.dart';
import 'home/home.dart';
import 'intro_slider/app_intro.dart';
final SettingState themeSetting = SettingState();
@ -20,14 +20,16 @@ Future main() async {
runApp(
MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => themeSetting),
ChangeNotifierProvider(
create: (_) => themeSetting,
),
ChangeNotifierProvider(create: (_) => AudioPlayerNotifier()),
ChangeNotifierProvider(create: (_) => GroupList()),
ChangeNotifierProvider(create: (_) => SubscribeWorker()),
ChangeNotifierProvider(create: (_) => RefreshWorker()),
ChangeNotifierProvider(
create: (_) => DownloadState(),
),
)
],
child: MyApp(),
),
@ -50,26 +52,8 @@ class MyApp extends StatelessWidget {
themeMode: setting.theme,
debugShowCheckedModeBanner: false,
title: 'Tsacdop',
theme: ThemeData(
accentColorBrightness: Brightness.dark,
primaryColor: Colors.grey[100],
theme: lightTheme.copyWith(
accentColor: setting.accentSetColor,
primaryColorLight: Colors.white,
primaryColorDark: Colors.grey[300],
dialogBackgroundColor: Colors.white,
backgroundColor: Colors.grey[100],
appBarTheme: AppBarTheme(
color: Colors.grey[100],
elevation: 0,
),
textTheme: TextTheme(
bodyText2:
TextStyle(fontSize: 15.0, fontWeight: FontWeight.normal),
),
tabBarTheme: TabBarTheme(
labelColor: Colors.black,
unselectedLabelColor: Colors.grey[400],
),
),
darkTheme: ThemeData.dark().copyWith(
accentColor: setting.accentSetColor,
@ -80,7 +64,7 @@ class MyApp extends StatelessWidget {
.copyWith(color: setting.realDark ? Colors.black87 : null),
appBarTheme: AppBarTheme(elevation: 0),
),
home: setting.showIntro ? SlideIntro(goto: Goto.home) : MyHomePage(),
home: setting.showIntro ? SlideIntro(goto: Goto.home) : Home(),
);
},
);