Flutter: как сделать ListView прозрачным для событий указателя (но не его непрозрачного содержимого)?

У меня есть Scrollable (ListView или любой другой), и он содержит прозрачный виджет, скажем Container(height:200). Я могу видеть как виджет, так и прокручиваемый (другими словами, я вижу виджеты за прокручиваемым).

Как я могу щелкнуть прозрачный виджет и прокручиваемый виджет, чтобы добраться до виджетов за прокручиваемым?

ListView(
  children: [
    Container(height: 200), // Transparent.
    Container(color: Colors.red, height: 200),
    ],
);

Обратите внимание: я не могу обернуть прокручиваемый элемент IgnorePointer, потому что я все еще хочу щелкать непрозрачные виджеты в прокручиваемом элементе.


person MarcG    schedule 19.08.2019    source источник
comment
что вы имели в виду, говоря "содержит прозрачный виджет"? как дочерние элементы ниже прокручиваемых или сложенных ниже прокручиваемого родителя?   -  person ejabu    schedule 20.08.2019
comment
Я имею в виду Container(height: 200) выше.   -  person MarcG    schedule 20.08.2019
comment
что означает «что я достигаю виджетов за прокручиваемым»?   -  person ejabu    schedule 20.08.2019
comment
Не могли бы вы подробнее рассказать о том, какого визуального эффекта вы пытаетесь достичь? Я не думаю, что вы можете касаться прозрачного виджета, но вы можете изменить макет так, чтобы визуально он оставался прежним, а виджет, на который вы хотите нажать, на самом деле был сверху.   -  person Ovidiu    schedule 20.08.2019
comment
@Ovidiu Представьте, что у вас есть ListView в стеке, который покрывает весь экран. ListView находится наверху. Вы можете перетащить его за непрозрачные виджеты. И вы можете нажать на прозрачные.   -  person MarcG    schedule 20.08.2019


Ответы (1)


Единственное разумное решение, которое я могу придумать, - это иметь GestureDetector на прозрачном контейнере, который даст вам глобальное положение кранов:

GestureDetector(
  onTapUp: (TapUpDetails tapUpDetails) {
    print("onTapUp global: " + tapUpDetails.globalPosition.toString());
  },

А затем добавьте Key к виджету за списком и используйте его, чтобы получить глобальную позицию верхнего левого угла прямоугольника виджета, а также размер виджета, и используйте их для получения прямоугольника виджета:

RenderBox renderBox = _key.currentContext.findRenderObject();
Offset topLeftCorner = renderBox.localToGlobal(Offset.zero);
Size size = renderBox.size;
Rect rectangle = topLeftCorner & size;

Если фоновый виджет не перемещается, вы можете сделать это в initState в следующем кадре, используя WidgetsBinding.instance.addPostFrameCallback (объект рендеринга будет нулевым, если делать это синхронно в initState) и сохранить Rect - иначе вам придется пересчитывать его при каждом нажатии .

И, наконец, при каждом касании прозрачного контейнера вы можете вычислить, находится ли положение касания в границах фонового виджета, и вызвать соответствующий код:

// if tap is within boundaries of the background widget
if (rectangle.contains(tapUpDetails.globalPosition)) {
  // your code here
}
person Ovidiu    schedule 22.08.2019
comment
Спасибо за Ваш ответ. В конце концов, я изменил свои требования, и мне это больше не нужно, поэтому у меня не будет возможности проверить ваш ответ. Но я думаю, что это может сработать, поэтому я приму это. Если однажды мне это снова понадобится, я постараюсь реализовать это и вернусь сюда, чтобы сообщить вам. - person MarcG; 03.09.2019