buildFocusingPoint method

Widget buildFocusingPoint({
  1. required CameraValue cameraValue,
  2. required BoxConstraints constraints,
  3. int quarterTurns = 0,
})

The area widget for the last exposure point that user manually set. 用户手动设置的曝光点的区域显示

Implementation

Widget buildFocusingPoint({
  required CameraValue cameraValue,
  required BoxConstraints constraints,
  int quarterTurns = 0,
}) {
  Widget buildControls(double size, double height) {
    const double verticalGap = 3;
    final ExposureMode exposureMode = cameraValue.exposureMode;
    final bool isLocked = exposureMode == ExposureMode.locked;
    return Column(
      children: <Widget>[
        ValueListenableBuilder<bool>(
          valueListenable: isFocusPointDisplays,
          builder: (_, bool value, Widget? child) => AnimatedOpacity(
            duration: _kDuration,
            opacity: value ? 1 : 0,
            child: child,
          ),
          child: GestureDetector(
            onTap: switchExposureMode,
            child: SizedBox.fromSize(
              size: Size.square(size),
              child: Icon(
                isLocked ? Icons.lock_rounded : Icons.lock_open_rounded,
                size: size,
                color: isLocked ? _lockedColor : null,
              ),
            ),
          ),
        ),
        const SizedBox(height: verticalGap),
        Expanded(
          child: buildExposureSlider(
            mode: exposureMode,
            size: size,
            height: height,
            gap: verticalGap,
          ),
        ),
        const SizedBox(height: verticalGap),
        SizedBox.fromSize(size: Size.square(size)),
      ],
    );
  }

  Widget buildFromPoint(Offset point) {
    const double controllerWidth = 20;
    final double pointWidth =
        math.min(constraints.maxWidth, constraints.maxHeight) / 5;
    final double lineHeight = pointWidth * 2.5;
    final double exposureControlWidth =
        pickerConfig.enableExposureControlOnPoint ? controllerWidth : 0;
    final double width = pointWidth + exposureControlWidth + 2;
    final bool shouldReverseLayout = cameraQuarterTurns.isEven &&
        enableScaledPreview &&
        point.dx > constraints.maxWidth / 4 * 3;
    final double effectiveLeft, effectiveTop, effectiveWidth, effectiveHeight;
    if (cameraQuarterTurns.isOdd && !enableScaledPreview) {
      effectiveLeft = math.min(
        constraints.maxWidth - lineHeight,
        math.max(0, point.dx - lineHeight / 2),
      );
      effectiveTop = math.min(
        constraints.maxHeight - width,
        math.max(0, point.dy - width / 2),
      );
      effectiveWidth = lineHeight;
      effectiveHeight = width;
    } else {
      effectiveLeft = math.min(
        constraints.maxWidth - width,
        math.max(0, point.dx - width / 2),
      );
      effectiveTop = math.min(
        constraints.maxHeight - lineHeight,
        math.max(0, point.dy - lineHeight / 2),
      );
      effectiveWidth = width;
      effectiveHeight = lineHeight;
    }
    return Positioned(
      left: effectiveLeft,
      top: effectiveTop,
      width: effectiveWidth,
      height: effectiveHeight,
      child: ExcludeSemantics(
        child: ValueListenableBuilder<bool>(
          valueListenable: isFocusPointFadeOut,
          builder: (BuildContext context, bool isFadeOut, Widget? child) {
            Widget body = AnimatedOpacity(
              curve: Curves.ease,
              duration: _kDuration,
              opacity: isFadeOut ? .5 : 1,
              child: Row(
                textDirection: shouldReverseLayout
                    ? TextDirection.rtl
                    : TextDirection.ltr,
                children: <Widget>[
                  child!,
                  if (pickerConfig.enableExposureControlOnPoint)
                    const SizedBox(width: 2),
                  if (pickerConfig.enableExposureControlOnPoint)
                    SizedBox.fromSize(
                      size: Size(exposureControlWidth, lineHeight),
                      child: buildControls(controllerWidth, lineHeight),
                    ),
                ],
              ),
            );
            if (quarterTurns != 0) {
              body = RotatedBox(quarterTurns: quarterTurns, child: body);
            }
            return body;
          },
          child: CameraFocusPoint(
            key: ValueKey<Offset>(point),
            size: pointWidth,
            color: cameraValue.exposureMode == ExposureMode.locked
                ? _lockedColor
                : theme.iconTheme.color!,
          ),
        ),
      ),
    );
  }

  return ValueListenableBuilder<Offset?>(
    valueListenable: lastExposurePoint,
    builder: (_, Offset? point, __) {
      if (point == null) {
        return const SizedBox.shrink();
      }
      return buildFromPoint(point);
    },
  );
}