Thanks to Uikit's coordinate system features, so that we spent 30 lines of code can reproduce the essence of uiscrollview, of course, the real uiscrollview than we do more complex, rebound effect, momentum rolling, amplification attempts, there are proxy methods, These features we are not involved in here.
First, let's take a look at how the coordinate systems in uikit work. If you are interested only in the code implementation of the scrolling attempt, you can safely skip the next section. Uikit coordinates each view defines his own coordinate system. As the following illustration shows, the x-axis points to the right and the y-axis points below:
Note that this logical coordinate system does not focus on the width and height of the view contained therein. The entire coordinate system has no boundary extending to the perimeter. We place four child view in the coordinate system. Each time the color block represents a view:
The code to add a view is implemented as follows:
UIView *redview = [[UIView alloc] Initwithframe:cgrectmake (20, 20, 100, 100)];
Redview.backgroundcolor = [Uicolor colorwithred:0.815 green:0.007
blue:0.105 Alpha:1];
UIView *greenview = [[UIView alloc] Initwithframe:cgrectmake (150, 160, 150, 200)];
Greenview.backgroundcolor = [Uicolor colorwithred:0.494 green:0.827
blue:0.129 Alpha:1];
UIView *blueview = [[UIView alloc] Initwithframe:cgrectmake (40, 400, 200, 150)];
Blueview.backgroundcolor = [Uicolor colorwithred:0.29 green:0.564
blue:0.886 Alpha:1];
UIView *yellowview = [[UIView alloc] Initwithframe:cgrectmake (100, 600, 180, 150)];
Yellowview.backgroundcolor = [Uicolor colorwithred:0.972 green:0.905
blue:0.109 Alpha:1];
[Mainview Addsubview:redview];
[Mainview Addsubview:greenview];
[Mainview Addsubview:blueview];
[Mainview Addsubview:yellowview];
Bounds
The bounds attribute is described in the Apple documentation for UIView:
Bounds rectangle ... Describes the position and size of the view in its own coordinate system.
A view can be viewed as a window or a visible area of a rectangle that is defined on the plane of the coordinate system. The view boundary indicates the position and size of the viewable region of the rectangle.
Suppose our view is 320 pixels wide and 480 pixels high, the origin is in (0,0). So this view becomes the observation port of the whole coordinate plane, and it shows only a small portion of the whole plane. The area outside the view boundary is still there, but it is hidden.
A view provides an observation port on the plane in which it is located. The bounds rectangle of the view describes the location and size of the area.
Frame
Next, we'll try to modify the origin coordinates of the bounds:
CGRect bounds = mainview.bounds;
Bounds.origin = Cgpointmake (0, 100);
Mainview.bounds = bounds;
When we set the bound origin to (0,100), the whole picture looks like this:
Modifying the origin of the bounds is equivalent to moving the visible region on the plane.
It looks like this view is moving down 100 pixels, which is true in the view's own coordinate system. But the position of this view, which is actually on the screen (more accurately in its parent view), has not changed because it is determined by the view's Frame property, and it does not change:
Frame Rectangle ... Defines the position and size of this view in its parent view coordinate system.
Because the position of the view is relatively fixed, you can think of the entire plane as a transparent screen that we can drag up and down, and visualize this view as the window in which we look at the coordinate plane. Adjusting the Bounds property of the view is equivalent to dragging the screen, so the bottom content can be observed in our view:
Modifying the origin coordinates of the bounds is also equivalent to dragging the entire coordinate system up, because the view frame is not changed, so it does not change its position relative to the parent view.
This is actually what happens when Uiscrollview slides. Note from a user's point of view, he thought that the view of the child view is moving, in fact their position in the coordinate system (their frame) has not changed.
Build your Uiscrollview.
A scroll view does not need the coordinates of the child view to make them scroll. The only thing to do is to change his bounds attributes. Knowing this, achieving a simple scroll view is no problem. We use a gesture recognizer to identify the user's drag operation, which changes the origin of the bounds according to the offset that the user drags:
CustomScrollView.h
@import Uikit;
@interface Customscrollview:uiview
@property (nonatomic) cgsize contentsize;
@end
customscrollview.m
#import "CustomScrollView.h"
@implementation Customscrollview
-(ID) initWithFrame: (CGRect) frame
{
self = [super Initwithframe:frame];
if (self = = nil) {
return nil;
}
Uipangesturerecognizer *gesturerecognizer = [[Uipangesturerecognizer alloc]
Initwithtarget:self Action: @selector (handlepangesture:)];
[Self addgesturerecognizer:gesturerecognizer];
return self;
}
-(void) Handlepangesture: (Uipangesturerecognizer *) Gesturerecognizer
{
Cgpoint translation = [Gesturerecognizer translationinview:self];
CGRect bounds = self.bounds;
Translate The view ' s bounds, but does not permit values that would violate contentsize
CGFloat Newboundsoriginx = bounds.origin.x-translation.x;
CGFloat Minboundsoriginx = 0.0;
CGFloat Maxboundsoriginx = self.contentsize.width-bounds.size.width;
bounds.origin.x = Fmax (Minboundsoriginx, Fmin (Newboundsoriginx, Maxboundsoriginx));
CGFloat newboundsoriginy = BOUNDS.ORIGIN.Y-TRANSLATION.Y;
CGFloat minboundsoriginy = 0.0;
CGFloat maxboundsoriginy = self.contentsize.height-bounds.size.height;
BOUNDS.ORIGIN.Y = Fmax (Minboundsoriginy, Fmin (Newboundsoriginy, maxboundsoriginy));
Self.bounds = bounds;
[Gesturerecognizer Settranslation:cgpointzero inview:self];
}
@end
Like the real Uiscrollview, our class also has a contentsize attribute, you have to set this value from the outside to specify the area that can be scrolled, and when we change the size of the bounds we want to make sure that the value is valid.
Results:
Uiscrollview Common Operation Method Finishing
-(void) viewdidload
{
[Super Viewdidload];
Do no additional setup after loading the view.
Create a scrolling view
Self.scrollview = [[Uiscrollview alloc] Initwithframe:cgrectmake (0, 64, 320, 568-64)];
Set up agents
Self.scrollView.delegate = self;
Self.scrollView.backgroundColor = [Uicolor Redcolor];
[Self.view Addsubview:_scrollview];
/**
* Cgpoint Contentoffset Monitor the current scrolling position
* Cgsize contentsize Scrolling Range size (main property)
* Uiedgeinsets the position of Contentinset view in ScrollView
* BOOL directionallockenabled Specifies whether the control can scroll only in one Direction
* BOOL bounces control controls encounter border bounce
* BOOL alwaysbouncevertical Control vertical direction to see if the border bounces
* BOOL Alwaysbouncehorizontal Control horizontal direction encountered border rebound
* BOOL pagingenabled Control whether the control is full page flip
* BOOL scrollenabled Control whether the control can scroll
* BOOL Showshorizontalscrollindicator Control whether the scroll bar is displayed in horizontal direction
* BOOL Showsverticalscrollindicator Control whether the vertical scroll bar is displayed
* Uiedgeinsets scrollindicatorinsets Specifies the position of the scroll bar in the Scrollerview
* Uiscrollviewindicatorstyle Indicatorstyle Set the style of the scroll bar
* Float decelerationrate Change the scrollerview position of the deceleration point
* BOOL Tracking Monitor If current target is being tracked
* BOOL dragging Monitor if the current target is being dragged
* BOOL decelerating Monitor If current target is slowing down
* BOOL Delayscontenttouches Control whether the view is delayed call method to start scrolling
* BOOL cancancelcontenttouches Controls whether controls contact the Cancel touch event
* Float Minimumzoomscale minimum ratio of scaling
* Float Maximumzoomscale maximum ratio of scaling
* Float Zoomscale Set Change ratio
* BOOL Bounceszoom to control whether the zoom will bounce
* BOOL zooming determines whether the control is changing in size
* BOOL zoombouncing to determine if a scaling rebound is in progress
* BOOL scrollstotop Control control scroll to the top
*/
Prompts the user that when the interface is created, a horizontal scroll bar or vertical scroll bar will appear with a flash effect
[Self.scrollview flashscrollindicators];
Offset driven drawing effect
[Self.scrollview setcontentoffset:cgpointmake (0) Animated:yes];
}
#pragma Mark Uiscrollviewdelegate.
As soon as it rolls, it triggers.
-(void) Scrollviewdidscroll: (Uiscrollview *) ScrollView;
{
}
Start dragging views
Executes the method when you start scrolling the view. One effective slide (start sliding, slide a small distance, as long as the fingers do not release, only one slide), only once.
-(void) scrollviewwillbegindragging: (Uiscrollview *) ScrollView;
{
}
Slide the view, and when the finger leaves the screen that moment, call the method. Slide effectively once, only once.
Decelerate, refer to, when our fingers leave that moment, the view will continue to roll forward (a distance), after testing, Decelerate=yes
-(void) scrollviewdidenddragging: (Uiscrollview *) ScrollView willdecelerate: (BOOL) decelerate;
{
}
When you start to spin down
-(void) scrollviewwillbegindecelerating: (Uiscrollview *) ScrollView;
{
}
The scrolling view slows completion and the method is called when scrolling stops. Slide effectively once, only once.
-(void) scrollviewdidenddecelerating: (Uiscrollview *) ScrollView;
{
}
Scrolling animation when it stops executing, when the code changes, when Setcontentoffset changes
When the scrolling view animation completes, the method is called, and if there is no animation, the method is not invoked
-(void) Scrollviewdidendscrollinganimation: (Uiscrollview *) ScrollView;
{
}
Sets the enlarged view, and returns the UIView object that will be scaled if the Uiscrollview is Subview. To perform multiple
-(UIView *) Viewforzoominginscrollview: (Uiscrollview *) ScrollView;
{
return nil;
}
Executes the method when scaling is about to begin. A valid zoom is performed once.
-(void) scrollviewwillbeginzooming: (Uiscrollview *) ScrollView Withview: (UIView *) view
{
NSLog (@ "scrollviewwillbeginzooming");
}
This method is invoked when the zoom is finished and the indent is small back to Minimumzoomscale and Maximumzoomscale (we may be out of range).
-(void) scrollviewdidendzooming: (Uiscrollview *) ScrollView Withview: (UIView *) View Atscale: (double) scale;
{
}
If you are not completely scrolling to the top of the roller view, you can light the status bar, and the visual roller view will scroll up to the top, which is the default behavior that you can use to return no to close it
-(BOOL) Scrollviewshouldscrolltotop: (Uiscrollview *) ScrollView;
{
return YES;
}
Has slipped to the top
-(void) Scrollviewdidscrolltotop: (Uiscrollview *) ScrollView;
{
}