course_module_page.dart 6.54 KB
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:wow_english/common/extension/string_extension.dart';
import 'package:wow_english/common/widgets/we_app_bar.dart';
import 'package:wow_english/models/course_module_entity.dart';
import 'package:wow_english/route/route.dart';

import 'bloc/module_bloc.dart';
import 'widgets/module_item_widget.dart';

// 课程阶段(模块)列表页
class CourseModulePage extends StatelessWidget {
  const CourseModulePage({super.key, this.starPageIndex});

  final int? starPageIndex;

  @override
  Widget build(BuildContext context) {
    return BlocProvider(
      create: (context) => ModuleBloc(
        starPageIndex ?? 0,
        PageController(initialPage: starPageIndex ?? 0, viewportFraction: 0.3),
      )..add(RequestDataEvent()),
      child: _LessonPageView(),
    );
  }
}

class _LessonPageView extends StatelessWidget {
  final double _cardHeight = 240.h;

  final double _scale = 0.8;

  @override
  Widget build(BuildContext context) {
    return BlocListener<ModuleBloc, ModuleState>(
      listener: (context, state) {},
      child: Scaffold(
        appBar: const WEAppBar(),
        body: _lessViewWidget(),
      ),
    );
  }

  Widget _lessViewWidget() =>
      BlocBuilder<ModuleBloc, ModuleState>(builder: (context, state) {
        final bloc = BlocProvider.of<ModuleBloc>(context);
        return Center(
          child: SafeArea(
            child: Column(
              children: [
                SizedBox(
                  height: _cardHeight,
                  child: PageView.builder(
                      itemCount: bloc.listData.length,
                      controller: bloc.pageController,
                      onPageChanged: (int index) {
                        bloc.add(PageViewChangeIndexEvent(index));
                      },
                      itemBuilder: (context, index) => _itemTransCard(index)),
                ),
                32.verticalSpace,
                SizedBox(
                  height: 32.h,
                  width: 66.w * bloc.listData.length,
                  child: ListView.builder(
                      itemCount: bloc.listData.length,
                      scrollDirection: Axis.horizontal,
                      itemBuilder: (BuildContext context, int index) {
                        return Container(
                          height: 32.h,
                          width: 66.w,
                          padding: const EdgeInsets.symmetric(horizontal: 5),
                          child: GestureDetector(
                            onTap: () {
                              if (index == bloc.currentPageIndex) {
                                return;
                              }
                              int mill = (index - bloc.currentPageIndex) > 0
                                  ? 100 * (index - bloc.currentPageIndex)
                                  : 100 * (bloc.currentPageIndex - index);
                              bloc.pageController.animateToPage(index,
                                  duration: Duration(milliseconds: mill),
                                  curve: Curves.ease);
                            },
                            child: Container(
                              height: bloc.currentPageIndex == index ? 32 : 20,
                              decoration: BoxDecoration(
                                color: bloc.currentPageIndex == index
                                    ? Colors.red
                                    : Colors.white,
                                borderRadius: BorderRadius.circular(5.r),
                                border: Border.all(
                                  width: 0.5,
                                  color: Colors.black,
                                ),
                              ),
                              alignment: Alignment.center,
                              child: Text(
                                (index + 1).toString(),
                                style: TextStyle(
                                    color: bloc.currentPageIndex == index
                                        ? Colors.white
                                        : Colors.black),
                              ),
                            ),
                          ),
                        );
                      }),
                )
              ],
            ),
          ),
        );
      });

  Widget _itemTransCard(int index) =>
      BlocBuilder<ModuleBloc, ModuleState>(builder: (context, state) {
        final bloc = BlocProvider.of<ModuleBloc>(context);
        Matrix4 matrix4 = Matrix4.identity();
        if (index == bloc.currentPageIndex.floor()) {
          //当前的item
          double currScale =
              (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble();
          var currTrans = _cardHeight * (1 - currScale) / 2;

          matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0)
            ..setTranslationRaw(0.0, currTrans, 0.0);
        } else if (index == bloc.currentPageIndex.floor() + 1) {
          //右边的item
          var currScale =
              _scale + (bloc.currentPageIndex - index + 1) * (1 - _scale);
          var currTrans = _cardHeight * (1 - currScale) / 2;

          matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0)
            ..setTranslationRaw(0.0, currTrans, 0.0);
        } else if (index == bloc.currentPageIndex - 1) {
          //左边
          var currScale =
              (1 - (bloc.currentPageIndex - index) * (1 - _scale)).toDouble();
          var currTrans = _cardHeight * (1 - currScale) / 2;

          matrix4 = Matrix4.diagonal3Values(1.0, currScale, 1.0)
            ..setTranslationRaw(0.0, currTrans, 0.0);
        } else {
          //其他,不在屏幕显示的item
          matrix4 = Matrix4.diagonal3Values(1.0, _scale, 1.0)
            ..setTranslationRaw(0.0, _cardHeight * (1 - _scale) / 2, 0.0);
        }
        CourseModuleEntity? model = bloc.listData[index];
        return Transform(
          transform: matrix4,
          child: Padding(
            padding: const EdgeInsets.symmetric(horizontal: 10),
            child: ModuleItemWidget(
              model: model,
              isSelected: bloc.currentPageIndex == index,
              onClickEvent: () {
                pushNamedAndRemoveUntil(
                    AppRouteName.courseUnit, (route) => route.isFirst,
                    arguments: {'courseModuleEntity': model});
              },
            ),
          ),
        );
      });
}