mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-04-20 11:08:03 +08:00
2256
lib/common/widgets/flutter/selectable_text/selectable_region.dart
Normal file
2256
lib/common/widgets/flutter/selectable_text/selectable_region.dart
Normal file
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
||||
|
||||
import 'dart:ui' as ui show BoxHeightStyle, BoxWidthStyle;
|
||||
|
||||
import 'package:PiliPlus/common/widgets/flutter/text_intro/text_selection.dart';
|
||||
import 'package:PiliPlus/common/widgets/flutter/selectable_text/text_selection.dart';
|
||||
import 'package:flutter/cupertino.dart'
|
||||
hide TextSelectionGestureDetectorBuilder;
|
||||
import 'package:flutter/gestures.dart';
|
||||
147
lib/common/widgets/flutter/selectable_text/selection_area.dart
Normal file
147
lib/common/widgets/flutter/selectable_text/selection_area.dart
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'package:PiliPlus/common/widgets/flutter/selectable_text/selectable_region.dart';
|
||||
import 'package:flutter/cupertino.dart'
|
||||
hide
|
||||
SelectableRegion,
|
||||
SelectableRegionState,
|
||||
SelectableRegionContextMenuBuilder;
|
||||
import 'package:flutter/material.dart'
|
||||
hide
|
||||
SelectableRegion,
|
||||
SelectableRegionState,
|
||||
SelectableRegionContextMenuBuilder;
|
||||
import 'package:flutter/rendering.dart';
|
||||
|
||||
/// A widget that introduces an area for user selections with adaptive selection
|
||||
/// controls.
|
||||
///
|
||||
/// This widget creates a [SelectableRegion] with platform-adaptive selection
|
||||
/// controls.
|
||||
///
|
||||
/// Flutter widgets are not selectable by default. To enable selection for
|
||||
/// a specific screen, consider wrapping the body of the [Route] with a
|
||||
/// [SelectionArea].
|
||||
///
|
||||
/// The [SelectionArea] widget must have a [Localizations] ancestor that
|
||||
/// contains a [MaterialLocalizations] delegate; using the [MaterialApp] widget
|
||||
/// ensures that such an ancestor is present.
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This example shows how to make a screen selectable.
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/selection_area/selection_area.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [SelectableRegion], which provides an overview of the selection system.
|
||||
/// * [SelectableText], which enables selection on a single run of text.
|
||||
/// * [SelectionListener], which enables accessing the [SelectionDetails] of
|
||||
/// the selectable subtree it wraps.
|
||||
class SelectionArea extends StatefulWidget {
|
||||
/// Creates a [SelectionArea].
|
||||
///
|
||||
/// If [selectionControls] is null, a platform specific one is used.
|
||||
const SelectionArea({
|
||||
super.key,
|
||||
this.focusNode,
|
||||
this.selectionControls,
|
||||
this.contextMenuBuilder = _defaultContextMenuBuilder,
|
||||
this.magnifierConfiguration,
|
||||
this.onSelectionChanged,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
/// The configuration for the magnifier in the selection region.
|
||||
///
|
||||
/// By default, builds a [CupertinoTextMagnifier] on iOS and [TextMagnifier]
|
||||
/// on Android, and builds nothing on all other platforms. To suppress the
|
||||
/// magnifier, consider passing [TextMagnifierConfiguration.disabled].
|
||||
///
|
||||
/// {@macro flutter.widgets.magnifier.intro}
|
||||
final TextMagnifierConfiguration? magnifierConfiguration;
|
||||
|
||||
/// {@macro flutter.widgets.Focus.focusNode}
|
||||
final FocusNode? focusNode;
|
||||
|
||||
/// The delegate to build the selection handles and toolbar.
|
||||
///
|
||||
/// If it is null, the platform specific selection control is used.
|
||||
final TextSelectionControls? selectionControls;
|
||||
|
||||
/// {@macro flutter.widgets.EditableText.contextMenuBuilder}
|
||||
///
|
||||
/// If not provided, will build a default menu based on the ambient
|
||||
/// [ThemeData.platform].
|
||||
///
|
||||
/// {@tool dartpad}
|
||||
/// This example shows how to build a custom context menu for any selected
|
||||
/// content in a SelectionArea.
|
||||
///
|
||||
/// ** See code in examples/api/lib/material/context_menu/selectable_region_toolbar_builder.0.dart **
|
||||
/// {@end-tool}
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [AdaptiveTextSelectionToolbar], which is built by default.
|
||||
final SelectableRegionContextMenuBuilder? contextMenuBuilder;
|
||||
|
||||
/// Called when the selected content changes.
|
||||
final ValueChanged<SelectedContent?>? onSelectionChanged;
|
||||
|
||||
/// The child widget this selection area applies to.
|
||||
///
|
||||
/// {@macro flutter.widgets.ProxyWidget.child}
|
||||
final Widget child;
|
||||
|
||||
static Widget _defaultContextMenuBuilder(
|
||||
BuildContext context,
|
||||
SelectableRegionState selectableRegionState,
|
||||
) => AdaptiveTextSelectionToolbar.buttonItems(
|
||||
buttonItems: selectableRegionState.contextMenuButtonItems,
|
||||
anchors: selectableRegionState.contextMenuAnchors,
|
||||
);
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => SelectionAreaState();
|
||||
}
|
||||
|
||||
/// State for a [SelectionArea].
|
||||
class SelectionAreaState extends State<SelectionArea> {
|
||||
final GlobalKey<SelectableRegionState> _selectableRegionKey =
|
||||
GlobalKey<SelectableRegionState>();
|
||||
|
||||
/// The [State] of the [SelectableRegion] for which this [SelectionArea] wraps.
|
||||
SelectableRegionState get selectableRegion =>
|
||||
_selectableRegionKey.currentState!;
|
||||
|
||||
@protected
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(debugCheckHasMaterialLocalizations(context));
|
||||
final TextSelectionControls controls =
|
||||
widget.selectionControls ??
|
||||
switch (Theme.of(context).platform) {
|
||||
TargetPlatform.android ||
|
||||
TargetPlatform.fuchsia => materialTextSelectionHandleControls,
|
||||
TargetPlatform.linux ||
|
||||
TargetPlatform.windows => desktopTextSelectionHandleControls,
|
||||
TargetPlatform.iOS => cupertinoTextSelectionHandleControls,
|
||||
TargetPlatform.macOS => cupertinoDesktopTextSelectionHandleControls,
|
||||
};
|
||||
return SelectableRegion(
|
||||
key: _selectableRegionKey,
|
||||
selectionControls: controls,
|
||||
focusNode: widget.focusNode,
|
||||
contextMenuBuilder: widget.contextMenuBuilder,
|
||||
magnifierConfiguration:
|
||||
widget.magnifierConfiguration ??
|
||||
TextMagnifier.adaptiveMagnifierConfiguration,
|
||||
onSelectionChanged: widget.onSelectionChanged,
|
||||
child: widget.child,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1083,3 +1083,42 @@ class TapAndHorizontalDragGestureRecognizer
|
||||
@override
|
||||
String get debugDescription => 'tap and horizontal drag';
|
||||
}
|
||||
|
||||
/// {@template flutter.gestures.selectionrecognizers.TapAndPanGestureRecognizer}
|
||||
/// Recognizes taps along with both horizontal and vertical movement.
|
||||
///
|
||||
/// This recognizer will accept a drag on any axis, regardless if it has won the
|
||||
/// arena for the primary pointer being tracked.
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [BaseTapAndDragGestureRecognizer], for the class that provides the main
|
||||
/// implementation details of this recognizer.
|
||||
/// * [TapAndHorizontalDragGestureRecognizer], for a similar recognizer that
|
||||
/// only accepts horizontal drags before it has won the arena for the primary
|
||||
/// pointer being tracked.
|
||||
/// * [PanGestureRecognizer], for a similar recognizer that only recognizes
|
||||
/// movement.
|
||||
/// {@endtemplate}
|
||||
class TapAndPanGestureRecognizer extends BaseTapAndDragGestureRecognizer {
|
||||
/// Create a gesture recognizer for interactions on a plane.
|
||||
TapAndPanGestureRecognizer({super.debugOwner, super.supportedDevices});
|
||||
|
||||
@override
|
||||
bool _hasSufficientGlobalDistanceToAccept(
|
||||
PointerDeviceKind pointerDeviceKind,
|
||||
) {
|
||||
return true;
|
||||
// return _globalDistanceMoved.abs() >
|
||||
// computePanSlop(pointerDeviceKind, gestureSettings);
|
||||
}
|
||||
|
||||
// @override
|
||||
// Offset _getDeltaForDetails(Offset delta) => delta;
|
||||
|
||||
// @override
|
||||
// double? _getPrimaryValueFromOffset(Offset value) => null;
|
||||
|
||||
@override
|
||||
String get debugDescription => 'tap and pan';
|
||||
}
|
||||
42
lib/common/widgets/flutter/selectable_text/text.dart
Normal file
42
lib/common/widgets/flutter/selectable_text/text.dart
Normal file
@@ -0,0 +1,42 @@
|
||||
import 'package:PiliPlus/common/widgets/flutter/selectable_text/selectable_text.dart';
|
||||
import 'package:PiliPlus/common/widgets/flutter/selectable_text/selection_area.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:flutter/material.dart' hide SelectableText, SelectionArea;
|
||||
|
||||
Widget selectableText(
|
||||
String text, {
|
||||
TextStyle? style,
|
||||
}) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
return SelectionArea(
|
||||
child: Text(
|
||||
style: style,
|
||||
text,
|
||||
),
|
||||
);
|
||||
}
|
||||
return SelectableText(
|
||||
style: style,
|
||||
text,
|
||||
scrollPhysics: const NeverScrollableScrollPhysics(),
|
||||
);
|
||||
}
|
||||
|
||||
Widget selectableRichText(
|
||||
TextSpan textSpan, {
|
||||
TextStyle? style,
|
||||
}) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
return SelectionArea(
|
||||
child: Text.rich(
|
||||
style: style,
|
||||
textSpan,
|
||||
),
|
||||
);
|
||||
}
|
||||
return SelectableText.rich(
|
||||
style: style,
|
||||
textSpan,
|
||||
scrollPhysics: const NeverScrollableScrollPhysics(),
|
||||
);
|
||||
}
|
||||
@@ -4,10 +4,13 @@
|
||||
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:PiliPlus/common/widgets/flutter/text_intro/tap_and_drag.dart';
|
||||
import 'package:PiliPlus/common/widgets/flutter/selectable_text/tap_and_drag.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart'
|
||||
hide BaseTapAndDragGestureRecognizer, TapAndHorizontalDragGestureRecognizer;
|
||||
hide
|
||||
BaseTapAndDragGestureRecognizer,
|
||||
TapAndHorizontalDragGestureRecognizer,
|
||||
TapAndPanGestureRecognizer;
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomTextSelectionGestureDetectorBuilder
|
||||
@@ -1,22 +0,0 @@
|
||||
import 'package:PiliPlus/common/widgets/flutter/text_intro/selectable_text.dart';
|
||||
import 'package:PiliPlus/utils/platform_utils.dart';
|
||||
import 'package:flutter/material.dart' hide SelectableText;
|
||||
|
||||
Widget selectableRichText(
|
||||
TextSpan textSpan, {
|
||||
TextStyle? style,
|
||||
}) {
|
||||
if (PlatformUtils.isDesktop) {
|
||||
return SelectionArea(
|
||||
child: Text.rich(
|
||||
style: style,
|
||||
textSpan,
|
||||
),
|
||||
);
|
||||
}
|
||||
return SelectableText.rich(
|
||||
style: style,
|
||||
textSpan,
|
||||
scrollPhysics: const NeverScrollableScrollPhysics(),
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user