Making picture carousel with uiscrollview

Time:2020-11-28

Uiscrollview picture carousel nstimer

I hope you can open your mobile phone anytime and anywhere to learn knowledge. Remember the sentence of the class!
Posture has never been so sexy! Learning has never been so happy! My name is hank!!

How to use uiscrollview

  • Create uiscrollview

  • Add child controls to uiscrollview

  • Set the contentsize of uiscrollview

Several situations in which uiscrollview cannot scroll

  • Contentsize is not set

  • scrollEnabled = NO

  • userInteractionEnabled = NO

Attention point: userinteractionenabled is not disabled. There are essential differences between them
Disabled means that the control cannot be used. The state is disabled
Userinteractionenabled represents whether the control can interact
Note:In enterprise development, never use subviews to get child controls in uiscrollview
Because the scrollbars in uiscrollview are included in subviews, and the order of the scrollbars is uncertain
Common properties of uiscrollview

bounces: used to set whether the uiscrollview has rebound effect

alwaysBounceVertical/alwaysBounceHorizontal

If the content size has been set in uiscrollview, there is no difference between yes and no (if there is no setting, the picture will not move at all)
Only uiscrollview does not set contentsize

Application scenarios: drop down refresh
Indicator style: sets the style of the scroll bar

showsHorizontalScrollIndicator/showsVerticalScrollIndicator

Yes show scroll bar / no hide scroll bar

//Is there a spring effect
self.scrollView.bounces = NO;
//With or without contentsize, it can have spring effect (generally applicable to pull-down refresh function and pull-up refresh function)
self.scrollView.alwaysBounceVertical = YES;  
self.scrollView.alwaysBounceHorizontal = YES;
//Do you want to display the scroll bar
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.showsVerticalScrollIndicator = NO;
  • Properties:contentOffset
    It is the distance that the visible content needs to move relative to the top left corner of the content

  • Function: used to set the scrolling offset of content
    Calculation formula: distance moved = “top left corner of control” – “top left corner of content”

Content control = top left corner of control – distance to move
It’s best to understand the IOS coordinate system first, and then understand the formula

Setcontentoffset: < # (cgpoint) ා > Animated: < # (bool) # > // with animation
  • attributecontentInset(added a little more border to add extra range)

  • Function: add extra scrolling area around contentsize

  • Application scenario: avoid the content in uiscrollview from being obscured

Note that if the Scrollview is not created through storyboard or Xib, there are no child controls in the first subviews

How to listen to a control

First of all, you need to view the header file of the control to see who it inherits from. If it inherits from uicontrol, you can listen through addtarget. If it does not inherit from uicontrol, you must listen through proxy

agent

  • To use a proxy:

    • Compliance with agency agreement

    • Implement proxy method

    • Set a protocol compliant object as a proxy

  • The law of agency:

    • The law of agency name:
      The protocol name begins with the class name, followed by delegate

    • The law of proxy method name
      The method name begins with the class name without the prefix, and is passed to whoever triggers the method

    • The proxy property is usually ID

The proxy property is weak, which is mainly used to avoid circular reference. Generally, the proxy of a control is a controller, and the control is added to the view of the controller

Application scenarios of agents

1. When object a wants to listen to the change of object B, you can use proxy to make a agent of B
2. When object B wants to notify object a, you can use proxy to make a proxy of B

How to listen to uiscrollview to stop scrolling

@property(nonatomic,assign) id<UIScrollViewDelegate>      
Delegate; // the proxy property of default nil. Weak reference Scrollview needs to comply with the uiscrollviewdelegate protocol
@interface ViewController ()  <UIScrollViewDelegate>
@End // generally, it is best to write the protocol in the anonymous class in. M
self.scorllView.delegate = self//ViewController


//scrollViewDidEndDragging
//As long as the user releases the hand, it will call to stop dragging, which does not mean that the scrolling will stop. That is to say, the uiscrollview scrolling is inertial
-(void) scrollviewdidenddragging: (uiscrollview *) Scrollview willdecelerate: (bool) decelerate{
 //1. Judge whether there is inertia. If there is no inertia, manually call scrollviewdidenddecelerating to inform that scrolling has been completely stopped
   if (decelerate == NO) {
        [self scrollViewDidEndDecelerating:scrollView];
    }
 }

Scrollviewdidenddecelerating
Uiscrollview will be called as long as it has inertia. If there is no inertia, it will not be called

To listen to uiscrollview to stop scrolling, you must implement both methods at the same time
Called whenever uiscrollview is about to start dragging

//Called when the uiscrollview Scrolls (the call frequency is very high, and it will be called once if you scroll once)
 1. (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
 2. (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
 3. (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
    NSLog(@"%s = %d", __func__, decelerate);  
    //1. Judge whether there is inertia. If there is no inertia, manually call scrollviewdidenddecelerating to inform that scrolling has been completely stopped
    if (decelerate == NO) {
        [self scrollViewDidEndDecelerating:scrollView];
    }
}

 4. (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    NSLog(@"%s", __func__);
    Nslog (@ "stop scrolling");

    self.iv.alpha = 1.0;
}

Uiscrollview zoom

Steps:

  1. Become a proxy for uiscrolview and tell uiscrolview which child control to scale through the proxy method
    < uiscrollviewdelegate > sets the maximum and minimum scaling of child controls

be careful

As long as the child control is reduced, the contentsize will also change. If there is no scaling, the scaling ratio may not be set, or the proxy common method is not set

Viewforzoominginscrollview: returns the child control that needs to be scaled
Scrollviewdidzoom: called whenever a child control is scaled (very frequently)
Scrollviewdidendzooming: drop when zooming is finished
How to ensure that the zoomed child controls are always centered

You need to scale as long as the contentsize of the child control is less than the width of the uiscrollview

The first one

//1. Judge whether the width and height of contentsize is smaller than the size of frame of uiscrollview
if (scrollView.contentSize.width < scrollView.bounds.size.width) {

self.iv1.center = CGPointMake(scrollView.bounds.size.width * 0.5, scrollView.bounds.size.height * 0.5); }
    if (scrollView.contentSize.height < scrollView.bounds.size.height) {
        self.iv1.center = CGPointMake(scrollView.bounds.size.width * 0.5, scrollView.bounds.size.height * 0.5);
    }    

The second kind

//1. Judge whether the width and height of contentsize is smaller than the size of frame of uiscrollview
if (scrollView.contentSize.width < scrollView.bounds.size.width) {        
        //Calculate the value of X
        CGFloat x =  (scrollView.contentSize.width * 0.5) + ((scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5);        
        //Reset Center
        self.iv1.center = CGPointMake(x, self.iv1.center.y);
}    
if (scrollView.contentSize.height < scrollView.bounds.size.height) {        
        //Calculate the value of Y
        CGFloat y =  (scrollView.contentSize.height * 0.5) + ((scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5);        
        //Reset Center
        self.iv1.center = CGPointMake(self.iv1.center.x, y);
    }

The third kind

CGFloat x = scrollView.contentSize.width < scrollView.bounds.size.width ? (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;

CGFloat y = scrollView.contentSize.height < scrollView.bounds.size.height ? (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;

self.iv1.center = CGPointMake(scrollView.contentSize.width * 0.5 + x, scrollView.contentSize.height * 0.5 + y);

Picture carousel

  • How to paginate: pagingenabled = yes

  • Pagination principle: paging is based on the width or height of the uiscrollview
    UIPageControl

  • Numberofpages: set the total page number CurrentPage: set the current page pageindextintcolor:
    Set the color of other page numbers currentpageindicator tintcolor: set the color of the current page number and customize the page number

Using KVC to set page number picture for uipagecontrol

    [pageControl setValue:[UIImage imageNamed:@"current"] forKeyPath:@"_currentPageImage"];

    [pageControl setValue:[UIImage imageNamed:@"other"] forKeyPath:@"_pageImage"];

Listen for uipagecontrol Click
Since uipagecontrol inherits from uicontrol, it listens through addtargt

[pageControl addTarget:self action:@selector(nextPage) forControlEvents:UIControlEventValueChanged];

Switch page number

Switch after scrolling

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{    
//Determine whether there is inertia. If not, manually call scrollviewdidenddecelerating
    if (NO == decelerate) {
    [self scrollViewDidEndDecelerating:scrollView];
    }
}
//It will only be called if there is inertia
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
    //1. Dynamically calculate the current page number
//Page number = offset of uiscrollview / width of uiscrollview
    int page = scrollView.contentOffset.x / scrollView.bounds.size.width;
    NSLog(@"page = %d", page);
    //2. Set the current page number
    self.pageControl.currentPage = page;
}
 Real time switching
//As long as you scroll, it is called
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
//    NSLog(@"%s", __func__);
//1. Dynamically calculate the current page number
//Page number = offset of uiscrollview / width of uiscrollview

    CGFloat page = scrollView.contentOffset.x / scrollView.bounds.size.width;   

    NSLog(@"page = %f", page + 0.5);
    //2. Set the current page number
    self.pageControl.currentPage = (int)(page + 0.5);
}

NSTimer

effect: allows the system to execute the specified method of the specified object at regular intervals
be careful:

The interval time is not accurate. As long as timers created through scheduledtimerwithtimeinterval are strongly referenced by runloop,
Therefore, if you use weak through attribute saving, as long as the validate method of nstimer is called, the timer cannot be used. If you want to use it, you must create it again
If the main thread is processing other operations, nstimer will not execute. The default nstimer is nsdefaultrunloopmode
To handle nstimer when the main thread is processing other operations,
Then the mode of nstiemr in runloop must be changed to nsrunloop common modes

How to pause and start timer

@property (nonatomic, weak) NSTimer *timer;
//Pause timer
 [self.timer setFireDate:[NSDate distantFuture]];

//Set timer start time to distant future 4001
//    NSLog(@"%@", [NSDate distantFuture]);

Turn on the timer

//Setting the timer start time to a certain time in the past means starting immediately
//    [self.timer setFireDate:[NSDate distantPast]];
//Set the timer to execute two seconds after the current time
[self.timer setFireDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
//Returns a timer that automatically starts executing tasks
self.timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(nextPage:) userInfo:@"123" repeats:YES];

//Modify the mode of nstimer in nsrunloop: nsrunloop commonmodes
//No matter what operation the main thread is processing, it will take time to process nstimer
[[NSRunLoop mainRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

off timer

[self.timer invalidate];

encapsulation

As long as the controller is found to know too much, it is necessary to consider refactoring the code. As long as an effect is found to be used in many places, encapsulation should be considered

Set the background color. If it is not displayed in storyboard, it will be displayed when running
Three steps to monitor the behavior of Scrollview (for example, let the controller monitor the behavior of Scrollview)

Set to the delegate object
scrollView.delegate =Controller;
The controller shall comply with the uiscrollviewdelegate protocol

@Interface controller () < uiscrollviewdelegate > 
@end

The controller should implement the proxy method in the uiscrollviewdelegate protocol

#pragma mark - <UIScrollViewDelegate>

Proxy method

/**This method is called whenever the Scrollview is scrolling (listening for Scrollview scrolling)*/
 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    NSLog(@"scrollViewDidScroll");
}

The general law of agent use

  • Function: used to monitor some behavior agents of control: controller object agent: ID type and weak pointer

  • Proxy protocol format: control class name delegate, such as uiscrollviewdelegate, uitextfielddelegate

  • Proxy method: the method name usually starts with the control name. For example, the proxy method of uiscrollview usually starts with Scrollview

How to monitor the behavior of a control

Through addtarget:

UITextField *tf = [[UITextField alloc] init];

[tf adction:@selector(textChange:) forControlEvents:UIControlEventEditingChanged] ;

- (void)textChange:(UITextField *)tf
{
    NSLog(@"textChange- %@", tf.text);
}

Only controls inherited from uicontrol have this function

Uicontrol eventtouchupinside /: click event (uibutton)
Uicontroleventvaluechanged /: value change event (uiswitch, uisegmentcontrol, uislider)
Uicontroleventeditingchanged /: uitextfield

Through delegate, only the control with the delegate property has this function