From 4e705934c2807014d1964e83cc0c6fc2bde167de Mon Sep 17 00:00:00 2001 From: toly <1981462002@qq.com> Date: Sat, 16 Apr 2022 14:55:21 +0800 Subject: [PATCH] =?UTF-8?q?=E7=BB=84=E4=BB=B6=E8=AF=A6=E6=83=85=E9=A1=B5?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=20CustomScrollView=20=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/app/res/style/unit_text_style.dart | 14 + .../widget_detail_page.dart | 250 ++++++------------ .../widget_detail_panel.dart | 77 ++++++ 3 files changed, 177 insertions(+), 164 deletions(-) create mode 100644 lib/widget_system/views/widget_detail_view/widget_detail_panel.dart diff --git a/lib/app/res/style/unit_text_style.dart b/lib/app/res/style/unit_text_style.dart index 76af312..11c4cc9 100644 --- a/lib/app/res/style/unit_text_style.dart +++ b/lib/app/res/style/unit_text_style.dart @@ -4,6 +4,20 @@ import 'unit_color.dart'; ///文本样式 class TStyleUnit { + + // 标题加黑 + static const labelBold = TextStyle(fontWeight: FontWeight.bold, fontSize: 16); + static const commonChip = TextStyle( + fontSize: 12, + color: Colors.white, + ); + static const deprecatedChip = TextStyle( + fontSize: 12, + color: Colors.white, + decoration: TextDecoration.lineThrough, + decorationThickness: 2, + ); + static const lagerTextSize = 30.0; static const bigTextSize = 23.0; static const normalTextSize = 18.0; diff --git a/lib/widget_system/views/widget_detail_view/widget_detail_page.dart b/lib/widget_system/views/widget_detail_view/widget_detail_page.dart index 7a58819..0a300a8 100644 --- a/lib/widget_system/views/widget_detail_view/widget_detail_page.dart +++ b/lib/widget_system/views/widget_detail_view/widget_detail_page.dart @@ -1,13 +1,13 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_star/flutter_star.dart'; import 'package:flutter_unit/app/blocs/global/global_bloc.dart'; import 'package:flutter_unit/app/blocs/global/global_state.dart'; import 'package:flutter_unit/app/res/cons.dart'; +import 'package:flutter_unit/app/res/style/unit_text_style.dart'; import 'package:flutter_unit/app/res/toly_icon.dart'; import 'package:flutter_unit/app/utils/Toast.dart'; +import 'package:flutter_unit/components/permanent/code/highlighter_style.dart'; import 'package:flutter_unit/components/permanent/feedback_widget.dart'; -import 'package:flutter_unit/components/permanent/panel.dart'; import 'package:flutter_unit/components/project/widget_node_panel.dart'; import 'package:flutter_unit/widget_system/blocs/widget_system_bloc.dart'; import 'package:flutter_unit/widget_system/repositories/model/node_model.dart'; @@ -15,6 +15,7 @@ import 'package:flutter_unit/widget_system/repositories/model/widget_model.dart' import '../../widgets/widgets_map.dart'; import 'category_end_drawer.dart'; +import 'widget_detail_panel.dart'; class WidgetDetailPage extends StatefulWidget { final WidgetModel model; @@ -40,39 +41,62 @@ class _WidgetDetailPageState extends State { @override Widget build(BuildContext context) { - return Scaffold( - endDrawer: CategoryEndDrawer(widget: _modelStack.last), - appBar: AppBar( - title: Text(_modelStack.last.name), - leading: const BackButton(), - actions: [ - _buildToHome(), - FeedbackWidget( - onPressed: () => _toggleLikeState(context), - child: BlocConsumer( - listener: _listenLikeStateChange, - builder: _buildByLikeState, - ), - ) - ], + return BlocBuilder( + builder: (_, state) => Scaffold( + endDrawer: CategoryEndDrawer(widget: currentWidgetModel), + appBar: AppBar( + title: Text(currentWidgetModel.name), + leading: const BackButton(), + actions: [ + _buildToHome(), + FeedbackWidget( + onPressed: () => _toggleLikeState(context), + child: BlocConsumer( + listener: _listenLikeStateChange, + builder: _buildByLikeState, + ), + ) + ], + ), + body: Builder(builder: (ctx) { + return _buildContent(ctx, state); + }), ), - body: Builder(builder: _buildContent), ); } - Widget _buildContent(BuildContext context) => WillPopScope( - onWillPop: () => _whenPop(context), - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - WidgetDetailTitle( - model: _modelStack.last, + Widget get linkText => Row( + children: const [ + Padding( + padding: EdgeInsets.only(left: 15, right: 5), + child: Icon(Icons.link, color: Colors.blue), + ), + Text('相关组件', style: TStyleUnit.labelBold), + ], + ); + + Widget _buildContent(BuildContext context, DetailState state) { + return WillPopScope( + onWillPop: () => _whenPop(context), + child: CustomScrollView( + slivers: [ + SliverToBoxAdapter( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + WidgetDetailPanel(model: _modelStack.last), + linkText, + if (state is DetailWithData) + _buildLinkTo(context, state.links), + const Divider(), + ], + ), ), - BlocBuilder(builder: _buildDetail) + if (state is DetailWithData) + _buildSliverNodeList(state.nodes, state.widgetModel.name) ], - ), - )); + )); + } Widget _buildToHome() => Builder( builder: (ctx) => GestureDetector( @@ -117,66 +141,24 @@ class _WidgetDetailPageState extends State { void _toggleLikeState(BuildContext context) { - BlocProvider.of(context) - .add(ToggleLikeWidgetEvent(id: currentWidgetModel.id)); - } - - Widget _buildNodes(List nodes, String name) { - GlobalState globalState = BlocProvider.of(context).state; - return Column( - children: nodes - .asMap() - .keys - .map((i) => WidgetNodePanel( - codeStyle: Cons.codeThemeSupport.keys.toList()[globalState.codeStyleIndex], - codeFamily: 'Inconsolata', - text: nodes[i].name, - subText: nodes[i].subtitle, - code: nodes[i].code, - show: WidgetsMap.map(name)[i], - )) - .toList()); + BlocProvider.of(context).add( + ToggleLikeWidgetEvent(id: currentWidgetModel.id), + ); } Future _whenPop(BuildContext context) async { if (Scaffold.of(context).isEndDrawerOpen) return true; _modelStack.removeLast(); if (_modelStack.isNotEmpty) { - setState(() { - BlocProvider.of(context).add(FetchWidgetDetail(_modelStack.last)); - }); + BlocProvider.of(context).add( + FetchWidgetDetail(currentWidgetModel), + ); return false; } else { return true; } } - Widget _buildDetail(BuildContext context, DetailState state) { - if (state is DetailWithData) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: const[ - Padding( - padding: EdgeInsets.only(left: 15, right: 5), - child: Icon(Icons.link, color: Colors.blue), - ), - Text( - '相关组件', - style: TextStyle(fontWeight: FontWeight.bold, fontSize: 16), - ), - ], - ), - _buildLinkTo(context, state.links), - const Divider(), - _buildNodes(state.nodes, state.widgetModel.name) - ], - ); - } - return Container(); - } - Color? get chipColor => isDark ? Theme.of(context).floatingActionButtonTheme.backgroundColor : Theme.of(context).primaryColor; @@ -196,103 +178,43 @@ class _WidgetDetailPageState extends State { child: Wrap( spacing: 5, children: links - .map((e) => ActionChip( - onPressed: () { - BlocProvider.of(context) - .add(FetchWidgetDetail(e)); - setState(() { - _modelStack.add(e); - }); - }, + .map((WidgetModel model) => ActionChip( + onPressed: () => _toLinkWidget(model), elevation: 2, shadowColor: chipColor, backgroundColor: chipColor, - labelStyle: TextStyle( - fontSize: 12, - color: Colors.white, - decoration: (e.deprecated) - ? TextDecoration.lineThrough - : TextDecoration.none, - decorationThickness: 2, - ), - label: Text(e.name), + labelStyle: model.deprecated + ? TStyleUnit.deprecatedChip + : TStyleUnit.commonChip, + label: Text(model.name), )) .toList(), ), ); } } -} -class WidgetDetailTitle extends StatelessWidget { - final WidgetModel model; - - const WidgetDetailTitle({Key? key, required this.model}) : super(key: key); - - @override - Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - children: [ - _buildLeft(model, context), - _buildRight(model), - ], - ), - const Divider(), - ], - ); + void _toLinkWidget(WidgetModel model) { + BlocProvider.of(context).add(FetchWidgetDetail(model)); + _modelStack.add(model); } - Widget _buildLeft(WidgetModel model, BuildContext context) => Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(top: 20.0, left: 20), - child: Text( - model.nameCN, - style: TextStyle( - fontSize: 20, - decoration: (model.deprecated) - ? TextDecoration.lineThrough - : TextDecoration.none, - decorationThickness: 2, - color: const Color(0xff1EBBFD), - fontWeight: FontWeight.bold), - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Panel( - color: Theme.of(context).appBarTheme.backgroundColor, - child: Text(model.info)), - ) - ], - ), - ); - - Widget _buildRight(WidgetModel model) => Column( - mainAxisSize: MainAxisSize.min, - children: [ - SizedBox( - height: 100, - child: Padding( - padding: const EdgeInsets.all(8.0), - child: Hero( - tag: "hero_widget_image_${model.id}", - child: ClipRRect( - borderRadius: const BorderRadius.all(Radius.circular(8)), - child: model.image == null - ? Image.asset('assets/images/caver.webp') - : Image(image: model.image!))), - ), - ), - StarScore( - score: model.lever, - star: const Star(size: 15, fillColor: Colors.blue), - ) - ], - ); + Widget _buildSliverNodeList(List nodes, String name) { + GlobalState globalState = BlocProvider.of(context).state; + HighlighterStyle codeStyle = + Cons.codeThemeSupport.keys.toList()[globalState.codeStyleIndex]; + return SliverList( + delegate: SliverChildBuilderDelegate( + (_, i) => WidgetNodePanel( + codeStyle: codeStyle, + codeFamily: 'Inconsolata', + text: nodes[i].name, + subText: nodes[i].subtitle, + code: nodes[i].code, + show: WidgetsMap.map(name)[i], + ), + childCount: nodes.length, + )); + } } + diff --git a/lib/widget_system/views/widget_detail_view/widget_detail_panel.dart b/lib/widget_system/views/widget_detail_view/widget_detail_panel.dart new file mode 100644 index 0000000..ae51f2a --- /dev/null +++ b/lib/widget_system/views/widget_detail_view/widget_detail_panel.dart @@ -0,0 +1,77 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_star/flutter_star.dart'; +import 'package:flutter_unit/components/permanent/panel.dart'; +import 'package:flutter_unit/widget_system/repositories/model/widget_model.dart'; + +class WidgetDetailPanel extends StatelessWidget { + final WidgetModel model; + + const WidgetDetailPanel({Key? key, required this.model}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + _buildLeft(model, context), + _buildRight(model), + ], + ), + const Divider(), + ], + ); + } + + Widget _buildLeft(WidgetModel model, BuildContext context) => Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 20.0, left: 20), + child: Text( + model.nameCN, + style: TextStyle( + fontSize: 20, + decoration: (model.deprecated) + ? TextDecoration.lineThrough + : TextDecoration.none, + decorationThickness: 2, + color: const Color(0xff1EBBFD), + fontWeight: FontWeight.bold), + ), + ), + Padding( + padding: const EdgeInsets.all(8.0), + child: Panel( + color: Theme.of(context).appBarTheme.backgroundColor, + child: Text(model.info)), + ) + ], + ), + ); + + Widget _buildRight(WidgetModel model) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: 100, + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Hero( + tag: "hero_widget_image_${model.id}", + child: ClipRRect( + borderRadius: const BorderRadius.all(Radius.circular(8)), + child: model.image == null + ? Image.asset('assets/images/caver.webp') + : Image(image: model.image!))), + ), + ), + StarScore( + score: model.lever, + star: const Star(size: 15, fillColor: Colors.blue), + ) + ], + ); +}