Flutter仿网易怎么实现广告卡片3D翻转效果(flutter,开发技术)

时间:2024-05-07 08:29:18 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    先看下网易新闻的效果:

    Flutter仿网易怎么实现广告卡片3D翻转效果

    实现思路

    1、获取各种距离

    看图:

    Flutter仿网易怎么实现广告卡片3D翻转效果

    思路: 如上图,状态栏高度和AppBar的高度我们都可以得到,屏幕的高度我们也可以得到,那么自然我们就可以计算出内容区域的高度,拿到内容区域高度我们先放到一边,接下来我们需要获取广告区域距离AppBar的距离,这是一个进行翻转核心数据,这里我们可以通过GlobalKey获取这个组件的渲染对象RenderObject并转化为RenderBox,通过RenderBox我们可以获取到这个组件在屏幕上的坐标,这样我们拿到这个坐标Y轴的值就是当前组件距离顶部的距离

    核心代码:

    //这里我们获取相对于屏幕左上角组件的坐标y轴GlobalKey_globalKey=GlobalKey();RenderBox?renderBox=_globalKey.currentContext?.findRenderObject()asRenderBox?;double?dy=renderBox?.localToGlobal(Offset.zero).dy;

    接下来我们就可以计算出几个关键数据:

    状态栏高度:stateHeight = MediaQuery.of(context).padding.top;已知。

    AppBar高度:appBarHeight = 56; 默认高度 已知。

    内容区域高度:contentHeight = MediaQuery.of(context).size.height - stateHeight -appBarHeight;

    假设我们广告区域的高度是200,广告组件的高度一般都是固定的。

    得出:广告上方距离顶部的最大距离:maxHeight= contentheight - 200;

    还记得我们上面获取的dy值吗,这个值是当前广告上面距离屏幕顶部的距离,那么我们就可以得出当前广告距离AppBar底部的距离: bannerY = dy - appBarHeight - stateHeight;

    同理可以得出当前广告的滑动距离:scrollY = contentheight - 200 - bannerY;

    滑动的最大距离就是:maxSrollY = contentHeight - bannerHeight;

    2、翻转

    搞定了这些数据,接下来的工作就比较简单了,我们使用Transform组件来进行180度的翻转就可以了,
    获取当前滑动的比例,那就是当前滑动距离/最大滑动距离,也就是 scrollY/maxHeight; 接下来我们看下Transform这个类,

    代码:

    Container(padding:EdgeInsetsDirectional.only(start:20,end:20,top:30,bottom:30),height:bannerHeight,key:_globalKey,child:Transform(alignment:Alignment.center,//相对于坐标系原点的对齐方式从中间翻转transform:Matrix4.identity()//这是一个矩阵变换类,可以对组件的坐标进行翻转,有兴趣可以了解下..rotateX(0)//翻转X轴..rotateY(angle),//翻转Y轴这里需要传入角度child:Image.asset("images/img.png",fit:BoxFit.fill,),));

    通过rotateY就可以将组件绕着Y轴进行翻转,也就达到了我们想要的3D效果,上面我们得到了滑动比例,那么我们就可以用这个比例乘以PI值,刷新页面就可以了呗,接下来我们通过滑动监听将这个数字进行更新看下效果:

    核心代码:

    doubleh=MediaQuery.of(context).size.height;//屏幕高度RenderBox?renderBox=_globalKey.currentContext?.findRenderObject()asRenderBox?;double?dy=renderBox?.localToGlobal(Offset.zero).dy;//56AppBar高度if(dy!=null){//广告距离AppBarY轴距离varbannerY=dy-appBarHeight-stateHeight;//主内容区域高度varcontentHeight=h-appBarHeight-stateHeight;if(bannerY+bannerHeight<contentHeight&&bannerY>0){setState((){//滑动的距离angle=pi*((contentHeight-bannerHeight-bannerY)/(contentHeight-bannerHeight));});}}

    效果:

    Flutter仿网易怎么实现广告卡片3D翻转效果

    翻转效果确实实现了,不过怎么看着有点不对劲呢,这里有两个问题:

    1、划上去翻过来的图片直接镜像了。

    Flutter仿网易怎么实现广告卡片3D翻转效果

    2、当我们滑动到一半的时候,两边的宽度是一致的,3D效果不明显。

    Flutter仿网易怎么实现广告卡片3D翻转效果

    其实这两个问题都很好解决,

    第一个滑动角度问题,我们滑动到90度进行翻过来的时候只需要将角度+180度进行翻转即可。这样就相当于翻了360度,最后自然会回到原来的图片的样子。

    第二个我们需要设置Transform的一个属性..setEntry(3, 2, 0.002),让卡片翻转过程中看起来远小近大的效果。

    我们加上这两个属性再看看效果:

    Flutter仿网易怎么实现广告卡片3D翻转效果

    这样看着是不是效果就好多了。

    这里我只简单了插入了一条广告,如果有多个广告建议用一个Map对象将Key存储起来,因为一个Key只能对应一个组件。

    完整代码

    classListViewWidgetDemoextendsStatefulWidget{@overrideState<StatefulWidget>createState(){returnListViewState();}}classListViewStateextendsState<ListViewWidgetDemo>{List<NewsListBean>lis=<NewsListBean>[];lateScrollController_scrollController=ScrollController();StringimageUrl="https://images.unsplash.com/photo-1451187580459-43490279c0fa?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60";GlobalKey_globalKey=GlobalKey();doubleangle=0;doublebannerHeight=200;@overridevoidinitState(){WidgetsBinding.instance?.addPostFrameCallback((timeStamp){_scrollController.addListener((){doubleappBarHeight=56;doublestateHeight=MediaQuery.of(context).padding.top;doubleh=MediaQuery.of(context).size.height;//屏幕高度RenderBox?renderBox=_globalKey.currentContext?.findRenderObject()asRenderBox?;double?dy=renderBox?.localToGlobal(Offset.zero).dy;//56AppBar高度if(dy!=null){//广告距离AppBarY轴距离varbannerY=dy-appBarHeight-stateHeight;//主内容区域高度varcontentHeight=h-appBarHeight-stateHeight;if(bannerY+bannerHeight<contentHeight&&bannerY>0){setState((){//滑动的距离angle=pi*((contentHeight-bannerHeight-bannerY)/(contentHeight-bannerHeight));//前半部分0-90后半部分270-360if(angle>=(pi/2)){angle=angle+pi;}});}}});});super.initState();for(inti=0;i<40;i++){lis.add(NewsListBean(i.isEven?0:1,"资讯标题$i",imageUrl,));}//插入广告lis.insert(12,NewsListBean(2,"广告",imageUrl));}@overrideWidgetbuild(BuildContextcontext){returnScaffold(appBar:AppBar(title:Text("仿网易新闻广告卡片翻转"),),body:ListView.builder(controller:_scrollController,shrinkWrap:true,scrollDirection:Axis.vertical,itemCount:lis.length,itemBuilder:(context,index){return_listWidget(lis[index]);}));}Widget_listWidget(NewsListBeanbean){lateWidgetwidget;switch(bean.type){case0:widget=Container(height:50,padding:EdgeInsetsDirectional.only(start:20),alignment:Alignment.centerLeft,color:Colors.blue[200],child:Text(bean.title,style:TextStyle(),));break;case1:widget=Row(children:[Expanded(child:Container(height:80,alignment:Alignment.center,color:Colors.red[200],margin:EdgeInsets.all(10),child:Text(bean.title)),),Image.network(bean.image,width:40,height:40,)],);break;case2:widget=Container(padding:EdgeInsetsDirectional.only(start:20,end:20,top:30,bottom:30),height:bannerHeight,key:_globalKey,child:Transform(alignment:Alignment.center,//相对于坐标系原点的对齐方式transform:Matrix4.identity()..setEntry(3,2,0.002)..rotateX(0)..rotateY(angle),child:Image.asset("images/img.png",fit:BoxFit.fill,),));break;default:widget=SizedBox();break;}returnwidget;}}classNewsListBean{//资讯类型0:资讯无图1:资讯有图2:3d广告finalinttype;finalboolisFirst;finalStringtitle;finalStringimage;NewsListBean(this.type,this.title,this.image,{this.isFirst=false});}
     </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
    本文:Flutter仿网易怎么实现广告卡片3D翻转效果的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:详解Python如何绘制动态水球图下一篇:

    6 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18