tiktok_video.dart 3.91 KB
import 'package:flutter/material.dart';
import 'package:flutter_spinkit/flutter_spinkit.dart';
import 'package:Parlando/tiktok/style/style.dart';
import 'package:Parlando/tiktok/widgets/tiktok_video_gesture.dart';

import 'package:Parlando/extension/int_extension.dart';

///
/// TikTok风格的一个视频页组件,覆盖在video上,提供以下功能:
/// 播放按钮的遮罩
/// 单击事件
/// 点赞事件回调(每次)
/// 长宽比控制
/// 底部padding(用于适配有沉浸式底部状态栏时)
///
class TikTokVideoPage extends StatelessWidget {
  final Widget? video;
  final double aspectRatio;
  final String? tag;
  final double bottomPadding;

  final Widget? rightButtonColumn;
  final Widget? leftPoemArea;
  final Widget? topInfo;
  final Widget? userInfoWidget;

  final bool hidePauseIcon;

  final Function? onAddFavorite;
  final Function? onSingleTap;

  const TikTokVideoPage({
    Key? key,
    this.bottomPadding = 16,
    this.tag,
    this.rightButtonColumn,
    this.topInfo,
    this.userInfoWidget,
    this.onAddFavorite,
    this.onSingleTap,
    this.video,
    this.aspectRatio = 9 / 16.0,
    this.hidePauseIcon = false,
    this.leftPoemArea,
  }) : super(key: key);
  @override
  Widget build(BuildContext context) {
    // 右边的按钮列表
    Widget rightButtons = rightButtonColumn ?? Container();
    Widget leftPoem = leftPoemArea ?? Container();
    // 视频加载的动画 // TODO 不要删除,后续添加加载逻辑
    Widget videoLoading = VideoLoadingPlaceHolder(tag: tag!);
    // 视频播放页
    Widget videoContainer = Stack(
      children: <Widget>[
        Container(
          height: double.infinity,
          width: double.infinity,
          color: Colors.black,
          alignment: Alignment.center,
          child: AspectRatio(
            aspectRatio: aspectRatio,
            child: video,
          ),
        ),
        TikTokVideoGesture(
          onAddFavorite: onAddFavorite,
          onSingleTap: onSingleTap,
          child: Container(
            color: ColorPlate.clear,
            height: double.infinity,
            width: double.infinity,
          ),
        ),
        // videoLoading, // TODO 加载动画需要修补
        hidePauseIcon
            ? Container()
            : Container(
                height: double.infinity,
                width: double.infinity,
                alignment: Alignment.center,
                child: Icon(
                  Icons.play_circle_outline,
                  size: 120.px,
                  color: Colors.white.withOpacity(0.4),
                ),
              ),
      ],
    );
    Widget body = Stack(
      children: <Widget>[
        videoContainer,
        Container(
          height: double.infinity,
          width: double.infinity,
          alignment: Alignment.topCenter,
          child: topInfo,
        ),
        Container(
          height: double.infinity,
          width: double.infinity,
          alignment: Alignment.bottomCenter,
          child: leftPoem,
        ),
        Container(
          height: double.infinity,
          width: double.infinity,
          alignment: Alignment.bottomRight,
          child: rightButtons,
        ),
      ],
    );
    return body;
  }
}

class VideoLoadingPlaceHolder extends StatelessWidget {
  const VideoLoadingPlaceHolder({
    Key? key,
    required this.tag,
  }) : super(key: key);

  final String tag;

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 64.px,
      width: 64.px,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          SpinKitWave(
            size: 36,
            color: Colors.white.withOpacity(0.3),
          ),
          Container(
            padding: EdgeInsets.all(50.px),
            child: Text(
              tag,
              style: StandardTextStyle.normalWithOpacity,
            ),
          ),
        ],
      ),
    );
  }
}