import 'package:chat/generated/i18n.dart'; import 'package:extended_text/extended_text.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; // Minimal padding from all edges of the selection toolbar to all edges of the // viewport. const double _kToolbarScreenPadding = 8.0; const double _kToolbarHeight = 44.0; /// /// create by zmtzawqlp on 2019/8/3 /// class MyExtendedMaterialTextSelectionControls extends ExtendedMaterialTextSelectionControls { TextSelectionDelegate delegate; @override Widget buildToolbar( BuildContext context, Rect globalEditableRegion, double textLineHeight, Offset position, List endpoints, TextSelectionDelegate delegate, ) { assert(debugCheckHasMediaQuery(context)); assert(debugCheckHasMaterialLocalizations(context)); this.delegate = delegate; // The toolbar should appear below the TextField // when there is not enough space above the TextField to show it. final TextSelectionPoint startTextSelectionPoint = endpoints[0]; final TextSelectionPoint endTextSelectionPoint = (endpoints.length > 1) ? endpoints[1] : null; final double x = (endTextSelectionPoint == null) ? startTextSelectionPoint.point.dx : (startTextSelectionPoint.point.dx + endTextSelectionPoint.point.dx) / 2.0; final double availableHeight = globalEditableRegion.top - MediaQuery.of(context).padding.top - _kToolbarScreenPadding; final double y = (availableHeight < _kToolbarHeight) ? startTextSelectionPoint.point.dy + globalEditableRegion.height + _kToolbarHeight + _kToolbarScreenPadding : startTextSelectionPoint.point.dy - textLineHeight * 2.0; final Offset preciseMidpoint = Offset(x, y); return ConstrainedBox( constraints: BoxConstraints.tight(globalEditableRegion.size), child: CustomSingleChildLayout( delegate: ExtendedMaterialTextSelectionToolbarLayout( MediaQuery.of(context).size, globalEditableRegion, preciseMidpoint, ), child: _TextSelectionToolbar( handleCut: canCut(delegate) ? () => handleCut(delegate) : null, handleCopy: canCopy(delegate) ? () => handleCopy(delegate) : null, handlePaste: canPaste(delegate) ? () => handlePaste(delegate) : null, handleSelectAll: canSelectAll(delegate) ? () => handleSelectAll(delegate) : null, // handleLike: () { // MessageMgr().emit('Delete Select Message', msg); // }, // handleRef: canSelectAll(delegate) // ? null // : () { // MessageMgr().emit('Reply Select Message', msg); // }, delegate: delegate, ), ), ); } test(){ handleSelectAll(delegate); } @override void goTest() { Future.delayed(Duration(milliseconds: 350),(){ handleSelectAll(delegate); }); } // @override // Widget buildHandle( // BuildContext context, TextSelectionHandleType type, double textHeight) { // final Widget handle = SizedBox( // width: _kHandleSize, // height: _kHandleSize, // child: Image.asset("assets/40.png"), // ); // // // [handle] is a circle, with a rectangle in the top left quadrant of that // // circle (an onion pointing to 10:30). We rotate [handle] to point // // straight up or up-right depending on the handle type. // switch (type) { // case TextSelectionHandleType.left: // points up-right // return Transform.rotate( // angle: math.pi / 4.0, // child: handle, // ); // case TextSelectionHandleType.right: // points up-left // return Transform.rotate( // angle: -math.pi / 4.0, // child: handle, // ); // case TextSelectionHandleType.collapsed: // points up // return handle; // } // assert(type != null); // return null; // } } /// Manages a copy/paste text selection toolbar. class _TextSelectionToolbar extends StatelessWidget { const _TextSelectionToolbar( {Key key, this.handleCopy, this.handleSelectAll, this.handleCut, this.handlePaste, // this.handleRef, // this.handleLike, this.delegate}) : super(key: key); final VoidCallback handleCut; final VoidCallback handleCopy; final VoidCallback handlePaste; final VoidCallback handleSelectAll; // final VoidCallback handleLike; // final VoidCallback handleRef; final TextSelectionDelegate delegate; @override Widget build(BuildContext context) { final List items = []; if (handleCopy != null) items.add(GestureDetector( onTap: handleCopy, child: Container( padding: EdgeInsets.fromLTRB(12, 9, 12, 9), child: Text( I18n.of(context).copy, textScaleFactor: 1.0, style: TextStyle(color: Colors.white, fontSize: 12), ), ), )); if (handleSelectAll != null) items.add(GestureDetector( onTap: handleSelectAll, child: Container( padding: EdgeInsets.fromLTRB(12, 9, 12, 9), child: Text( I18n.of(context).select_all, textScaleFactor: 1.0, style: TextStyle(color: Colors.white, fontSize: 12), ), ), )); // if (handleRef != null) { // items.add(GestureDetector( // onTap: () { // delegate.hideToolbar(); // handleRef(); // }, // child: Container( // padding: EdgeInsets.fromLTRB(12, 9, 12, 9), // child: Text( // '回复', // textScaleFactor: 1.0, // style: TextStyle(color: Colors.white, fontSize: 12), // ), // ), // )); //} // if (handleCut != null) // items.add(FlatButton( // child: Text(localizations.cutButtonLabel), onPressed: handleCut)); // if (handleCopy != null) // items.add(FlatButton( // child: Text(localizations.copyButtonLabel), onPressed: handleCopy)); // if (handlePaste != null) // items.add(FlatButton( // child: Text(localizations.pasteButtonLabel), // onPressed: handlePaste, // )); // if (handleSelectAll != null) // items.add(FlatButton( // child: Text(localizations.selectAllButtonLabel), // onPressed: handleSelectAll)); // if (handleLike != null) // items.add(GestureDetector( // onTap: handleLike, // child: Container( // padding: EdgeInsets.fromLTRB(12, 9, 12, 9), // child: Text( // I18n.of(context).delete, // textScaleFactor: 1.0, // style: TextStyle(color: Colors.white, fontSize: 12), // ), // ), // )); // If there is no option available, build an empty widget. if (items.isEmpty) { return Container(width: 0.0, height: 0.0); } return Material( elevation: 1.0, child: Container( child: Wrap(children: items), decoration: BoxDecoration( color: Colors.black, borderRadius: BorderRadius.all(Radius.circular(5.0))), ), ); } }