Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to realize the 3D flipping effect of Advertising Card by imitating NetEase by Flutter

2025-01-23 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)05/31 Report--

This article mainly introduces the relevant knowledge of "Flutter imitating NetEase how to achieve advertising card 3D flipping effect". The editor shows you the operation process through actual cases, the operation method is simple and fast, and practical. I hope this "Flutter imitating NetEase how to achieve advertising card 3D flipping effect" article can help you solve the problem.

Let's first take a look at the effect of NetEase's news:

Realization idea 1. Get all kinds of distances

Look at the picture:

Idea: such as the figure above, the height of the status bar and the height of AppBar, we can also get the height of the screen, then naturally we can calculate the height of the content area, and when we get the height of the content area, we first put it aside, and then we need to get the distance between the advertising area and the AppBar, which is the core data for flipping. Here we can get the rendering object RenderObject of this component through GlobalKey and convert it to RenderBox, and through RenderBox we can get the coordinates of the component on the screen, so that the value of the Y axis of this coordinate is the distance from the top of the current component.

Core code:

/ / here we get the coordinates of the y-axis relative to the upper-left component of the screen GlobalKey _ globalKey = GlobalKey (); RenderBox? RenderBox = _ globalKey.currentContext?.findRenderObject () as RenderBox?;double? Dy = renderBox?.localToGlobal (Offset.zero) .dy

Then we can calculate several key data:

Status bar height: stateHeight = MediaQuery.of (context) .padding.top; known.

AppBar height: appBarHeight = 56; default height is known.

Content area height: contentHeight = MediaQuery.of (context). Size.height-stateHeight-appBarHeight

Assuming that the height of our advertising area is 200, the height of the advertising component is generally fixed.

It is concluded that the maximum distance from the top of the advertisement to the top: maxHeight= contentheight-200

Remember the y value we got above, which is the distance from the top of the current ad to the top of the screen, so we can get the distance from the bottom of the AppBar to the current ad: bannerY = dy-appBarHeight-stateHeight.

By the same token, we can get the sliding distance of the current ad: scrollY = contentheight-200-bannerY.

The maximum distance to slide is: maxSrollY = contentHeight-bannerHeight

2. Flip

After getting rid of these data, the next work is relatively simple, we can use the Transform component to flip 180 degrees.

Get the ratio of the current slide, which is the current sliding distance / maximum sliding distance, that is, scrollY/maxHeight;. Next, let's take a look at the class Transform.

Code:

Container (padding: EdgeInsetsDirectional.only (start: 20, end: 20, top: 30, bottom: 30), height: bannerHeight, key: _ globalKey, child: Transform (alignment: Alignment.center, / / alignment relative to the origin of the coordinate system flips from the middle transform: Matrix4.identity () / / this is a matrix transformation class that can flip the coordinates of the component If you are interested, you can learn about... rotateX (0) / / flip the X axis.. rotateY (angle), / / flip the Y axis where you need to input the angle child: Image.asset ("images/img.png", fit: BoxFit.fill,)).

Through rotateY, you can flip the component around the Y axis, which achieves the desired 3D effect. Above, we get the sliding ratio, so we can multiply this ratio by Pi and refresh the page. Next, we update this number by sliding listening to see the effect:

Core code:

Double h = MediaQuery.of (context) .size.height; / / screen height RenderBox? RenderBox = _ globalKey.currentContext?.findRenderObject () as RenderBox?;double? Dy = renderBox?.localToGlobal (Offset.zero). Dy;// 56 AppBar height if (dy! = null) {/ / Advertising distance AppBar Y axis distance var bannerY = dy-appBarHeight-stateHeight; / / main content area height var contentHeight = h-appBarHeight-stateHeight; if (bannerY + bannerHeight

< contentHeight && bannerY >

0) {setState (() {/ / sliding distance angle = pi * ((contentHeight-bannerHeight-bannerY) / (contentHeight-bannerHeight));});}}

Effect:

It's true that the flip effect has been achieved, but why doesn't it look right? here are two questions:

1. The picture turned over is mirrored directly.

2. When we slide halfway, the width of both sides is the same, and the 3D effect is not obvious.

In fact, both of these problems are easy to solve.

For the first sliding angle problem, when we slide to 90 degrees to flip, we only need to flip the angle + 180 degrees. This is equivalent to turning over 360 degrees, and eventually it will naturally return to the original picture.

Second, we need to set a property of Transform.. setEntry (3, 2, 0.002) to make the card look far and near during the flipping process.

Let's add these two attributes to see the effect:

Does it look much better this way?

Here I simply insert an ad, and if there are multiple ads, it is recommended to store the Key with a Map object, because a Key can only correspond to one component.

The complete code class ListViewWidgetDemo extends StatefulWidget {@ override State createState () {return ListViewState ();}} class ListViewState extends State {List lis = []; late ScrollController _ scrollController = ScrollController (); String imageUrl = "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 (); double angle = 0; double bannerHeight = 200 @ override void initState () {WidgetsBinding.instance?.addPostFrameCallback ((timeStamp) {_ scrollController.addListener () {double appBarHeight = 56; double stateHeight = MediaQuery.of (context) .padding.top; double h = MediaQuery.of (context) .size.height; / / screen height RenderBox? RenderBox = _ globalKey.currentContext?.findRenderObject () as RenderBox?; double? Dy = renderBox?.localToGlobal (Offset.zero) .dy; / 56 AppBar height if (dy! = null) {/ / Advertising distance AppBar Y axis distance var bannerY = dy-appBarHeight-stateHeight; / / main content area height var contentHeight = h-appBarHeight-stateHeight; if (bannerY + bannerHeight)

< contentHeight && bannerY >

0) {setState (() {/ / sliding distance angle = pi * ((contentHeight-bannerHeight-bannerY) / (contentHeight-bannerHeight) / / first half 090 second half 270360 if (angle > = (pi / 2)) {angle = angle + pi;}});}); super.initState (); for (int I = 0; I < 40) Lis.add +) {lis.add (NewsListBean (i.isEven? 0: 1, "Information title $I", imageUrl,));} / / insert ad lis.insert (12, NewsListBean (2, "Advertising", imageUrl)) } @ override Widget build (BuildContext context) {return Scaffold (appBar: AppBar (title: Text), body: ListView.builder (controller: _ scrollController, shrinkWrap: true, scrollDirection: Axis.vertical, itemCount: lis.length, itemBuilder: (context) Index) {return _ listWidget (lisi [index]) }));} Widget _ listWidget (NewsListBean bean) {late Widget widget Switch (bean.type) {case 0: widget = Container (height: 50, padding: EdgeInsetsDirectional.only (start: 20), alignment: Alignment.centerLeft, color: Colors.blue, child: Text (bean.title, style: TextStyle (),); break Case 1: 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 Case 2: widget = Container (padding: EdgeInsetsDirectional.only (start: 20, end: 20, top: 30, bottom: 30), height: bannerHeight, key: _ globalKey, child: Transform (alignment: Alignment.center / / alignment relative to the origin of the coordinate system 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;} return widget;}} class NewsListBean {/ / Information Type 0: no Information figure 1: information figure 2 A 3D advertisement final int type; final bool isFirst; final String title; final String image; NewsListBean (this.type, this.title, this.image, {this.isFirst = false}) } this is the end of the content about "how Flutter imitates NetEase to achieve the 3D flip effect of advertising cards". Thank you for your reading. If you want to know more about the industry, you can follow the industry information channel. The editor will update different knowledge points for you every day.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report