有没有办法在 FittedBox 中获取图像的真实大小/位置?
Is there a way to get the real size / position of Image in a FittedBox?
我有一个简单的布局,其中包含一个封装在 FittedBox 中的图像小部件。我想获取它的大小和位置,所以我在 Image 小部件上放了一个键并从 initState 中获取它:
final GlobalKey imgKey = GlobalKey();
@override
void initState() {
SchedulerBinding.instance?.addPostFrameCallback((timeStamp) async {
await ModalRoute.of(context)?.didPush(); //wait opening transition
final keyPosContext = imgKey.currentContext;
if (keyPosContext != null){
final renderPlan = keyPosContext.findRenderObject() as RenderBox;
final pos = renderPlan.localToGlobal(Offset.zero);
if(pos != planOffset || renderPlan.size != planSize) {
setState(() {
planOffset = pos;
planSize = renderPlan.size;
});
}
}
});
super.initState();
}
布局:
Widget build(BuildContext context){
return Stack(
children: [
Positioned(
top: 0, left: 100, right: 100, height: 30,
child: Align(alignment: Alignment.center,
child: Text('$title'),
),
),
Positioned(
top: 30, left: 0, right: 0, bottom: 0,
child: DragTarget<DraggableData>(
onMove: onMove,
onAccept: onAccept,
builder: (BuildContext context, List candidateData, List rejectedData) {
File img = File(myPlan);
if (img.existsSync()) {
return FittedBox(
fit: BoxFit.contain,
child: Image.file(img, key: imgKey),
);
} else
return Container();
}
),
),
Positioned(//TEST
top: planOffset.dy,
left: planOffset.dx,
height: planSize.height,
width: planSize.width,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 2),
),
),
),
]
);
}
最后一个 Positioned 只是一个用来测试值的绿色矩形。我采取了正确的位置,但尺寸不对:我采用原始图像尺寸(在我的情况下为 400*300),而不管合适的尺寸...
您可以使用此小部件在 运行 时获取尺寸。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
typedef void OnWidgetSizeChange(Size size);
class MeasureSize extends SingleChildRenderObjectWidget {
final OnWidgetSizeChange onChange;
const MeasureSize({Key? key, required this.onChange, required Widget child}) : super(key: key, child: child);
@override
RenderObject createRenderObject(BuildContext context) => _MeasureSizeRenderObject(onChange);
}
class _MeasureSizeRenderObject extends RenderProxyBox {
Size? oldSize;
final OnWidgetSizeChange onChange;
_MeasureSizeRenderObject(this.onChange);
@override
void performLayout() {
super.performLayout();
Size newSize = child!.size;
// if (oldSize == newSize) return;
oldSize = newSize;
WidgetsBinding.instance!.addPostFrameCallback((_) => onChange(newSize));
}
}
获取尺寸
...
Positioned(
top: 30, left: 0, right: 0, bottom: 0,
child: DragTarget<DraggableData>(
onMove: onMove,
onAccept: onAccept,
builder: (BuildContext context, List candidateData, List rejectedData) {
File img = File(myPlan);
if (img.existsSync()) {
return FittedBox(
fit: BoxFit.contain,
child: MeasureSize(
child: Image.file(img, key: imgKey),
onChange: (Size newSize) {
setState(() {
planSize = newSize;
});
},
),
);
} else
return Container();
}
),
),
...
感谢@Dennis Mwea 抽出时间提供解决方案,我只是为了我的目的添加了小部件偏移量,但它非常完美。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
typedef void OnWidgetSizeChange(Size size, Offset pos);
class MeasuredWidget extends SingleChildRenderObjectWidget {
final OnWidgetSizeChange onChange;
const MeasuredWidget({Key? key, required this.onChange, required Widget child}) : super(key: key, child: child);
@override
RenderObject createRenderObject(BuildContext context) => _MeasureWidgetRenderObject(onChange);
}
class _MeasureWidgetRenderObject extends RenderProxyBox {
Size? oldSize;
Offset? oldPos;
final OnWidgetSizeChange onChange;
_MeasureWidgetRenderObject(this.onChange);
@override
void performLayout() {
super.performLayout();
WidgetsBinding.instance!.addPostFrameCallback((_){
Size newSize = child!.size;
Offset newPos = child!.localToGlobal(Offset.zero);
if (oldSize == newSize && oldPos == newPos) return;
oldSize = newSize;
oldPos = newPos;
onChange(newSize, newPos));
}
}
我有一个简单的布局,其中包含一个封装在 FittedBox 中的图像小部件。我想获取它的大小和位置,所以我在 Image 小部件上放了一个键并从 initState 中获取它:
final GlobalKey imgKey = GlobalKey();
@override
void initState() {
SchedulerBinding.instance?.addPostFrameCallback((timeStamp) async {
await ModalRoute.of(context)?.didPush(); //wait opening transition
final keyPosContext = imgKey.currentContext;
if (keyPosContext != null){
final renderPlan = keyPosContext.findRenderObject() as RenderBox;
final pos = renderPlan.localToGlobal(Offset.zero);
if(pos != planOffset || renderPlan.size != planSize) {
setState(() {
planOffset = pos;
planSize = renderPlan.size;
});
}
}
});
super.initState();
}
布局:
Widget build(BuildContext context){
return Stack(
children: [
Positioned(
top: 0, left: 100, right: 100, height: 30,
child: Align(alignment: Alignment.center,
child: Text('$title'),
),
),
Positioned(
top: 30, left: 0, right: 0, bottom: 0,
child: DragTarget<DraggableData>(
onMove: onMove,
onAccept: onAccept,
builder: (BuildContext context, List candidateData, List rejectedData) {
File img = File(myPlan);
if (img.existsSync()) {
return FittedBox(
fit: BoxFit.contain,
child: Image.file(img, key: imgKey),
);
} else
return Container();
}
),
),
Positioned(//TEST
top: planOffset.dy,
left: planOffset.dx,
height: planSize.height,
width: planSize.width,
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.green, width: 2),
),
),
),
]
);
}
最后一个 Positioned 只是一个用来测试值的绿色矩形。我采取了正确的位置,但尺寸不对:我采用原始图像尺寸(在我的情况下为 400*300),而不管合适的尺寸...
您可以使用此小部件在 运行 时获取尺寸。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
typedef void OnWidgetSizeChange(Size size);
class MeasureSize extends SingleChildRenderObjectWidget {
final OnWidgetSizeChange onChange;
const MeasureSize({Key? key, required this.onChange, required Widget child}) : super(key: key, child: child);
@override
RenderObject createRenderObject(BuildContext context) => _MeasureSizeRenderObject(onChange);
}
class _MeasureSizeRenderObject extends RenderProxyBox {
Size? oldSize;
final OnWidgetSizeChange onChange;
_MeasureSizeRenderObject(this.onChange);
@override
void performLayout() {
super.performLayout();
Size newSize = child!.size;
// if (oldSize == newSize) return;
oldSize = newSize;
WidgetsBinding.instance!.addPostFrameCallback((_) => onChange(newSize));
}
}
获取尺寸
...
Positioned(
top: 30, left: 0, right: 0, bottom: 0,
child: DragTarget<DraggableData>(
onMove: onMove,
onAccept: onAccept,
builder: (BuildContext context, List candidateData, List rejectedData) {
File img = File(myPlan);
if (img.existsSync()) {
return FittedBox(
fit: BoxFit.contain,
child: MeasureSize(
child: Image.file(img, key: imgKey),
onChange: (Size newSize) {
setState(() {
planSize = newSize;
});
},
),
);
} else
return Container();
}
),
),
...
感谢@Dennis Mwea 抽出时间提供解决方案,我只是为了我的目的添加了小部件偏移量,但它非常完美。
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
typedef void OnWidgetSizeChange(Size size, Offset pos);
class MeasuredWidget extends SingleChildRenderObjectWidget {
final OnWidgetSizeChange onChange;
const MeasuredWidget({Key? key, required this.onChange, required Widget child}) : super(key: key, child: child);
@override
RenderObject createRenderObject(BuildContext context) => _MeasureWidgetRenderObject(onChange);
}
class _MeasureWidgetRenderObject extends RenderProxyBox {
Size? oldSize;
Offset? oldPos;
final OnWidgetSizeChange onChange;
_MeasureWidgetRenderObject(this.onChange);
@override
void performLayout() {
super.performLayout();
WidgetsBinding.instance!.addPostFrameCallback((_){
Size newSize = child!.size;
Offset newPos = child!.localToGlobal(Offset.zero);
if (oldSize == newSize && oldPos == newPos) return;
oldSize = newSize;
oldPos = newPos;
onChange(newSize, newPos));
}
}