#dart #flutter #overlay
#dart #флаттер #наложение
Вопрос:
Я пишу приложение flutter и пытаюсь создать учебное наложение, которое будет полностью отображать только те компоненты, с которыми я хочу, чтобы пользователь мог взаимодействовать.
итак, я расширил класс CustomPainter, получив контекст страницы (чтобы получить его размеры) и список GlobalKeys (для элементов, которые я хочу отображать и взаимодействовать с ними)
Color colorBlack = Colors.black.withOpacity(0.4);
class CurvePainter extends CustomPainter{
BuildContext context;
List<GlobalKey> globalKeys;
double padding;
@override
void paint(Canvas canvas, Size size) {
final double screenWidth = MediaQuery.of(context).size.width;
final double screenHeight = MediaQuery.of(context).size.height;
Path path = Path()..addRect(Rect.fromLTWH(0, 0, screenWidth, screenHeight));
Set<GlobalKey> keysSet = Set.from(globalKeys);
keysSet.forEach((element){
final List<double> vals = global_key_util.getArea(element);
path = Path.combine(PathOperation.difference,
path,
Path()
..addOval(Rect.fromLTWH(vals[0]-(padding/2),vals[1]-padding/2,vals[2] padding,vals[3] padding)));
});
canvas.drawPath(path,
Paint()..color = colorBlack);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return oldDelegate != this;
}
CurvePainter({this.context,this.globalKeys,this.padding=4});
}
пока все хорошо … кнопка, с которой я хочу взаимодействовать с пользователем, полностью видна, на initState()
моей странице я создаю наложение и показываю его.
проблема в том, что я не могу взаимодействовать с этой кнопкой! как я могу это решить?
Спасибо
Комментарии:
1. Оберните свой
widget
с помощьюgestureDetector
и используйтеonTap
для выполнения желаемого действия.2. @KeertiPurswani — иногда я хочу, чтобы элемент ввода был видимым .. поэтому ontap с этим не поможет
3. Не могли бы вы объяснить «видимый элемент ввода». Какой код вы пробовали?
4. @KeertiPurswani — Я хочу иметь возможность наложения на весь мой экран и при этом иметь возможность взаимодействовать с некоторыми виджетами за ним. в настоящее время я использую clipPath, чтобы виджеты за ним были полностью видны и могли взаимодействовать с ними. вопрос в том .. можно ли это сделать без clipPath, чтобы мое наложение все еще было видно в этих областях
Ответ №1:
итак .. ответ просто не использовать CustomPainter, использовать ClipPath
с CustomClipper
.
в моем случае я хотел определить, когда пользователь нажимает на переполнение, но также позволить ему взаимодействовать с видимыми виджетами за ним.
итак, я создал InvertedClipper
класс, который расширяет CustomClipper
:
import 'package:flutter/material.dart';
import 'package:collection/collection.dart';
import 'HoleArea.dart';
import 'WidgetData.dart';
class InvertedClipper extends CustomClipper<Path> {
final Animation<double> animation;
final List<WidgetData> widgetsData;
double padding;
Function deepEq = const DeepCollectionEquality().equals;
List<HoleArea> areas = [];
InvertedClipper({@required this.padding, this.animation, Listenable reclip,
this.widgetsData}) : super(reclip: reclip) {
if (widgetsData.isNotEmpty) {
widgetsData.forEach((WidgetData widgetData) {
if (widgetData.isEnabled) {
final GlobalKey key = widgetData.key;
if (key == null) {
// throw new Exception("GlobalKey is null!");
} else if (key.currentWidget == null) {
// throw new Exception("GlobalKey is not assigned to a Widget!");
} else {
areas.add(getHoleArea(key: key,shape: widgetData.shape,padding: widgetData.padding));
}
}
});
}
}
@override
Path getClip(Size size) {
Path path = Path();
double animationValue = animation != null ? animation.value : 0;
areas.forEach((HoleArea area) {
switch (area.shape) {
case WidgetShape.Oval: {
path.addOval(Rect.fromLTWH(area.x - (((area.padding padding) animationValue*15) / 2), area.y - ((area.padding padding) animationValue*15) / 2,
area.width ((area.padding padding) animationValue*15), area.height ((area.padding padding) animationValue*15)));
}
break;
case WidgetShape.Rect: {
path.addRect(Rect.fromLTWH(area.x - (((area.padding padding) animationValue*15) / 2), area.y - ((area.padding padding) animationValue*15) / 2,
area.width ((area.padding padding) animationValue*15), area.height ((area.padding padding) animationValue*15)));
}
break;
case WidgetShape.RRect: {
path.addRRect(RRect.fromRectAndCorners(Rect.fromLTWH(area.x - (((area.padding padding) animationValue*15) / 2), area.y - ((area.padding padding) animationValue*15) / 2,
area.width ((area.padding padding) animationValue*15), area.height ((area.padding padding) animationValue*15)),
topLeft: Radius.circular(5.0),
topRight: Radius.circular(5.0),
bottomLeft: Radius.circular(5.0),
bottomRight: Radius.circular(5.0)));
}
break;
}
});
return path
..addRect(Rect.fromLTWH(0.0, 0.0, size.width, size.height))
..fillType = PathFillType.evenOdd;
}
@override
bool shouldReclip(InvertedClipper oldClipper) {
return !deepEq(oldClipper.areas, areas);
}
}
и перед этим я настраиваю GestureDetector
, чтобы определять, когда пользователь нажимает на наложение:
return GestureDetector(
onTap: onTap,
child: ClipPath(
clipper: InvertedClipper(
padding: defaultPadding,
animation: animation,
reclip: animationController,
widgetsData: widgetsData),
...