name27 / flutter

0 stars 0 forks source link

TabBar, TabBarView, pageController #118

Open name27 opened 10 months ago

name27 commented 10 months ago

TabBar

import 'package:flutter/material.dart';
import 'package:sfac_design_flutter/sfac_design_flutter.dart';

import 'page_controller.dart';

class SFTabBar extends StatefulWidget {
  const SFTabBar(
      {super.key,
      required this.tabs,
      this.focusedColor,
      this.width,
      required this.height,
      this.backgroundColor,
      this.borderColor,
      this.borderBottom,
      this.borderWidth = 4.0,
      this.physics,
      this.textStyle,
      required this.pageController,
      this.duration,
      this.curve});
  // 탭 바 메뉴
  final List<Widget> tabs;

  //포커스될 때 색
  final Color? focusedColor;

  //가로 넓이
  final double? width;

  //높이
  final double height;

  // 탭 배경색
  final Color? backgroundColor;

  //탭 테두리색
  final Color? borderColor;

  // 바텀보더
  final BorderSide? borderBottom;

  //보더 테두리 두께
  final double borderWidth;

  // 스크롤 피지컬
  final ScrollPhysics? physics;

  // 메뉴 텍스트 스타일
  final TextStyle? textStyle;

  // 페이지 컨트롤러
  final SFPageController pageController;

  // 페이지 이동 시간
  final Duration? duration;

  // 페이지 이동 효과
  final Curve? curve;

  @override
  State<SFTabBar> createState() => _TabState();
}

class _TabState extends State<SFTabBar> {
  int _index = 0;
  List<bool> isHover = [];

  @override
  void initState() {
    super.initState();
    isHover = List.generate(widget.tabs.length, (index) => false);
    _index = widget.pageController.initialPage;
    widget.pageController.addListener(_tabListener);
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SizedBox(
          width: widget.width,
          height: widget.height,
          child: ListView.builder(
            physics: widget.physics ?? const NeverScrollableScrollPhysics(),
            scrollDirection: Axis.horizontal,
            itemCount: widget.tabs.length,
            itemBuilder: (context, index) {
              Widget? tabsText;
              TextStyle? tabsStyle;
              tabsStyle = widget.textStyle ??
                  SFTextStyle.b3M16(
                    color: _index == index
                        ? widget.focusedColor ?? SFColor.primary100
                        : Colors.black,
                  );
              tabsText = AnimatedDefaultTextStyle(
                style: tabsStyle,
                duration: kThemeChangeDuration,
                child: widget.tabs[index],
              );
              return InkWell(
                splashColor: Colors.transparent,
                highlightColor: Colors.transparent,
                onTap: () {
                  widget.pageController.animateToPage(
                    index,
                    duration:
                        widget.duration ?? const Duration(milliseconds: 300),
                    curve: widget.curve ?? Curves.ease,
                  );
                },
                hoverColor: Colors.transparent,
                onHover: (value) {
                  setState(() {
                    isHover[index] = value;
                  });
                },
                child: Container(
                  width: widget.width != null
                      ? widget.width! / widget.tabs.length
                      : MediaQuery.of(context).size.width / widget.tabs.length,
                  decoration: BoxDecoration(
                    color: widget.backgroundColor,
                    border: Border(
                      bottom: isHover[index]
                          ? widget.borderBottom ??
                              BorderSide(
                                color: widget.borderColor ?? SFColor.primary100,
                                width: widget.borderWidth,
                              )
                          : _index == index
                              ? widget.borderBottom ??
                                  BorderSide(
                                    color: widget.borderColor ??
                                        SFColor.primary100,
                                    width: widget.borderWidth,
                                  )
                              : BorderSide.none,
                    ),
                  ),
                  child: Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        isHover[index]
                            ? SizedBox(
                                height: widget.borderBottom != null ||
                                        widget.borderBottom != BorderSide.none
                                    ? widget.borderWidth
                                    : null,
                              )
                            : _index != index
                                ? const SizedBox()
                                : SizedBox(
                                    height: widget.borderBottom != null ||
                                            widget.borderBottom !=
                                                BorderSide.none
                                        ? widget.borderWidth
                                        : null,
                                  ),
                        tabsText,
                      ],
                    ),
                  ),
                ),
              );
            },
          ),
        ),
      ],
    );
  }

  void _tabListener() {
    if (_index != widget.pageController.page!.round()) {
      setState(() {
        _index = widget.pageController.page!.round();
      });
    }
  }

  @override
  void dispose() {
    widget.pageController.removeListener(_tabListener);
    super.dispose();
  }
}

TabBarVIew

import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

import 'page_controller.dart';

class SFTabBarView extends StatelessWidget {
  const SFTabBarView({
    super.key,
    required this.tabController,
    required this.views,
    this.physics,
    this.dragStartBehavior,
    this.onPageChanged,
    // required this.height,
  });

  // 페이지 컨트롤러
  final SFPageController tabController;

  // PageView body 리스트
  final List<Widget> views;

  // PageView ScrollPhysics
  final ScrollPhysics? physics;

  // PageView DragStartBehavior
  final DragStartBehavior? dragStartBehavior;

  // PageView onPageChanged
  final Function(int)? onPageChanged;

  //final double height;

  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: PageView(
        onPageChanged: onPageChanged,
        dragStartBehavior: dragStartBehavior ?? DragStartBehavior.start,
        controller: tabController,
        physics: physics ?? const ClampingScrollPhysics(),
        children: views,
      ),
    );
  }
}

pageController

import 'package:flutter/material.dart';

class SFPageController extends PageController {
  SFPageController({
    required this.length,
    int initialPage = 0,
    bool keepPage = true,
    double viewportFraction = 1.0,
  }) : super(
          initialPage: initialPage,
          keepPage: keepPage,
          viewportFraction: viewportFraction,
        );

  final int length;
}