Two imageviews in iOS implement image scrolling,

Source: Internet
Author: User

Two imageviews in iOS implement image scrolling,

Author: codingZero

 

Introduction

In many projects, the image carousel function is available. The online image carousel frameworks are emerging one after another. Based on my own ideas, I have used two imageviews to achieve image carousel, let's talk about the author's main ideas and general steps. For the specific code, please refer to here. If you think it is easy to use, please present your star.

 

Advantages of this carousel framework:

 

Few files and concise code

Independent from any other third-party libraries, low coupling

Supports both local and network images

You can modify the position of the paging control to display or hide it.

The custom page control image is so personalized

Built-in image cache, one-time loading, permanent use

Good performance, low memory usage, smooth carousel

 

Actual use

Let's first look at the demo. The Code is as follows:


Running Effect

Carousel implementation steps

 

Next, I will analyze them one by one from various aspects.

 

Hierarchical Structure

The bottom layer is a UIView with UIScrollView and UIPageControl. Two uiimageviews are available on scrollView. imageView width and height = scrollview width and height = view width and height

Carousel Principle

Assuming that the width of the carousel control is x and the height is y, we set contentSize. width of scrollview to 3x, and set the horizontal offset of scrollview to x to display the most intermediate content.

ScrollView. contentSize = CGSizeMake (3x, y );

ScrollView. contentOffset = CGPointMake (x, 0 );


Add the imageView to the center of the scrollview content View


Next, use the proxy method scrollViewDidScroll to listen to scrollview scrolling and define an enumeration variable to record the scrolling direction.

Typedef enum {

DirecNone,

DirecLeft,

DirecRight

} Direction; @ property (nonatomic, assign) Direction direction;

-(Void) scrollViewDidScroll :( UIScrollView *) scrollView {self. direction = scrollView. contentOffset. x> x? DirecLeft: DirecRight;

}

 

Use KVO to listen for changes to the direction Attribute Value

 

[Self addObserver: self forKeyPath: @ "direction" options: NSKeyValueObservingOptionNew context: nil];

 

Determines the scroll direction. When the offset is greater than x, it indicates the Left shift, the otherImageView is added to the right. If the offset is less than x, it indicates the right shift. The otherImageView is added to the left.


-(Void) observeValueForKeyPath :( NSString *) keyPath ofObject :( id) object change :( NSDictionary *) change context :( void *) context {// self. currIndex indicates the index of the currently displayed image, self. nextIndex indicates the index of the image to be displayed.

// _ Images: Image array

If (change [NSKeyValueChangeNewKey] = change [NSKeyValueChangeOldKey]) return;

If ([change [NSKeyValueChangeNewKey] intValue] = DirecRight) {self. otherImageView. frame = CGRectMake (0, 0, self. width, self. height );

Self. nextIndex = self. currIndex-1;

If (self. nextIndex <0) self. nextIndex = _ images. count-1;

} Else if ([change [NSKeyValueChangeNewKey] intValue] = DirecLeft) {self. otherImageView. frame = CGRectMake (CGRectGetMaxX (_ currImageView. frame), 0, self. width, self. height );

Self. nextIndex = (self. currIndex + 1) % _ images. count;

}

Self. otherImageView. image = self. images [self. nextIndex];

}

 

The scrollViewDidEndDecelerating proxy method is used to listen for the rolling process. After the rolling process ends, the following two cases occur:

At this point, the scrollview offset is 0 or 2x. We can use the code to set the scrollview offset to x again, and change the image of currImageView to the image of otherImageView.

-(Void) scrollViewDidEndDecelerating :( UIScrollView *) scrollView {

[Self pauseScroll];

}

-(Void) pauseScroll {self. direction = DirecNone; // clear the scroll direction

// Determine whether to roll to the right or left

Int index = self. scrollView. contentOffset. x/x; if (index = 1) return; // if it is equal to 1, no scrolling is performed.

Self. currIndex = self. nextIndex; // The current image index changes.

Self. pageControl. currentPage = self. currIndex; self. currImageView. frame = CGRectMake (x, 0, x, y); self. currImageView. image = self. otherImageView. image; self. scrollView. contentOffset = CGPointMake (x, 0 );

}

 

So what we see is currImageView, which only shows the next image and becomes the initial effect.


Auto scroll

 

The carousel function is implemented. Next, add a timer to make it automatically scroll, which is quite simple.

-(Void) startTimer {// if there is only one image, the system returns directly without enabling the timer.

If (_ images. count <= 1) return; // if the timer has been enabled, stop and enable it again

If (self. timer) [self stopTimer]; self. timer = [NSTimer timerWithTimeInterval: self. time target: self selector: @ selector (nextPage) userInfo: nil repeats: YES];

[[Nsunloop currentRunLoop] addTimer: self. timer forMode: nsunloopcommonmodes];

}

-(Void) nextPage {// The animation can automatically scroll by changing the scrollview offset.

[Self. scrollView setContentOffset: CGPointMake (self. width * 2, 0) animated: YES];

}

 

Note: setContentOffset: animated: After the method is executed, the scrollViewDidEndDecelerating method of scrollview is not called, but scrollViewDidEndScrollingAnimation method is called. Therefore, pauseScroll is called in this method

-(Void) scrollViewDidEndScrollingAnimation :( UIScrollView *) scrollView {

[Self pauseScroll];

}

 

Stop Auto-scroll when dragging

 

When we manually drag an image, we need to stop auto-scroll. Now we only need to make the timer invalid. When we stop the drag, restart the timer.

-(Void) scrollViewWillBeginDragging :( UIScrollView *) scrollView {

[Self. timer invalidate];

}

-(Void) scrollViewDidEndDragging :( UIScrollView *) scrollView willDecelerate :( BOOL) decelerate {

[Self startTimer];

}

 

Attach Images

 

In actual development, we seldom carousel local images, most of which are obtained by servers, and may also have both local images and network images. How can we load them?

Define four attributes

  • NSArray imageArray: exposed in a. h file. The image or path array to be loaded is assigned to this attribute.

  • NSMutableArray images: array used to store images

  • NSMutableDictionary imageDic: The dictionary used to cache images. The key is URL.

  • NSMutableDictionary operationDic: The dictionary used to save the download operation. The key is the URL.

  • Determine whether the image or path is passed in from the outside world. If it is an image, directly add it to the Image array. If it is a path, add a placeholder image first, and then download the Image Based on the path.

_ Images = [NSMutableArray array]; for (int I = 0; I <imageArray. count; I ++) {if ([imageArray [I] isKindOfClass: [UIImage class]) {

[_ Images addObject: imageArray [I]; // Add the image directly to images

} Else if ([imageArray [I] isKindOfClass: [NSString class]) {

[_ Images addObject: [UIImage imageNamed: @ "placeholder"]; // if it is a path, add a placeholder image to images.

[Self downloadImages: I]; // download the network image

}

}

 

Download the image, first from the cache. If yes, replace the previous placeholder image. If no, remove it from the sandbox. If yes, replace the placeholder image, and add it to the cache. If not, enable asynchronous thread download.

-(Void) downloadImages :( int) index {NSString * key = _ imageArray [index]; // retrieves an image from the dictionary Cache

UIImage * image = [self. imageDic objectForKey: key]; if (image ){

_ Images [index] = image; // If an image exists, replace the previous placeholder image.

} Else {// no image is retrieved from the sandbox in the dictionary

NSString * cache = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString * path = [cache Duration: [key lastPathComponent]; NSData * data = [NSData dataWithContentsOfFile: path]; if (data) {// in the sandbox, replace the placeholder image and add it to the dictionary cache.

Image = [UIImage imageWithData: data];

_ Images [index] = image;

[Self. imageDic setObject: image forKey: key];

} Else {// No dictionary sandbox. Download the image.

NSBlockOperation * download = [self. operationDic objectForKey: key]; // check whether the download operation exists

If (! Download) {// does not exist

// Create a queue, which is a concurrent queue by default

NSOperationQueue * queue = [[NSOperationQueue alloc] init]; // create a download operation

Download = [NSBlockOperation blockOperationWithBlock: ^ {NSURL * url = [NSURL URLWithString: key]; NSData * data = [NSData dataWithContentsOfURL: url]; if (data) {// After the download is complete, replace the placeholder image, store it in the dictionary, write it into the sandbox, and remove the download operation from the dictionary.

UIImage * image = [UIImage imageWithData: data];

[Self. imageDic setObject: image forKey: key]; self. images [index] = image; // if there is only one image, you must manually modify the value of currImageView in the main thread.

If (_ images. count = 1) [_ currImageView initialize mselecw.mainthread: @ selector (setImage :) withObject: image waitUntilDone: NO];

[Data writeToFile: path atomically: YES];

[Self. operationDic removeObjectForKey: key];

}

}];

[Queue addOperation: download];

[Self. operationDic setObject: download forKey: key]; // adds the download operation to the dictionary.

}

}

}

}

 

Listen to image clicks

 

When an image is clicked, we often need to perform some operations, so we need to listen to the image clicking, the idea is as follows:

  1. Define a block attribute to be exposed to external void (^ imageClickBlock) (NSInteger index)

  2. Set the userInteractionEnabled of currImageView to YES.

  3. Add a click gesture to currImageView

  4. Call block in the gesture method and input the image Index

 

Conclusion

The above is the author's main idea and part of the code, please go to the author's

Github download:
Https://github.com/codingZero/XRCarouselView

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.