import 'dart:ui'; import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; import 'package:flutter_easyrefresh/easy_refresh.dart'; import 'package:sport/bean/forum.dart'; import 'package:sport/bean/post.dart'; import 'package:sport/pages/social/post_detail_page.dart'; import 'package:sport/pages/social/post_page.dart'; import 'package:sport/pages/social/post_widget.dart'; import 'package:sport/provider/lib/provider_widget.dart'; import 'package:sport/provider/lib/view_state_lifecycle.dart'; import 'package:sport/provider/social_detail_model.dart'; import 'package:sport/router/navigator_util.dart'; import 'package:sport/services/api/resp.dart'; import 'package:sport/services/userid.dart'; import 'package:sport/widgets/appbar.dart'; import 'package:sport/widgets/error.dart'; import 'package:sport/widgets/loading.dart'; import 'package:sport/widgets/misc.dart'; import 'package:sport/widgets/persistent_header.dart'; import 'package:sport/widgets/space.dart'; class SocialDetailPage extends StatefulWidget { final Forum forum; final int index; SocialDetailPage(this.forum, {this.index}); @override State createState() => _PageState(); } class _PageState extends ViewStateLifecycle with TickerProviderStateMixin, UserId { ScrollController _controller; double _expandedHeight = 0; int _brightness = 0; TabController _tabController; final List _tabs = ['热门', '关注', '最新', '精华', '我的']; Future> _getPostListByOfficial; @override SocialDetailModel createModel() => SocialDetailModel(widget.index ?? 0); @override void initState() { super.initState(); _getPostListByOfficial = model.api .getPostListByOfficial(forumId: widget.forum.forumId, limit: 3); _tabController = TabController( length: _tabs.length, initialIndex: widget.index ?? 0, vsync: this) ..addListener(() { if (_tabController.index.toDouble() == _tabController.animation.value) { model?.swtichTab(_tabController.index); _controller.animateTo(0, duration: Duration(milliseconds: 100), curve: Curves.ease); } }); _controller = ScrollController() ..addListener(() { if (_controller.position.pixels >= _expandedHeight - 70) { if (_brightness == 0) { setState(() { _brightness = 1; }); } } else { if (_brightness == 1) { setState(() { _brightness = 0; }); } } }); } @override void dispose() { super.dispose(); _controller?.dispose(); _tabController?.dispose(); PaintingBinding.instance.imageCache.clear(); } Widget _buildHeaderWidget() { return Stack(children: [ CachedNetworkImage( imageUrl: "${widget.forum.cover}", fit: BoxFit.cover, width: double.infinity, height: MediaQuery.of(context).size.width * 154.0 / 375 + MediaQuery.of(context).padding.top, ), BackdropFilter( filter: ImageFilter.blur(sigmaX: 30.0, sigmaY: 30.0), child: Center( child: Container( color: Colors.black.withOpacity(.3), ), ), ), Align( alignment: Alignment.center, child: Column( mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.fromLTRB(12.0, 50, 12.0, 0), child: Row( mainAxisAlignment: MainAxisAlignment.start, children: [ CircleAvatar( backgroundImage: CachedNetworkImageProvider("${widget.forum.cover}"), radius: 30.0), Space( width: 12, ), Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( "${widget.forum.name}", style: Theme.of(context).textTheme.headline4, ), Space( height: 10, ), Row( children: [ Image.asset( "lib/assets/img/bbs_icon_reportnumber.png"), Space( width: 4, ), Text( "帖子数:${widget.forum.subjectCount}", style: Theme.of(context) .textTheme .subtitle2 .copyWith(color: Colors.white), ), ], ), ], ), ], ), ), ], ), ), Positioned( left: 0, right: 0, bottom: -1, child: Container( height: 10, decoration: BoxDecoration( borderRadius: BorderRadius.vertical(top: Radius.circular(10)), color: Colors.white), ), ), ]); } Color getColor(String tag) { if (tag == "榜单" || tag == "公告") return Theme.of(context).accentColor; else if (tag == "置顶") { return const Color(0xff5498FF); } return const Color(0xff00DC42); } Widget _buildHeaderListWidget() { return Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.vertical(top: Radius.circular(10))), child: FutureBuilder>( future: _getPostListByOfficial, builder: (BuildContext context, AsyncSnapshot> snapshot) { if (snapshot.connectionState == ConnectionState.done && snapshot.data?.pageResult?.results?.isNotEmpty == true) { return Column(children: [ Space( height: 5, ), Column( children: snapshot.data.pageResult.results .map((e) => InkWell( onTap: () { Navigator.push(context, MaterialPageRoute(builder: (context) { return PostDetailPage(e, false, snapshot.data?.pageResult?.results ?? []); })); }, child: Row( children: [ Container( decoration: BoxDecoration( color: Colors.white, borderRadius: BorderRadius.all(Radius.circular(2)), border: Border.all( color: getColor(e.tags?.first), width: .5, )), padding: EdgeInsets.symmetric(horizontal: 2), margin: EdgeInsets.fromLTRB(12.0, 5, 6, 5), child: Text( "${e.tags.first}", strutStyle: fixedLine, style: Theme.of(context) .textTheme .subtitle2 .copyWith(color: getColor(e.tags?.first)), )), Expanded( child: Text( "${e.title?.isNotEmpty == true ? e.title : e.content}", maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context).textTheme.subtitle1), ) ], ))) .toList(), ), Space( height: 5, ), Divider() ]); } return Container(); }, ), ); } @override Widget build(BuildContext context) { _expandedHeight = MediaQuery.of(context).size.width * 154.0 / 375; return Scaffold( backgroundColor: Colors.white, body: Stack( children: [ ProviderWidget( model: model, onModelReady: (model) => model.initData(), builder: (_, model, __) { return EasyRefresh.builder( controller: model.refreshController, enableControlFinishRefresh: true, enableControlFinishLoad: true, onRefresh: () => model.refresh(), onLoad: model.isIdle ? () => model.loadMore() : null, header: buildClassicalHeader(), footer: buildClassicalFooter(), builder: (context, physics, header, footer) { return CustomScrollView( controller: _controller, physics: physics, slivers: [ SliverAppBar( expandedHeight: _expandedHeight, pinned: true, elevation: 0, iconTheme: IconThemeData( color: _brightness == 0 ? Colors.white : Colors.black), brightness: _brightness == 0 ? Brightness.dark : Brightness.light, title: _brightness == 0 ? Text("") : Text( "${widget.forum.name}", style: titleStyle, ), backgroundColor: Colors.white, flexibleSpace: FlexibleSpaceBar( collapseMode: CollapseMode.pin, background: _buildHeaderWidget(), ), leading: IconButton( icon: Image.asset( "lib/assets/img/topbar_return${_brightness == 0 ? "_white" : ""}.png"), onPressed: () { Navigator.of(context).pop(); }, ), ), header, SliverToBoxAdapter( child: _buildHeaderListWidget(), ), SliverPersistentHeader( delegate: PersistentHeader( min: 34, max: 34, child: Container( color: Colors.white, padding: EdgeInsets.only(bottom: 5), child: TabBar( isScrollable: true, indicatorPadding: EdgeInsets.symmetric(horizontal: 8), indicatorWeight: 3, controller: _tabController, tabs: _tabs.map((e) => Tab(text: e)).toList(), ), )), pinned: true, ), if (model.isBusy) SliverToBoxAdapter( child: RequestLoadingWidget(), ), if (model.isEmpty) SliverFillRemaining( child: Center( child: RequestErrorWidget( null, msg: "暂无帖子~", assets: RequestErrorWidget.ASSETS_NO_INVITATION, ), ), ), if (model.isIdle) SliverList( delegate: SliverChildBuilderDelegate( (context, index) { Post post = model.list[index]; return PostWidget( post, model, selfId == post.userId); }, childCount: model.list.length, ), ), ], ); }); }, ), Positioned( right: 12.0, bottom: 12.0, child: GestureDetector( onTap: () { NavigatorUtil.goPage( context, (context) => PostPage( widget.forum.forumId, forum: widget.forum, )); }, child: Image.asset("lib/assets/img/bbs_icon_edit.png"))) ], )); } }