Carousel Banner of Flutter Control Package

There are many ways to realize the carousel image in Flutter, such as using three-party flutter_swiper, card_swiper, etc. Using these three parties, you can quickly and conveniently realize a carousel image display, which can basically meet our daily development needs. If Say, if you want some customized operations, you have to change the source code or customize one yourself. If you define it yourself, Flutter provides a native component PageView, which can be used to easily implement a carousel.

PageView is similar to ViewPager in Android. It can slide the page horizontally or vertically. The specific use method can be directly PageView(), or use PageView.builder(). Both methods can be realized. The difference is that the former will convert all pages One-time initialization, but the latter will not, in order to facilitate everyone to understand this component, we will simply give a small case.

According to past practice, let's first look at the outline of this article, which is roughly as follows:

1. List of final realization effects

2. The properties and specific use of the PageView component

3. Precautions for carousel image packaging

4. Case source code analysis

5. Packaged source code and how to use it

6. Summary

1. List of final realization effects

Use PageView to encapsulate some specific effects, such as text indicators, rounded corner indicators, and indicator positions, indentation display of carousel pictures, etc., and record a Gif rendering, as follows:

Two, the properties and specific use of the PageView component

After all, PageView is used to implement a carousel, so for this component, we need a brief introduction:

First look at the basic common attributes:

Attributes

type

overview

scrollDirection

Axis

Scrolling direction, horizontal or vertical, the default is horizontal.

Horizontal: Axis.horizontal

Vertical: Axis.vertical

controller

PageController

Scroll controller, which can locate the page and obtain information such as the page

onPageChanged

ValueChanged<int>

Callback when the page changes

physics

ScrollPhysics

Sliding effect, if not set, there will be different scrolling effects according to different platforms

After NeverScrollableScrollPhysics is set, the page cannot be scrolled

BouncingScrollPhysics means that there will be a bouncing effect after scrolling to the end, which is the default interaction of iOS

ClampingScrollPhysics means that an effect will be given when scrolling to the end, which is the default interaction of Android

FixedExtentScrollPhysics is the interaction of iOS classic selection time component UIDatePicker

pageSnapping

bool

Whether it is a full page slide, the default is true

In actual development, the PageView.builder() method is mostly used. It is also recommended that you use this method. It is very simple. You only need to return the page view in itemBuilder. The code is as follows:

PageView.builder(
            itemCount: 6,
            onPageChanged: (position) {
              print("当前索引为:$position");
            },
            itemBuilder: (context, index) {
              return Container(
                  color: Colors.amber,
                  alignment: Alignment.center,
                  child: Text("我是第$index个页面"));
            })

The basic effect is as follows:

3. Precautions for packaging carousels

After basically mastering the usage of PageView, we started to package a carousel map. Let’s first analyze the elements that make up the carousel map. First, it meets the requirements of automatic carousel, and can dynamically set the carousel duration. Second, it must be able to meet the requirements of various indicators, and the position can be set dynamically. Third, it must meet the requirements of manual rotation and automatic rotation, and it must handle the direct conflict between gestures and timing. Fourth, the most important thing is to use Keep it simple.

Timer Considerations

After simply determining the elements, we can write by hand. Automatic carousel is very simple. We only need to start a timer, but the timer needs to pay attention to starting and pausing, that is, when to start and when to pause, otherwise it will be very difficult. It is easy to cause confusion in the carousel.

At the beginning of the carousel image, firstly, the automatic carousel property is actively set. When we enter the page, we need to enable the timing. If the page retreats to the background and then returns to the foreground, we also need to enable the carousel. It is pause. In addition to retreating into the background to pause, there is also a need to pause when gestures slide, otherwise it will cause conflicts with timing.

Gesture Considerations

Regarding gestures, if we directly monitor the gestures of page components, we find that they conflict with PageView. In order to solve this gesture problem, we can use the original pointer event listener to monitor gesture sliding.

Part of the code is as follows. After the finger is pressed, the timing is canceled, and when the finger is lifted, the timing is turned on. Of course, if there is only pressing and lifting, then it is a click event, and we can call back this event to the user.

Listener(
          onPointerDown: (event) {
            //手指按下,定时取消
            _pauseTimer();
            _isClick = true;
          },
          onPointerMove: (event) {
            _isClick = false;
          },
          onPointerUp: (event) {
            //手指抬起,定时开启
            _startTimer();
            //作为点击事件
            if (_isClick && widget.bannerClick != null) {
              widget.bannerClick!(_currentPage);
            }
          },
          child: PageView.builder()t
)

Indicator Considerations

You need to pay attention to the indicator. If you use it for yourself, there is nothing wrong with one indicator. If it is for others to use, then it must be colorful and meet as many needs as possible.

4. Case source code analysis

1. Create a timer

The timer uses Timer, which defines two methods, which are convenient for starting and pausing. When the carousel time is up, the page switching operation can be performed, using PageController's animateToPage to switch.

/*
  * 开启定时
  * */
  void _startTimer() {
    if (!_isRunning) {
      _isRunning = true;
      _timer = Timer.periodic(Duration(seconds: widget.delay!), (timer) {
        _controller.animateToPage(_pagePosition + 1,
            duration: const Duration(milliseconds: 800),
            curve: Curves.easeInOut);
      });
    }
  }

  /*
  * 暂停定时
  * */
  void _pauseTimer() {
    if (_isRunning) {
      _isRunning = false;
      _timer?.cancel(); //取消计时器
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    _timer?.cancel();
    super.dispose();
  }

2. Perceive life cycle changes

When the page retreats to the background and returns to the foreground, we need to pause and start timing, then we need to monitor the page. After adding the monitor, remember the current class with WidgetsBindingObserver.

// 添加监听
    WidgetsBinding.instance.addObserver(this);


  /*
  * 感知生命周期变化
  * */
  @override
  void didChangeAppLifecycleState(AppLifecycleState state) {
    super.didChangeAppLifecycleState(state);
    if (state == AppLifecycleState.resumed && widget.autoPlay!) {
      _startTimer(); //页面可见,开启定时
    } else if (state == AppLifecycleState.paused && _isRunning) {
      _pauseTimer(); //页面不可见,关闭定时
    }
  }

3. Picture rounded corners

There are many rounded corners of pictures, such as Container decorator, or using the component ClipRRect.

ClipRRect(
         //设置图片圆角
          borderRadius: BorderRadius.circular(widget.radius!),
          child: getBannerImage(imageUrl)))

4. Indicator type and position

The indicator type can be specially customized according to business needs. The current types in the source code include the following types, namely, circle, rounded corner, rectangle, text, and its position can be placed in the middle, left and right sides, and carousel below the figure.

/*
  * 指示器
  * */
  Widget _buildIndicators(mainAxisAlignment) {
    if (widget.indicatorType == IndicatorType.text) {
      //文字
      return Container(
        alignment: widget.textIndicatorAlignment,
        child: VipText(
          "${_currentPage + 1}/${widget.imageList!.length}",
          style: widget.textIndicatorStyle,
          backgroundColor: widget.textIndicatorBgColor,
          padding: widget.textIndicatorPadding,
          paddingLeft: widget.textIndicatorPaddingLeft,
          paddingTop: widget.textIndicatorPaddingTop,
          paddingRight: widget.textIndicatorPaddingRight,
          paddingBottom: widget.textIndicatorPaddingBottom,
        ),
      );
    }
    return Row(
      mainAxisAlignment: mainAxisAlignment,
      children: List.generate(widget.imageList!.length, (index) {
        return Container(
          width: _currentPage == index
              ? widget.indicatorWidth
              : widget.indicatorUnWidth ?? widget.indicatorWidth,
          height: _currentPage == index
              ? widget.indicatorHeight
              : widget.indicatorUnHeight ?? widget.indicatorHeight,
          margin: EdgeInsets.symmetric(horizontal: widget.indicatorMargin!),
          decoration: BoxDecoration(
            shape: widget.indicatorType == IndicatorType.circle
                ? BoxShape.circle
                : BoxShape.rectangle,
            borderRadius: widget.indicatorType == IndicatorType.rectangle
                ? BorderRadius.all(Radius.circular(widget.indicatorRadius!))
                : null,
            color: _currentPage == index
                ? widget.indicatorSelectColor
                : widget.indicatorUnSelectColor,
          ),
        );
      }),
    );
  }

5. Carousel image indentation effect

There are two types of indentation. One is that the left and right pictures will become smaller except for the current picture, and it will be enlarged after sliding to the current picture. The other is very simple indentation.

viewportFraction can be understood as the ratio of the content of a page to the screen, full is 1, less than 1 is not full.

 PageController(viewportFraction: widget.viewportFraction!)

If we want to zoom in and zoom out the picture when sliding, then we need to perform a zoom in and zoom out animation Transform.scale.

return Transform.scale(
                    scale: endScale,
                    child: Container(
                        margin: widget.imageMargin != null
                            ? EdgeInsets.all(widget.imageMargin!)
                            : EdgeInsets.only(
                                left: widget.imageMarginLeft!,
                                top: widget.imageMarginTop!,
                                right: widget.imageMarginRight!,
                                bottom: widget.imageMarginBottom!),
                        child: ClipRRect(
                            //设置图片圆角
                            borderRadius: BorderRadius.circular(widget.radius!),
                            child: getBannerImage(imageUrl))))

5. Packaged source code and how to use it

At present, the source code has been uploaded to Github. If you need it, you can check it. Due to the limited space, I will not paste it all. Address:

https://github.com/AbnerMing888/flutter_widget/blob/master/lib/ui/widget/vip_banner.dart

List of available attributes

Attributes

type

overview

imageList

List<String>

Image address collection

titleList

List<String>

title collection

radius

double

Picture rounded corners

height

double

image height

delay

int

How many times to rotate

autoPlay

bool

Whether to automatically rotate

bannerClick

Function(int)

item click event

showIndicators

bool

Whether to show the indicator

imageMarginLeft

double

The distance from the image to the left

imageMarginTop

double

The distance from the image to the top

imageMarginRight

double

The distance from the image to the right

imageMarginBottom

double

The distance from the image to the bottom

imageMargin

double

The distance from the upper left to the lower right of the picture, set uniformly

marginLeft

double

The overall distance from the carousel to the left

marginTop

double

The overall distance of the carousel image from the top

marginRight

double

The overall distance of the carousel image from the right

marginBottom

double

The overall distance from the lower edge of the carousel image

margin

double

The overall distance of the carousel image from the upper left to the lower right

indicatorMarginLeft

double

The distance from the indicator to the left

indicatorMarginRight

double

The distance from the indicator to the right

indicatorMarginBottom

double

The distance from the indicator to the bottom

indicatorSelectColor

Color

The color selected by the indicator

indicatorUnSelectColor

Color

The unselected color of the indicator

indicatorWidth

double

indicator width

indicatorHeight

double

indicator high

indicatorUnWidth

double

indicator unchecked wide

indicatorUnHeight

double

indicator unchecked high

indicatorMargin

double

indicator margin

indicatorType

IndicatorType

indicator type

circle, rectangle, text

indicatorRadius

double

Number of rounded angles of the indicator

indicatorBannerBottom

bool

Indicator position, whether it is on the banner or under the banner

indicatorBottomColor

Color

The background of the indicator under the Banner, the default is transparent

indicatorBottomHeight

double

The height of the indicator under the Banner

indicatorBottomMarginRight

double

The indicator is to the right of the distance under the Banner

indicatorBottomMarginLeft

double

The indicator is on the left of the distance under the Banner

indicatorBottomMainAxisAlignment

MainAxisAlignment

The position of the indicator under the Banner

left middle right

viewportFraction

double

banner indentation

textIndicatorAlignment

Alignment

text position

textIndicatorStyle

TextStyle

text style

textIndicatorBgColor

Color

text indicator background

textIndicatorPadding

double

text indicator padding

textIndicatorPaddingLeft

double

text indicator padding left

textIndicatorPaddingTop

double

text indicator padding on

textIndicatorPaddingRight

double

text indicator padding right

textIndicatorPaddingBottom

double

text indicator padding down

titleBgColor

Color

Text Title background

titleHeight

double

Text Title Height

titleAlignment

Alignment

The position of the text Title

titleStyle

TextStyle

Text Title style

titleMarginBottom

double

Text Title distance from bottom

bannerOtherScale

double

Image scaling other than middle

placeholderImage

String

Banner placeholder

errorImage

String

Banner error graph

imageBoxFit

BoxFit

Image scaling mode

How to use

normal loading

VipBanner(
          imageList: const [
            "https://www.vipandroid.cn/ming/image/gan.png",
            "https://www.vipandroid.cn/ming/image/zao.png"
          ],
          bannerClick: (position) {
            //条目点击
            Toast.toast(context, msg: position.toString());
          })

text indicator

VipBanner(
          imageList: const [
            "https://www.vipandroid.cn/ming/image/gan.png",
            "https://www.vipandroid.cn/ming/image/zao.png"
          ],
          indicatorType: IndicatorType.text,
          bannerClick: (position) {
            Toast.toast(context, msg: position.toString());
          })

rounded corner indicator

VipBanner(
          imageList: const [
            "https://www.vipandroid.cn/ming/image/gan.png",
            "https://www.vipandroid.cn/ming/image/zao.png"
          ],
          indicatorType: IndicatorType.rectangle,
          indicatorRadius: 5,
          indicatorWidth: 20,
          indicatorHeight: 5,
          bannerClick: (position) {
            Toast.toast(context, msg: position.toString());
          })

There are many types of usage, so I won’t give examples one by one. You can see the page in the source code, the address is:

https://github.com/AbnerMing888/flutter_widget/blob/master/lib/ui/page/view/banner/banner_page.dart

6. Summary

When encapsulating, the following elements must be determined, one is the timing carousel, the other is gesture and timing conflict resolution, the third is infinite carousel, the fourth is the setting of the indicator, and the fifth is the effect of the picture carousel. It is not difficult to encapsulate these potential elements with a simple carousel.

Guess you like

Origin blog.csdn.net/ming_147/article/details/131161714