Two imageViews implement image rotation

foreword

In many projects, the function of picture carousel will be used. Now there are endless wheels about picture carousel on the Internet. According to my own ideas, the author also uses two imageViews to realize picture carousel. Here I will introduce it to you. The author's main ideas and approximate steps.

Carousel implementation steps

Hierarchy

The bottom layer is a UIView, with a UIScrollView and UIPageControl on it, and two UIImageViews on the scrollView, the width and height of the imageView = the width and height of the scrollView = the width and height of the view

figure 1

Carousel principle

Assuming that the width of the carousel control is x and the height is y, we set the width of the contentSize of the scrollView to 3x, and let the offset of the scrollView in the x direction be x, that is, to display the intermediate content

    scrollView.contentSize = CGSizeMake(3x, y);
    scrollView.contentOffset = CGPointMake(x, 0);

2

Next, use the proxy method scrollViewDidScroll to monitor scrollView scrolling and define an enumeration to record the scrolling direction

    typedef NS_ENUM(NSInteger, Direction) {
        DirectionNone = 1 << 0,
        DirectionLeft = 1 << 1,
        DirectionRight = 1 << 2
    };
    // 滚动方向
    @property (nonatomic, assign) Direction direction;
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView {
        CGFloat offX = scrollView.contentOffset.x;
        self.direction = offX > self.width ? DirectionLeft : offX < self.width ? DirectionRight : DirectionNone;
    }

Rewrite the setter method of direction to set the display of the next picture according to the scrolling direction. If it is scrolling to the left, the position of the next picture should be on the right, and if it is scrolling to the right, the position of the next picture should be on the left. (ps: here you should pay attention to the boundary conditions of scrolling to the first and last sheets )

    #pragma mark - 设置滚动方向
    - (void)setDirection:(Direction)direction {
        if (_direction == direction) return;
        _direction = direction;
        if (_direction == DirectionNone) return;
        if (_direction == DirectionRight) { // 如果是向右滚动
            self.nextImageView.frame = CGRectMake(0, 0, self.width, self.height);
            self.nextIndex = self.currentIndex - 1;
            if (self.nextIndex < 0) self.nextIndex = _images.count - 1;
        }else if (_direction == DirectionLeft){ // 如果是向左边滚动
            self.nextImageView.frame = CGRectMake(CGRectGetMaxX(_currentImageView.frame), 0, self.width, self.height);
            self.nextIndex = (self.currentIndex + 1) % _images.count;
        }
        self.nextImageView.image = self.images[self.nextIndex];
    }

The end of scrolling is monitored through the proxy method scrollViewDidEndDecelerating. After the end, it will become the following two situations:

  • After scrolling left

image 3

  • after scroll right

Figure 4

At this time, the offset of scrollView is 0 or 2x. We set the offset of scrollView to x again through the code, and modify the picture of nextImageView to the picture assigned to currentImageView

    - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
        [self pauseScroll];
    }
    - (void)pauseScroll {
        // 等于1表示没有滚动
        if (self.scrollView.contentOffset.x / self.width == 1) return;
        self.currentIndex = self.nextIndex;
        self.pageControl.currentPage = self.currentIndex;
        self.currentImageView.frame = CGRectMake(self.width, 0, self.width, self.height);
        self.descLabel.text = self.describeArray[self.currentIndex];
        self.currentImageView.image = self.nextImageView.image;
        self.scrollView.contentOffset = CGPointMake(self.width, 0);
    }

After this, we still see the currentImageView, but the picture shows the next picture or the previous picture, and it returns to the original appearance.

auto scroll

The function of carousel is realized, the next step is to add a timer to make it scroll automatically.

    // 开启定时器
    - (void)startTimer {
        // 如果只有一张,直接放回,不需要开启定时器
        if (_images.count <= 1) return;
        // 如果定时器已经开启,则先停止再开启
        if (self.timer) [self stopTimer];
        self.timer = [NSTimer timerWithTimeInterval:_time < 1 ? DEFAULTTIME : _time target:self selector:@selector(nextPage) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];
    }
    // 下一页
    - (void)nextPage {
        [self.scrollView setContentOffset:CGPointMake(self.width * 2, 0) animated:YES];
    }

Notice

After the setContentOffset:animated: method is executed, the scrollViewDidEndDecelerating method of the scrollview will not be called, but the scrollViewDidEndScrollingAnimation method will be called, so we need to call pauseScroll in this method

    - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
        [self pauseScroll];
    }

Stop timer while dragging

When we manually drag and drop, we need to stop the automatic scrolling. At this time, we only need to turn off the timer. When we end the dragging, restart the timer.

    - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
        [self stopTimer];
    }
    - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
        [self startTimer];
    }

load image

In actual development, we rarely rotate local pictures automatically, most of them are picture urls obtained by the server, and there may be both local pictures and network pictures, so how to load them?

  1. Define an imageArr to receive an array from the outside world (it can be a picture or a network picture path, you can mix pictures and paths)
  2. Define an images to store pictures (only pictures). Determine the array passed in from the outside world. If it is a picture, add it directly to images. If it is a connection, add a default placeholder image first.
  3. Define a dictionary used by imageDic to cache images, the key is the image URL
  4. Define a dictionary of operationDic used to save the download operation, the key is the image URL

Image caching strategy (the idea of ​​SDWebImage)

To download an image, first take it from the cache. If there is, replace the previous placeholder image. If not, take it from the sandbox. If there is, replace the placeholder image and add it to the cache. If not, open asynchronous thread download

Monitor image clicks

In actual development, usually the carousel image has the operation of clicking on the image to jump to the corresponding content, so it is necessary to monitor the click of the image, and provide two ideas:

  • by block:

    1. Define a block to the outside world
    2. User interaction to open currentImageView
    3. Add a tap gesture to currentImageView
    4. Call block in the click gesture response method and pass in the index where the image is located
  • Via proxy:

    1. Define a protocol method, set a proxy property
    2. User interaction to open currentImageView
    3. Add a tap gesture to currentImageView
    4. In the click gesture response method, use the proxy to call the protocol method,

concluding remarks

The above is the author's idea of ​​​​implementing the carousel map and part of the code. If you need the source code, please click here . If you find any bugs in use, please submit them! If you find it useful, don't forget to give your star!

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324860044&siteId=291194637