#flutter
#трепетание
Вопрос:
Я хочу, чтобы событие запускалось, когда виджет находится в определенном положении экрана. Предположим, например, что у нас есть Container
виджет, который все еще не виден. Он находится в определенном положении прокручиваемого Scaffold
объекта, высота тела которого достаточна для прокрутки. Мы начинаем прокручивать, и когда виджет становится видимым и, скажем, достигает середины экрана, это запускает событие. Другими словами, событие должно запускаться только в том случае, если виджет находится в определенном положении. Возможно, чего-то подобного можно было бы достичь с помощью a ScrollController
, но мне интересно, могут ли быть другие подходы к этому.
Комментарии:
1. Вы имеете в виду, что хотите запустить функцию, когда виджет виден в списке?
2. Я думаю, что да. Просто чтобы быть уверенным, что вы имеете в виду под «списком»?
3. Но не только видимый, но и «в определенной позиции на экране»
4. для определенного положения не уверен, но для видимости вы можете использовать виджет детектора видимости
5. Отлично. Это уже хорошая информация. Проверяю это.
Ответ №1:
Итак, я начал небольшое исследование и обнаружил, что то, чего я хотел, может быть достигнуто с помощью объектов RenderBox. Используя их, вы можете получить размер (типа Size
) или положение (типа Offset
). Как только они у вас появятся, вызвать событие будет очень легко. В этом случае я привел простой пример, в котором я печатаю инструкцию только в том случае, если положение контейнера превышает заданное смещение по оси y (скажем, определенный процент от высоты экрана, который вы можете получить с MediaQuery.of(context).size.height
помощью). Я установил свой лимит на 75% высоты экрана. Событие вызывается при нажатии кнопки FloatingActionButton
. Если вы хотите протестировать его, прокрутите немного, а затем нажмите кнопку. Прокрутите еще раз, проверьте его еще раз и так далее. Вы увидите, что событие срабатывает при превышении предела.
Я добился этого с помощью следующей статьи: https://medium.com/@diegoveloper/flutter-widget-size-and-position-b0a9ffed9407
Вот мой пример:
import 'package:flutter/material.dart';
class Example extends StatefulWidget {
@override
_ExampleState createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
GlobalKey _keyRed = GlobalKey();
GlobalKey _keyPurple = GlobalKey();
GlobalKey _keyGreen = GlobalKey();
Offset positionGreen;
_getSizes(){
RenderBox renderBoxRed = _keyRed.currentContext.findRenderObject();
Size sizeRed = renderBoxRed.size;
print("red size is: $sizeRed");
RenderBox renderBoxPurple = _keyRed.currentContext.findRenderObject();
Size sizePurple = renderBoxPurple.size;
print("purple size is: $sizePurple");
RenderBox renderBoxGreen = _keyGreen.currentContext.findRenderObject();
Size sizeGreen = renderBoxGreen.size;
print("green size is: $sizeGreen");
}
_getPositions(){
final RenderBox renderBoxRed = _keyRed.currentContext.findRenderObject();
final positionRed = renderBoxRed.localToGlobal(Offset.zero);
print("red position is: $positionRed");
final RenderBox renderBoxPurple = _keyPurple.currentContext.findRenderObject();
final positionPurple = renderBoxPurple.localToGlobal(Offset.zero);
print("purple position is: $positionPurple");
final RenderBox renderBoxGreen = _keyGreen.currentContext.findRenderObject();
positionGreen = renderBoxGreen.localToGlobal(Offset.zero);
print("green position is: $positionGreen");
}
@override
Widget build(BuildContext context) {
double limit = MediaQuery.of(context).size.height*.75;
return Scaffold(
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.orange,
onPressed: (){
_getSizes();
_getPositions();
print("npositionGreen in dy is ${positionGreen.dy} and limit is $limit");
if(positionGreen.dy > limit){
print("screen resizes");
} else {
print("screen doesn't resize");
}
},
),
body: SingleChildScrollView(
child: Column(
children: [
Container(
height: 400,
key: _keyRed,
color: Colors.red,
),
Container(
height: 600,
key: _keyPurple,
color: Colors.purple,
),
Container(
height: 800,
key: _keyGreen,
color: Colors.green,
),
],
),
),
);
}
}