如何知道用户是否看到了抖动的图像

时间:2019-03-26 13:17:37

标签: dart flutter

可滚动屏幕中有一个Image组件。打开屏幕时,开始时看不到图像,但是您需要向下滚动才能查看图像。

当用户滚动到图像后,如何确定其完全可见?我想计算用户的印象。

如何在颤抖中实现这一目标?

3 个答案:

答案 0 :(得分:6)

我没有关于您的代码的太多信息,所以这就是我解决的方法。仅当图像在屏幕上完全可见时才计算印象,您可以使用_count =表达式来更改印象。我为Container使用了简单的Image

首先查看此屏幕截图。

enter image description here


代码

void main() => runApp(MaterialApp(home: HomePage()),);

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  ScrollController _scrollController;
  double _heightListTile = 56, _heightContainer = 200, _oldOffset = 0, _heightBox, _initialAdd;
  int _initialCount, _count, _previousCount = 0, _itemsInList = 4;

  @override
  void initState() {
    super.initState();
    _heightBox = ((_itemsInList) * _heightListTile) + _heightContainer;
    _scrollController = ScrollController();
    _scrollController.addListener(() {
      double offset = _scrollController.offset;
      if (offset >= _oldOffset) {
        _oldOffset = offset;
        _count = _initialCount + (offset + _initialAdd) ~/ _heightBox;
        if (_count != _previousCount) setState(() {});
        _previousCount = _count;
      }
    });

    Timer.run(() {
      bool isIos = Theme.of(context).platform == TargetPlatform.iOS;
      var screenHeight = MediaQuery.of(context).size.height - (isIos ? 100 : 80); // for non notches phone use 76 instead of 100 (it's the height of status and navigation bar)
      _initialCount = screenHeight ~/ _heightBox;
      _initialAdd = screenHeight % _heightBox;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(_count == null ? "Let's count" : "Images shown = ${_count}")),
      body: ListView.builder(
        itemCount: 100,
        controller: _scrollController,
        itemBuilder: (context, index) {
          if (index == 0) return Container();

          if (index != 0 && index % (_itemsInList + 1) == 0) {
            return Container(
              height: _heightContainer,
              alignment: Alignment.center,
              color: Colors.blue[(index * 20) % 1000],
              child: Text("Image #${(index + 1) ~/ 5}"),
            );
          }

          return SizedBox(height: _heightListTile, child: ListTile(title: Text("Item ${index}")));
        },
      ),
    );
  }
}

答案 1 :(得分:2)

enter image description here

此解决方案将检测您的Image在用户屏幕上是否已完全可见,并且将更改AppBar的标题。假设您要显示一个包含一些内容和一个Image的页面:

  class ImageDisplayDetection extends StatefulWidget {
  ImageDisplayDetection({Key key,}) : super(key: key);

  @override
  _ImageDisplayDetectionState createState() => _ImageDisplayDetectionState();
  }

  class  _ImageDisplayDetectionState extends State<ImageDisplayDetection> {

  ScrollController _controller; // To get the current scroll offset

  var _itemSize = 400.0 ; // The height of your image

  double _listSize = 2000.0 ;

  double position = 1500.0 ; // position from the top of the list where the image begins

  var seen = false ; // to report the visibility of your image


 @override
 void initState() {
    _controller = ScrollController();
    _controller.addListener(_scrollListener); // The listener will be used to check if the image has become visible
    super.initState();
 }

 _scrollListener() {
    setState(() {
      // This 60.0 is the assumed hieght of the bottom navigation buttons so the image won't be considered visible unless it is above these buttons
      if((_controller.offset + MediaQuery.of(context).size.height) >= position + _itemSize + 60.0){
        seen = true ;
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
    backgroundColor: Colors.grey.shade200 ,
    appBar: new AppBar(title: new Text(seen ? 'Image Displayed Successfully' : 'Image not displayed'),),
    body: ListView.builder(
      controller: _controller ,
      itemCount: 1,
      itemBuilder: (context, index) {
        return Container(
              height: _listSize ,
              child: new Stack(
                children: <Widget>[
                  // You can include other childern here such as TextArea

                  Positioned(
                    top: position,
                    child: SizedBox(
                      height: _itemSize,
                      width: _itemSize,
                      child: ClipRRect(
                        borderRadius: BorderRadius.circular(5.0),
                        child: Image.asset('assets/images/2.jpg'), //Change the image widget to match your own image source and name
                      ),
                    ),
                  ),
                ],
              ),
            );
         }),
       );
     }
   }

如果您想让listview包含多个ListTiles,则可以选择使用此answer,它可以检测任意索引的child是否可见并显示在屏幕上的特定位置。

答案 2 :(得分:1)

还没有办法知道listView中的可见项。遵循此issue。您可以在列表视图中添加项目,并使用ScrollController检查是否已到达列表底部。

import 'package:flutter/material.dart';

void main() => runApp(MainPage());

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  ScrollController _controller;

  @override
  void initState() {
    _controller = ScrollController();
    _controller.addListener(_scrollListener);
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Scaffold(
        backgroundColor: Colors.white,
        body: ListView(
          controller: _controller,
          children: <Widget>[
            Text(text),
            Text(text),
            Text(text),
            Text(text),
            Text(text),
            Image.network(
                'https://sample-videos.com/img/Sample-png-image-200kb.png'),
            Text(text),
          ],
        ),
      ),
    );
  }

  _scrollListener() {
    if (_controller.offset >= _controller.position.maxScrollExtent &&
        !_controller.position.outOfRange) {
      // reached at the bottom of list
      // Increment the view by one
    }
  }

  String text =
      'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Curabitur id ornare orci. In aliquet sed leo vel suscipit. Suspendisse eget dolor arcu. Duis fermentum quam suscipit nisl interdum fermentum. Aliquam laoreet, mi eu gravida rutrum, elit ex ornare erat, in egestas leo augue ac nisl. Sed vitae commodo metus, nec vulputate dui. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Phasellus rhoncus tellus nec diam elementum laoreet. Phasellus ac sapien leo. Donec dolor ante, porta quis pellentesque quis, iaculis vitae quam. Sed bibendum tortor a vestibulum malesuada. Duis non nisl congue, fringilla nulla et, laoreet odio.';
}