想象一下,我有一段很长的文字:HELLO THIS IS MY LONG SENTENCE
。当我点击它时,我想要LONG
这个词涟漪(墨水溅)。
假设我有这段代码:
new RichText(
text: new TextSpan(
text: 'HELLO THIS IS MY ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
new TextSpan(text: 'LONG', style: new TextStyle(fontWeight: FontWeight.bold)),
new TextSpan(text: ' SENTENCE'),
],
),
)
谢谢!
答案 0 :(得分:5)
如果您希望使用通用解决方案将小部件放在部分文本上,see this gist。
您可以使用以下代码将纹波约束到文本的特定部分:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'dart:ui' show TextBox;
import 'dart:math';
void main() {
runApp(new MaterialApp(
home: new Material(
child: new Center(
child: new Demo(),
),
),
));
}
class Demo extends StatelessWidget {
final TextSelection textSelection =
const TextSelection(baseOffset: 17, extentOffset: 21);
final GlobalKey _textKey = new GlobalKey();
@override
Widget build(context) => new Stack(
children: <Widget>[
new RichText(
key: _textKey,
text: new TextSpan(
text: 'HELLO THIS IS MY ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
new TextSpan(
text: 'LONG',
style: new TextStyle(fontWeight: FontWeight.bold)),
new TextSpan(text: ' SENTENCE'),
],
),
),
new Positioned.fill(
child: new LayoutBuilder(
builder: (context, _) => new Stack(
children: <Widget>[
new Positioned.fromRect(
rect: _getSelectionRect(),
child: new InkWell(
onTap: () => {}, // needed to show the ripple
),
),
],
),
),
),
],
);
Rect _getSelectionRect() =>
(_textKey.currentContext.findRenderObject() as RenderParagraph)
.getBoxesForSelection(textSelection)
.fold(
null,
(Rect previous, TextBox textBox) => new Rect.fromLTRB(
min(previous?.left ?? textBox.left, textBox.left),
min(previous?.top ?? textBox.top, textBox.top),
max(previous?.right ?? textBox.right, textBox.right),
max(previous?.bottom ?? textBox.bottom, textBox.bottom),
),
) ??
Rect.zero;
}
答案 1 :(得分:3)
您可以通过调整ink_well.dart中的代码来实现此效果。
在此示例中,我将rectCallback
配置为展开到包含卡片,但您可以提供一个较小的矩形,其中的水龙头位于水龙头的中心周围。
import 'package:flutter/material.dart';
import 'package:flutter/gestures.dart';
import 'dart:collection';
void main() {
runApp(new MaterialApp(home: new DemoApp()));
}
class DemoText extends StatefulWidget {
@override
DemoTextState createState() => new DemoTextState();
}
class DemoTextState<T extends InkResponse> extends State<T>
with AutomaticKeepAliveClientMixin {
Set<InkSplash> _splashes;
InkSplash _currentSplash;
@override
bool get wantKeepAlive => (_splashes != null && _splashes.isNotEmpty);
void _handleTapDown(TapDownDetails details) {
final RenderBox referenceBox = context.findRenderObject();
InkSplash splash;
splash = new InkSplash(
controller: Material.of(context),
referenceBox: referenceBox,
containedInkWell: true,
rectCallback: () => referenceBox.paintBounds,
position: referenceBox.globalToLocal(details.globalPosition),
color: Theme.of(context).splashColor,
onRemoved: () {
if (_splashes != null) {
assert(_splashes.contains(splash));
_splashes.remove(splash);
if (_currentSplash == splash) _currentSplash = null;
updateKeepAlive();
} // else we're probably in deactivate()
});
_splashes ??= new HashSet<InkSplash>();
_splashes.add(splash);
_currentSplash = splash;
updateKeepAlive();
}
void _handleTap(BuildContext context) {
_currentSplash?.confirm();
_currentSplash = null;
Feedback.forTap(context);
}
void _handleTapCancel() {
_currentSplash?.cancel();
_currentSplash = null;
}
@override
void deactivate() {
if (_splashes != null) {
final Set<InkSplash> splashes = _splashes;
_splashes = null;
for (InkSplash splash in splashes) splash.dispose();
_currentSplash = null;
}
assert(_currentSplash == null);
super.deactivate();
}
Widget build(BuildContext context) {
return new Padding(
padding: new EdgeInsets.all(20.0),
child: new RichText(
text: new TextSpan(
text: 'HELLO THIS IS MY ',
style: DefaultTextStyle.of(context).style,
children: <TextSpan>[
new TextSpan(
recognizer: new TapGestureRecognizer()
..onTapCancel = _handleTapCancel
..onTapDown = _handleTapDown
..onTap = () => _handleTap(context),
text: 'LONG',
style: new TextStyle(fontWeight: FontWeight.bold),
),
new TextSpan(text: ' SENTENCE'),
],
),
),
);
}
}
class DemoApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Container(
height: 150.0,
width: 150.0,
child: new Card(
child: new DemoText(),
),
),
),
);
}
}