NestedScrollView中child首次点击无效

本文探讨了在使用NestedScrollView时遇到的点击事件延迟问题,并提供了一个解决方案。通过重写两个关键方法,可以实现点击事件的正常响应。

问题发生

NestedScrollView是support v4包里提供的适应嵌套滑动的ScrollView,用法和ScrollView是相似的,这里不是讲它怎么使用,而是说它的一个Bug——在NestedScrollView里面的添加相关的子View,当滑动NestedScrollView之后,对于任何子View的首次点击事件都是无效的,第二次点击就是OK的。相关Issues

解决方案

public class NestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild {
...
private void initScrollView() {
    ...
    // replace this line:
    // mScroller = new ScrollerCompat(getContext(), null);
    mScroller = ScrollerCompat.create(getContext(), null);
    ...
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    ...
    switch (action & MotionEventCompat.ACTION_MASK) {
        ...
        case MotionEvent.ACTION_DOWN: {
            ...
            // replace this line:
            // mIsBeingDragged = !mScroller.isFinished();
            mIsBeingDragged = false;
            ...
        }
    }
}   
}

自己创建一个NestedScrollView重写两个方法,基本上就可以用了!!

具体请参考:
stackoverflow

### 如何在 Flutter 中使用 `NestedScrollView` 和 `SliverPersistentHeader` #### 创建带有持久头部的嵌套滚动视图 为了构建一个具有复杂滚动行为的应用界面,可以利用 `NestedScrollView` 来组合多个级组件。特别是当涉及到需要固定某些部分(比如顶部栏),同时让其余内容能够自由滚动的情况时,`SliverPersistentHeader` 是非常有用的工具。 下面是一个简单的例来展示如何设置这样的结构: ```dart import 'package:flutter/material.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( appBar: AppBar(title: Text('Example')), body: NestedScrollView( headerSliverBuilder: (BuildContext context, bool innerBoxIsScrolled) { return <Widget>[ SliverOverlapAbsorber( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), sliver: SliverAppBar( title: const Text('Title'), floating: false, pinned: true, expandedHeight: 160.0, flexibleSpace: FlexibleSpaceBar( background: Image.network( "https://example.com/image.jpg", fit: BoxFit.cover, ), ), ), ), // 添加一个固定的头部区域 SliverPersistentHeader( delegate: _MySliverAppBarDelegate( minHeight: 60.0, maxHeight: 200.0, child: Container( color: Colors.lightBlueAccent, child: Center(child: Text('PERSISTENT HEADER', style: TextStyle(fontSize: 24))), ), ), pinned: true, ) ]; }, body: Builder( builder: (BuildContext context) { return CustomScrollView( slivers: <Widget>[ SliverOverlapInjector( handle: NestedScrollView.sliverOverlapAbsorberHandleFor(context), ), SliverPadding( padding: EdgeInsets.all(8.0), sliver: new SliverFixedExtentList( itemExtent: 50.0, delegate: new SliverChildBuilderDelegate( (context, index) => ListTile(title: Text('$index')), childCount: 30, ), ), ), ], ); } ), ), ), ); } } // 定义自定义的 SliverPersistentHeader 的代理类 class _MySliverAppBarDelegate extends SliverPersistentHeaderDelegate { final double minHeight; final double maxHeight; final Widget child; _MySliverAppBarDelegate({ required this.minHeight, required this.maxHeight, required this.child, }); @override double get minExtent => minHeight; @override double get maxExtent => math.max(maxHeight, minHeight); @override Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) { return SizedBox.expand(child: child); } @override bool shouldRebuild(_MySliverAppBarDelegate oldDelegate) { return maxHeight != oldDelegate.maxHeight || minHeight != oldDelegate.minHeight || child != oldDelegate.child; } } ``` 此代码片段展示了如何创建一个包含图片背景的大标题栏和一个始终可见的小标题栏的效果[^1]。通过调整 `_MySliverAppBarDelegate` 类中的参数,可以根据实际需求改变这个浮动条目的外观特性。 #### 关于 `pinned`, `floating` 属性的作用说明 - 当设置了 `pinned=true` 后,即使用户向上滚动页面,该头部也会保持在其位置上不消失。 - 如果希望随着用户的上下滑动使头部跟随移动,则应将 `floating=false` 设置为真值,并配合合适的动画效果以增强用户体验[^2]。 #### 处理潜在的问题 有时可能会遇到一些由于布局冲突或者事件处理不当而导致的问题。例如,在含有 `TabBarView` 的场景下,内外层滚动可能不会按预期工作。此时可以通过仔细配置各个组件之间的关系并确保它们遵循正确的层次结构来进行修复[^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值