我在可滚动屏幕中有一个Image
组件。在屏幕打开时,无法看到图像,但您需要向下滚动才能查看。
如何在用户滚动图像后确保图像完全被用户看到?我想数一下用户的形象印象。
你是如何实现这一目标的?
我没有太多关于你的代码的信息,所以这就是我解决它的方法。仅在图像在屏幕上完全可见时才会计算印象,您可以使用_count =
表达式更改该图像。我使用简单的Container
为Image
。
先看看这个截图。
码
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}")));
},
),
);
}
}
此解决方案将检测您的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
是否显示在屏幕的某个位置。
目前还没有办法知道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.';
}