GithubHelp home page GithubHelp logo

nicklockwood / swipeview Goto Github PK

View Code? Open in Web Editor NEW
2.6K 79.0 415.0 839 KB

SwipeView is a class designed to simplify the implementation of horizontal, paged scrolling views on iOS. It is based on a UIScrollView, but adds convenient functionality such as a UITableView-style dataSource/delegate interface for loading views dynamically, and efficient view loading, unloading and recycling.

License: Other

Objective-C 98.62% Ruby 1.38%

swipeview's Introduction

Purpose

SwipeView is a class designed to simplify the implementation of horizontal, paged scrolling views on iOS. It is based on a UIScrollView, but adds convenient functionality such as a UITableView-style dataSource/delegate interface for loading views dynamically, and efficient view loading, unloading and recycling.

SwipeView's interface and implementation is based on the iCarousel library, and should be familiar to anyone who has used iCarousel.

Supported OS & SDK Versions

  • Supported build target - iOS 7.0 (Xcode 5.0, Apple LLVM compiler 5.0)
  • Earliest supported deployment target - iOS 5.0
  • Earliest compatible deployment target - iOS 4.3

NOTE: 'Supported' means that the library has been tested with this version. 'Compatible' means that the library should work on this OS version (i.e. it doesn't rely on any unavailable SDK features) but is no longer being tested for compatibility and may require tweaking or bug fixes to run correctly.

ARC Compatibility

As of version 1.3, SwipeView requires ARC. If you wish to use SwipeView in a non-ARC project, just add the -fobjc-arc compiler flag to the SwipeView.m class. To do this, go to the Build Phases tab in your target settings, open the Compile Sources group, double-click SwipeView.m in the list and type -fobjc-arc into the popover.

If you wish to convert your whole project to ARC, comment out the #error line in SwipeView.m, then run the Edit > Refactor > Convert to Objective-C ARC... tool in Xcode and make sure all files that you wish to use ARC for (including SwipeView.m) are checked.

Thread Safety

SwipeView is derived from UIView and - as with all UIKit components - it should only be accessed from the main thread. You may wish to use threads for loading or updating SwipeView contents or items, but always ensure that once your content has loaded, you switch back to the main thread before updating the SwipeView.

Examples

Controls Example

controls

Paging Example

paging

Installation

To use the SwipeView class in an app, just drag the SwipeView class files (demo files and assets are not needed) into your project.

Properties

The SwipeView has the following properties:

@property (nonatomic, weak) IBOutlet id<SwipeViewDataSource> dataSource;

An object that supports the SwipeViewDataSource protocol and can provide views to populate the SwipeView.

@property (nonatomic, weak) IBOutlet id<SwipeViewDelegate> delegate;

An object that supports the SwipeViewDelegate protocol and can respond to SwipeView events and layout requests.

@property (nonatomic, readonly) NSInteger numberOfItems;

The number of items in the SwipeView (read only). To set this, implement the numberOfItemsInSwipeView: dataSource method. Note that not all of these item views will be loaded or visible at a given point in time - the SwipeView loads item views on demand as it scrolls.

@property (nonatomic, readonly) NSInteger numberOfPages;

The number of pages in the SwipeView (read only). To set this, implement the numberOfItemsInSwipeView: dataSource method and set the itemsPerPage value. If itemsPerPage = 1, numberOfPages will match the numberOfItems.

@property (nonatomic, readonly) CGSize itemSize;

The size of each item in the SwipeView. This property is read-only, but can be set using the swipeViewItemSize: delegate method.

@property (nonatomic, assign) NSInteger itemsPerPage;

The number of items per page when paging is enabled. Defaults to one;

@property (nonatomic, assign) BOOL truncateFinalPage;

If the number of items is not exactly divisible by the itemsPerPage value then it can result in blank space on the last page. By setting truncateFinalPage to YES, you can eliminate that space.

@property (nonatomic, strong, readonly) NSArray *indexesForVisibleItems;

An array containing the indexes of all item views currently loaded and visible in the SwipeView. The array contains NSNumber objects whose integer values match the indexes of the views. The indexes for item views start at zero and match the indexes passed to the dataSource to load the view.

@property (nonatomic, strong, readonly) NSArray *visibleItemViews;

An array of all the item views currently displayed in the SwipeView (read only). The indexes of views in this array do not match the item indexes, however the order of these views matches the order of the visibleItemIndexes array property, i.e. you can get the item index of a given view in this array by retrieving the equivalent object from the visibleItemIndexes array (or, you can just use the indexOfItemView: method, which is much easier).

@property (nonatomic, strong, readonly) UIView *currentItemView;

The first item view of the currently centered (or left-aligned, depending on the alignment value) page.

@property (nonatomic, readonly) NSInteger currentItemIndex;

The index of the first item of the currently centered (or left-aligned, depending on the alignment value) page. Setting this value is equivalent to calling scrollToItemAtIndex:duration: with the duration argument set to 0.0.

@property (nonatomic, assign) NSInteger currentPage;

The index of the currently centered (or left-aligned, depending on the alignment value) page. If itemsPerPage is equal to one, this value will match the currentItemIndex value. Setting this value is value is equivalent to calling scrollToPage:duration: with the duration argument set to 0.0.

@property (nonatomic, assign) SwipeViewAlignment alignment;

This property controls how the SwipeView items are aligned. The default value of SwipeViewAlignmentEdge means that the item views will extend to the edges of the SwipeView. Switching the alignment to SwipeViewAlignmentCenter means that the leftmost and rightmost item views will be centered when the SwipeView is fully scrolled to either extreme.

@property (nonatomic, assign, getter = isPagingEnabled) BOOL pagingEnabled;

Enables and disables paging. When paging is enabled, the SwipeView will stop at each item view as the user scrolls.

@property (nonatomic, assign, getter = isScrollEnabled) BOOL scrollEnabled;

Enables and disables user scrolling of the SwipeView. The SwipeView can still be scrolled programmatically if this property is set to NO.

@property (nonatomic, assign, getter = isWrapEnabled) BOOL wrapEnabled;

Enables and disables wrapping. When in wrapped mode, the SwipeView can be scrolled indefinitely and will wrap around to the first item view when it reaches past the last item. When wrap is enabled, the bounces property has no effect.

@property (nonatomic, assign, getter = isVertical) BOOL vertical;

This property toggles whether the SwipeView is displayed horizontally or vertically on screen.

@property (nonatomic, assign) BOOL delaysContentTouches;

This property works like the equivalent property of UIScrollView. It defers handling of touch events on subviews within the SwipeView so that embedded controls such as buttons do not interfere with the smooth scrolling of the SwipeView. Defaults to YES.

@property (nonatomic, assign) BOOL bounces;

Sets whether the SwipeView should bounce past the end and return, or stop dead.

@property (nonatomic, assign) float decelerationRate;

A floating-point value that determines the rate of deceleration after the user lifts their finger.

@property (nonatomic, readonly, getter = isDragging) BOOL dragging;

Returns YES if user has started scrolling the SwipeView and has not yet released it.

@property (nonatomic, readonly, getter = isDecelerating) BOOL decelerating;

Returns YES if the user isn't dragging the SwipeView any more, but it is still moving.

@property (nonatomic, readonly, getter = isScrolling) BOOL scrolling;

Returns YES if the SwipeView is currently being scrolled programatically.

@property (nonatomic, assign) BOOL defersItemViewLoading;

Sometimes when your SwipeView contains very complex item views, or large images, there can be a noticeable jerk in scrolling performance as it loads the new views. Setting the defersItemViewLoading property to YES forces the SwipeView to defer updating the currentItemIndex property and loading of new item views until after the scroll has finished. This can result in visible gaps in the SwipeView if you scroll too far in one go, but for scrolling short distances you may find that this improves animation performance.

@property (nonatomic, assign) CGFloat autoscroll;

This property can be used to set the SwipeView scrolling at a constant speed. A value of 1.0 would scroll the SwipeView forwards at a rate of one item per second. The autoscroll value can be positive or negative and defaults to 0.0 (stationary). Autoscrolling will stop if the user interacts with the SwipeView, and will resume when they stop.

Methods

The SwipeView class has the following methods:

- (void)reloadData;

This reloads all SwipeView item views from the dataSource and refreshes the display. Note that reloadData will reset the currentItemIndex back to zero, so if you want to retain the current scroll position, make a note of currentItemIndex before reloading and restore it afterwards. If you just wish to refresh the visible items without changing the number of items, consider calling reloadItemAtIndex: on all visible items instead.

- (void)reloadItemAtIndex:(NSInteger)index;

This method will reload the specified item view. The new item will be requested from the dataSource. Off-screen views will not be reloaded.

- (void)scrollByNumberOfItems:(NSInteger)itemCount duration:(NSTimeInterval)duration;

This method allows you to scroll the SwipeView by a fixed distance, measured in item widths. Positive or negative values may be specified for itemCount, depending on the direction you wish to scroll. SwipeView gracefully handles bounds issues, so if you specify a distance greater than the number of items in the SwipeView, scrolling will be clamped when it reaches the end of the SwipeView.

- (void)scrollToItemAtIndex:(NSInteger)index duration:(NSTimeInterval)duration;

This will center the SwipeView on the specified item, either immediately or with a smooth animation.

- (void)scrollToPage:(NSInteger)page duration:(NSTimeInterval)duration;

This will center the SwipeView on the specified item, either immediately or with a smooth animation.

- (UIView *)itemViewAtIndex:(NSInteger)index;

Returns the visible item view with the specified index. Note that the index relates to the position in the SwipeView, and not the position in the visibleItemViews array, which may be different. The method only works for visible item views and will return nil if the view at the specified index has not been loaded, or if the index is out of bounds.

- (NSInteger)indexOfItemView:(UIView *)view;

The index for a given item view in the SwipeView. This method only works for visible item views and will return NSNotFound for views that are not currently loaded. For a list of all currently loaded views, use the visibleItemViews property.

- (NSInteger)indexOfItemViewOrSubview:(UIView *)view

This method gives you the item index of either the view passed or the view containing the view passed as a parameter. It works by walking up the view hierarchy starting with the view passed until it finds an item view and returns its index within the SwipeView. If no currently-loaded item view is found, it returns NSNotFound. This method is extremely useful for handling events on controls embedded within an item view. This allows you to bind all your item controls to a single action method on your view controller, and then work out which item the control that triggered the action was related to.

Protocols

The SwipeView follows the Apple convention for data-driven views by providing two protocol interfaces, SwipeViewDataSource and SwipeViewDelegate. The SwipeViewDataSource protocol has the following required methods:

- (NSInteger)numberOfItemsInSwipeView:(SwipeView *)swipeView;

Return the number of items (views) in the SwipeView.

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view;

Return a view to be displayed at the specified index in the SwipeView. The reusingView argument works like a UIPickerView, where views that have previously been displayed in the SwipeView are passed back to the method to be recycled. If this argument is not nil, you can set its properties and return it instead of creating a new view instance, which will slightly improve performance. Unlike UITableView, there is no reuseIdentifier for distinguishing between different SwipeView view types, so if your SwipeView contains multiple different view types then you should just ignore this parameter and return a new view each time the method is called. You should ensure that each time the swipeView:viewForItemAtIndex:reusingView: method is called, it either returns the reusingView or a brand new view instance rather than maintaining your own pool of recyclable views, as returning multiple copies of the same view for different SwipeView item indexes may cause display issues with the SwipeView.

The SwipeViewDelegate protocol has the following optional methods:

- (CGSize)swipeViewItemSize:(SwipeView *)swipeView;

Returns the size in points/pixels of each item view. If this method is not implemented, the item size is automatically calculated from the first item view that is loaded.

- (void)swipeViewDidScroll:(SwipeView *)swipeView;

This method is called whenever the SwipeView is scrolled. It is called regardless of whether the SwipeView was scrolled programatically or through user interaction.

- (void)swipeViewCurrentItemIndexDidChange:(SwipeView *)swipeView;

This method is called whenever the SwipeView scrolls far enough for the currentItemIndex property to change. It is called regardless of whether the item index was updated programatically or through user interaction.

- (void)swipeViewWillBeginDragging:(SwipeView *)swipeView;

This method is called when the SwipeView is about to start moving as the result of the user dragging it.

- (void)swipeViewDidEndDragging:(SwipeView *)swipeView willDecelerate:(BOOL)decelerate;

This method is called when the user stops dragging the SwipeView. The willDecelerate parameter indicates whether the SwipeView is travelling fast enough that it needs to decelerate before it stops (i.e. the current index is not necessarily the one it will stop at) or if it will stop where it is. Note that even if willDecelerate is NO, if pagin is enabled, the SwipeView will still scroll automatically until it aligns exactly on the current index.

- (void)swipeViewWillBeginDecelerating:(SwipeView *)swipeView;

This method is called when the SwipeView is about to start decelerating after the user has finished dragging it.

- (void)swipeViewDidEndDecelerating:(SwipeView *)swipeView;

This method is called when the SwipeView finishes decelerating and you can assume that the currentItemIndex at this point is the final stopping value.

- (void)swipeViewDidEndScrollingAnimation:(SwipeView *)swipeView;

This method is called when the SwipeView finishes moving after being scrolled programmatically using the scrollByNumberOfItems: or scrollToItemAtIndex: methods.

- (void)swipeView:(SwipeView *)swipeView didSelectItemAtIndex:(NSInteger)index;

This method will fire if the user taps any SwipeView item view. This method will not fire if the user taps a control within the currently selected view (i.e. any view that is a subclass of UIControl).

- (BOOL)swipeView:(SwipeView *)swipeView shouldSelectItemAtIndex:(NSInteger)index;

This method will fire if the user taps any SwipeView item view. The purpose of a method is to give you the opportunity to ignore a tap on the SwipeView. If you return YES from the method, or don't implement it, the tap will be processed as normal and the swipeView:didSelectItemAtIndex: method will be called. If you return NO, the SwipeView will ignore the tap and it will continue to propagate up the view hierarchy. This is a good way to prevent the SwipeView intercepting tap events intended for processing by another view.

Detecting Taps on Item Views

There are two basic approaches to detecting taps on views in SwipeView. The first approach is to simply use the swipeView:didSelectItemAtIndex: delegate method, which fires every time an item is tapped.

Alternatively, if you want a little more control you can supply a UIButton or UIControl as the item view and handle the touch interactions yourself.

You can also nest UIControls within your item views and these will receive touches as expected (See the Controls Example project for how this can be done).

If you wish to detect other types of interaction such as swipes, double taps or long presses, the simplest way is to attach a UIGestureRecognizer to your item view or its subviews before passing it to the SwipeView.

Release Notes

Version 1.3.2

  • Scroll offsets are now calculated correctly when SwipeView is scaled or rotated
  • Reverted fix from 1.3.1 as it caused other scrollOffset bugs that were worse

Version 1.3.1

  • Fixed bug with scrollOffset changing when screen is rotated

Version 1.3

  • SwipeView now requires ARC (see README for details)
  • Added autoscroll property to set SwipeView scrolling at a constant speed
  • Now supports animated item view resizing and screen rotation
  • No longer crashes sometimes on iOS 7
  • The scrollOffset property is now public
  • Added scrollByOffset:duration: and scrollToOffset:duration: methods
  • Calling reloadData no longer resets scroll position
  • No longer behaves strangely if there is only one item and wrap is enabled
  • Fixed problems with contentOffset when used inside UINavigationController
  • You can now toggle wrapEnabled at any time without messing up item views
  • Now conforms to -Weverything warning level

Version 1.2.10

  • Fixed confict between SwipeView animation and UIScrollView scrolling
  • Fixed issue due to missing [super layoutSubviews]

Version 1.2.9

  • Fixed tap handling when wrap is enabled

Version 1.2.8

  • Fixed bounds error when swipe view size is zero
  • Fixed bug in the logic for automatically calculating item size
  • Fixed bug where last visible view was sometimes not draw in non-wrapped mode
  • Moved ARCHelper macros out of .h file so they do not affect non-ARC code in other classes

Version 1.2.7

  • numberOfItems / numberOfPages getters now call numberOfItemsInSwipeView: dataSource method to ensure that value is correct.

Version 1.2.6

  • SwipeView now calculates number of visible views more accurately
  • Fixed a bug in the wrapping logic that could cause gaps when wrapEnabled = YES and alignment = SwipeViewAlignmentEdge
  • SwipeView now won't attempt to call any datasource methods until the views need to be drawn, which avoids certain race conditions

Version 1.2.5

  • Fixed issue where SwipeView was not correctly deferring view loading when the defersItemViewLoading option was enabled

Version 1.2.4

  • SwipeView now correctly handles touch events on views outside the current page bounds
  • Fixed rounding error when using defersItemViewLoading is enabled
  • Added Controls Example to demo touch event handling

Version 1.2.3

  • Fixed issue where setting currentItemIndex immediately after creating SwipeView would prevent user being able to swipe to the left

Version 1.2.2

  • Fixed rounding error for edge-aligned SwipeViews with paging enabled

Version 1.2.1

  • Fixed off-by-one error when using scrollToItemAtIndex:duration: method
  • swipeViewDidScroll: event is now sent as normal when defersItemViewLoading is enabled, but swipeViewCurrentItemIndexDidChange: is still deferred

Version 1.2

  • Added vertical scrolling option
  • Changed itemWidth property and swipeViewItemWidth: delegate method to itemSize and swipeViewItemSize: respectively
  • Fixes some bugs when defersItemViewLoading is enabled

Version 1.1.7

  • Added delaysContentTouches property, which defaults to YES
  • Fixed blank pages issue when using defersItemViewLoading

Version 1.1.6

  • defersItemViewLoading property is now observed when swiping as well as when scrolling programatically
  • Fixed divide-by-zero error

Version 1.1.5

  • Fixed layout bug when scrolling more than a single page at a time
  • Added defersItemViewLoading property

Version 1.1.4

  • Scrolling methods now let you specify the duration of the scroll

Version 1.1.3

  • Fixed reloading bug on wrapped SwipeViews
  • Added test projects folder

Version 1.1.2

  • Fixed wrapping issue with carousel for certain item counts
  • Calling reloadData on carousel now resets currentItemIndex to zero

Version 1.1.1

  • Removed some leftover debug code that had broken the view recycling logic
  • Fixed bug where scrolling SwipeView programmatically immediately after loading would cause a crash
  • Added ARC Test example

Version 1.1

  • Added support for wrapping
  • It is now possible to display multiple items per page
  • Fixed layout glitches when rotating or resizing view
  • Added additional properties and delegate methods
  • Added page control to example application

Version 1.0.1

  • Fixed bug in delegate setter method
  • Fixed crash when total number of items is less than visible number

Version 1.0

  • Added dynamic view loading and recycling
  • Added ARC support
  • Added documentation
  • Renamed some methods for consistency with iCarousel

Version 0.9

  • Prerelease version.

swipeview's People

Contributors

adolfo avatar fjbelchi avatar nicklockwood avatar noxt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

swipeview's Issues

Best way to preload next/previous page with single item paging swipe view

First of all thanks for this great component. It's working great for me, but i'm trying to do something and can't seem to figure out the best way.

I'm using it fullscreen with a single view per page. Placed within each view there's a UIWebView loading local html content. This works OK, but you can see the html content snap in place inside the webview when loading the CSS and stuff for a fraction of a second when swiping to the next page...

I'd like to prevent this as much as possible by having at least the next and previous page already preloaded. But since the next and previous views are outside of the screen boundaries, they won't be loaded until the swiping started.

How would you to approach this? Should I subclass SwipeView and override the loadUnloadView method to change the handling of offscreen views? Or is there an easier way? I do want to keep reusing the views however.

Cheers

Big issue when using only 2 or so views - they don't show up

Here is my basic setup on iPad:
- One view in the center
- One view on either side where you only see around 50 pixels or so of them

When I load the swipeview with just 2 or 3 items, it only shows the centered one. When I swipe right to the next one, it moves as if there is a view but no view shows up at all. This only happens with a small count. I need a minimum of 3 visible views. Do you know what's happening? When I turn on wrap mode and then turn it off it messes things up even more.

didSelect not being called

the didSelect method is not being called. Going through SwipeView shows that -didTap: is never being called either.

Feature Request - Reusing views

Hey Nick,

Thanks for sharing, it seems that the SwipView doesn't support reusing views, do you think that can cause performance / memory problems with large number of views?

And do you plan to support reusing in the near future?

Change item width on orientation change

Is there an easy way to change the item width depending on orientation? For example, I want the item width to be 50pts smaller if in portrait mode. Thanks

Expose contentOffset ivar

You have excellent didScroll delegate methods, but not way to determine the contentOffset of the internal scrollView. This is useful for things like fading a view out as it is swiped away, or fading it in as it comes into view as a percentage of the offset, similar to how many of the default iOS pages fade content as they dissappear offscreen.

Scroll to item index/page bug

I think there is a bug when scrolling programmatically to item index or page. I can't pinpoint what it is exactly yet, but I did a quick test by programmatically scrolling from third item to first item. Sometimes it would scroll to the first item correctly, but sometimes, it stops on the second item.

I'm not sure if I did anything wrong, but I'll continue investigating.

animateWithDuration makes swipeview choppy in indexDidChange.

I have utlized a swipeView set as a subview in a viewcontroller, another subview on the viewcontroller is a backgroundImageView. I change the image of the backgroundImageView during the:
- (void)swipeViewCurrentItemIndexDidChange:(SwipeView *)swipeView

This works fine unless I have that image view do a coreanimation animateWithDuration. The scroll then becomes very chop as it finishes itself. I have found that setting the swipeview to:
_swipeView.defersItemViewLoading = YES;

mitigates the problem, however now the transition is delayed... Here is my code for that method. Any possibility to make this work much smoother without setting the defer?

- (void)swipeViewCurrentItemIndexDidChange:(SwipeView *)swipeView
{
//update page control page
pageControl.currentPage = swipeView.currentPage;
[pageControl updateCurrentPageDisplay];

  _backgroundImageView.image = [_backgroundImages objectAtIndex:pageControl.currentPage];
[UIView animateWithDuration:0.3
                      delay:0
                    options: UIViewAnimationOptionTransitionCrossDissolve
                 animations:^{
                     //view.alpha = 1;
                     //if([view isKindOfClass:[WDTourItemView class]])
                     _backgroundImageView.image = [_backgroundImages objectAtIndex:pageControl.currentPage];
                 } completion:^(BOOL finished){}];
}

Swipeview doesn't show last item

Swipeview settings:

itemsPerPage = 3
defersItemViewLoading = YES
wrapEnabled = NO
datasource contains 3 views

Swipeview doesn't display the last (3rd) item. If i scroll the first view off screen then the 3rd view appears, but if I let go them it disappears again at the end of decelerating.

When i set defersItemViewLoading = NO, then i see all 3 views, but i need to set defersItemViewLoading = YES

first webview stays empty

I try to display a series of full screen UIWebViews. All data displayed in the views is locally available. Sometimes, the first UIWebView remains white on display. Swiping to the next UIWebView and back, reveals the contents of the first view.

It seems to be timing related. Do you have any idea what could be the problem?

Toggling WrapEnabled

I took your example project and added a button to toggle on and off "wrap". When you turn it on, swipe to the next view or two, then turn it off, the entire swipe view gets messed up. It ends up on a blank spot in the swipeview and you can't get back to the actual views. Do you have a fix?

Support on "dynamic data"

I have dynamic data, used for viewForItemAtIndex. I need a method similar to [self.tableview reloadData] to refresh data. I tried but fail to find it, so I have to ask for your help.

Liang

layoutSubviews

Maybe not necessarily an issue, but it looks a bit suspicious.

Your implementation of layoutSubviews calls updateLayout twice. I wonder if the first call was meant to call super layoutSubviews.

gap between items and some animation while scrolling

hi

1 - is it possible to put a gap between items?
2 - is it possible to make centered item bigger than others?
3 - how to make animation like iCarousel, (center item is bigger than others while scrolling)?

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view does not work properly

The way I am setting up the view for this method is

if (view == nil) {
    UILabel *label = nil;
    label = [[[UILabel alloc] initWithFrame:CGRectMake(0, 0, 120, 30)] autorelease];
    label.backgroundColor = [UIColor grayColor];
    label.textAlignment = NSTextAlignmentCenter;
    switch (index) {
        case 0:
            label.text   =   @"TAP 1";
            break;
        case 1:
            label.text   =   @"TAP 2";
            break;
        case 2:
            label.text   =   @"TAP 3";
            break;
        case 3:
            label.text   =   @"TAP 4";
            break;
    }
    label.font = [label.font fontWithSize:12];       
    view = label;
}
return view;  

}

when I run the application, the tags are in the the right order.However, when I try scrolling and the order of tag are changed.
I post a clip at here so that you can easily see the problem. in the clip, the order of tag1 and tag2 are switched. This should not happen.
Do you have any idea about this issue ?

using tableview inside swipeview

Hi, i was wondering hoy can make a swipe view with tableview inside?
i guess that part is not complicated, but how do you get the tableview´s delegate methods calls?

thanks

Customising SwipeView.

Hi Everyone,
I have a requirement like below , and i am trying to do it by customizing the swipeView. Please suggest me how to do it or let me know if any other bettwer ways to do. I have already spent much amount of time, would be great if anybody of you can save my days.
Looking forward to hear from you
My requirements are below along with my pencil sketch .

User is presented menu items as a sequence of cards ( the big rectangle in the center) and they flick through each one of them. User can also double tap on a card and in that case, card will cover the entire screen and user can go back to the card flow by double tapping again . Also there could be a sequence of pictures (on a card)
that users can flick through by flick gesture on that area within the card. ( anywhere else should result in card movement). Apart from these the card in the center should shown with more prominence as shown in the pencil sketch below.

Note:Please click on the sketch below to see in the actual view, i dont why its coming in landscape mode.

photo

Thanks,
Mur

Minor discrepancies between docs and code

In docs:

- (NSUInteger)numberOfItemsInSwipeView:(SwipeView *)swipeView;
- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view;

In code:

- (NSInteger)numberOfItemsInSwipeView:(SwipeView *)swipeView;
- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view;

NSUInteger vs NSInteger

Thanks!

Visible views aren't refreshing on reloadData

My SwipeView is getting it's data off of an NSFetchedResultsController (FRC). When my view appears on screen, I call reload data on the SwipeView in -viewWillAppear: so that it can update based on the updated FRC's content. The visible views are not refreshing. If I scroll away and come back they are correct. Do you know why this is? I can't figure out a fix.

How to make "center alignment"

Hi
It's OK when numberOfItems is more than 2.
However, when numberOfItems = 1 or 2, it's by default is left aligned, and not beautiful enough. I tried several ways to make it Centre aligned, but failed. Is there any way could easily make it center aligned, at least when numberOfItems is less than 3.

See attached.

Thanks so much
demo

Advantage over UITableView with transform

Hi there,

Just curious, what are the advantages of using SwipeView over UITableView with rotation transform applied to the table view and table cell to make it scroll horizontally?

Thanks!

crash in dequeueItemView

It crashes in [_itemViewPool anyObject] ...
I guess the _itemViewPool is deallocated otherwise I have no explanation for this.

I get this quite frequently, do you have any idea how could I fix it? I need the code it in production by Thursday morning ...

Thanks,
Dan

Delegate bug

Hey Nick,

There is a bug in the method:

(void)setDelegate:(id)delegate
{
if (_delegate != delegate)
{
_delegate = _delegate;
if (_delegate && _dataSource)
{
[self reloadData];
}
}
}

Of course _delegate = _delegate;
should be _delegate = delegate;

Sorry I don't know how to change the code here by myself...

Low performance with fast scrolling

Hello!
I implemented the Swipe View with paging enabled and added lots of pages. It works really well in terms of memory management and I'm not even reusing the views.

(Each view is very complex (tons of subviews) so it's difficult to reuse them and update all the info. I've tried but it doesn't work for me.)

The problem is:
I connected a UISlider to the Swipe View to allow fast scrolling through all the pages.
What happens is, the scrolling is faster than the time the new views need to be created and that produces a sluggish scroll effect.

One solution could be to load more views than the swipe view load by default. Can you provide some alternative solutions or give some insights on how to adapt the library to do that ?

setting currentItemIndex gives a crash

When I set currentItemIndex in v1.1.5 it will give a crash:

  • (void)viewDidLoad
    {
    ...
    _swipeView.currentItemIndex = n;
    ...
    }

* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSPlaceholderSet initWithCapacity:]: capacity (2147483648) is ridiculous'

It seems that in loadUnloadViews function self.bounds.size.width is divided by 0:
NSInteger numberOfVisibleItems = ceilf(self.bounds.size.width / _itemWidth) + 2;

Couldn't figure out why _itemWidth has a value of 0.

Feature request - Padding for items

Hi,
let me thank you for great control and I would appreciate it if you could add possibility to configure side and to padding of items.
Thanks

scrollToItemAtIndex don't work

Hi,

I have button for remote scrolling of SwipeView. After click a button, view should center at the given index, but it doesn't. Swipes and whole swipeView is working normally. The swipeView stays in place when I click a button, no move and no log output. Please help.

Codes:

_arrowRightButton = [UIButton buttonWithType:UIButtonTypeCustom];
[_arrowRightButton addTarget:self action:@selector(scrollCarouselRight) forControlEvents:UIControlEventTouchUpInside];

-(void)scrollCarouselRight {
    [_swipeView scrollToItemAtIndex:3 duration:1.0];
}

Christopher

Feature Request - Dragging & Decelerating properties

Hey Nick,

TableView has a readonly dragging and decelerating properties, is it possible to add it to the SwipeView?
And to expose the scrollViewDidEndDecelerating / scrollViewDidEndDragging:willDecelerate delegate methods?

The reason I need this is that I have an image view inside every swipe view item, when a user scroll to an item I'm fetching the item's image from my server in the viewForItemAtIndex method.

Currently if the user scroll from item at index 1 to item at index 10 I'll fetch all the images for all the items between them.
I prefer to defer the image fetching for items 2-9 until the user actually stop on one of them, so I want to detect if the user is dragging the SwipeView or if the SwipeView is still decelerating if so I'll defer the image fetching and I'll do it in the scrollViewDidEndDecelerating / scrollViewDidEndDragging:willDecelerate instead.

Swipe View layout

Hey nick,

I want to display the swipe view items a certain way, I want that an item width will be smaller then the screen width, i want items to have space between them and also when item is centered then both previous and next items edges are visible from both of his sides.

I will try to be clearer and draw the situation - this is the iPhone screen when item 2 is centered:

|| item1 ]-space-[ -------------- item 2 -------------- ]-space-[ item3 ||

In the previous version of SwipeView I managed to achieve this by creating a view with width 260.0 in viewForItemAtIndex data source method, and returning 280.0 in the swipeViewPageWidth delegate method.

But in the new version I see that the swipeViewPageWidth is gone, so how could I achieve this layout?

SwipeView with UIViewControllerContainment

I have an Array of UIViewControllers, I would like each page in the swipeView to be the right viewController's view

In the swipeView:viewForItemAtIndex:reusingView method, I have the following implemented but it isn't working. How do I use swipeView with UIViewController containment APIs in iOS5 and above?

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
    VerticalViewController *viewController = self.verticalsViewControllers[index];
    [viewController.view setFrame:CGRectMake(0, 0, 768, 1024)];
    [viewController loadData];

    return viewController.view;
}

- (NSInteger)numberOfItemsInSwipeView:(SwipeView *)swipeView
{
    return [self.verticalsViewControllers count];
}

The 3rd view always show 1st view's data

I added 3 subviews to the swipeview. I implemented swipeview datasource and delegate methods. But BrandTableView is showing CategoryTableView's data. If I switch them, still, the 3rd view don't work, it's showing 1st view's data and UI.


- (NSInteger)numberOfItemsInSwipeView:(SwipeView *)swipeView
  {
  return 3;
  }
- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
  {
  switch (index)
  {
      case 0:
      {
          CategoryTableView *category = (CategoryTableView *)view;
          if (!view) {
              category = [[CategoryTableView alloc] initWithFrame:self.view.bounds];
              category.parentViewController = self;
              category.delegatge = self;
              view = category;
          }
      }
          break;
      case 1:
      {
          SupermarketTableView *supermarket = (SupermarketTableView *)view;
          if (!view) {
              supermarket = [[SupermarketTableView alloc] initWithFrame:self.view.bounds];
              supermarket.parentViewController = self;
              view = supermarket;
          }
  
  ```
  }
      break;
  case 2:
  {
  
      BrandTableView *brand = (BrandTableView *)view;
      if (!view)
      {
          brand = [[BrandTableView alloc] initWithFrame:self.view.bounds];
          brand.parentViewController = self;
          view = brand;
      }
  }
      break;
  ```
  
  }
  return view;
  }
  

Limit scrolling till the last item

Hi Nick,

My swipe view present 3.5 items at a given moment.
When the user swipe the screen (not the swipe view) I use the [self.swipeView scrollByNumberOfItems:1 duration:0.3];
method to swipe the swipe view one item to the right.

The problem is (or my problem is...) that the scrolling doesn't stop when reaching the last item (most right one), I don't want it to scroll to the most left side, I want it to stop scrolling when he is at the most right side.

I also want that if before scroll this last item is half visible, that the scroll will just scroll enough to show it completely. (so actually that the scrollByNumberOfItems method will not scroll 1 item if it is the last one)

I hope you can understand this hazy description...
Thanks
Eyal

Use of NSInteger instead of NSUInteger

Many methods (such as - currentItemIndex) return an NSInteger as opposed to an NSUInteger, which seems strange as most cocoa collections use NSUInteger so I have to typecast a lot. Is there a reason for this?

Not support on iOS7

I'm testing it on iOS7 (Xcode5 DP2). It crashes at swipeview.m:

"view.center = CGPointMake(([self offsetForItemAtIndex:index] + 0.5f) * _itemSize.width + _scrollView.contentOffset.x, _scrollView.frame.size.height/2.0f);"

delaysContentTouches set to NO by default

Is there a reason why delaysContentTouches is set to NO by default? I think it should be set to YES so it's more consistent with UIScrollView and UITableView. Or maybe it should be configurable?

How to trigger swipeview to reload tableview's data that inside it

I created two subviews, they each have a tableview inside it. I have implemented the swipeview's delegate. I have added swipeview in a view controller. Now, I want to trigger the tableview's data throught swipe view, how to do that? each time the subview have initial data back the tableview data. so, in the view controller, i want to update the tableview data, and reload the tableview data. I have tried delegate, but it's not working.

Bug - viewForItemAtIndex call for un exists indexes

Nick, it seems that there is a bug with the loadUnloadViews method, It trigger a viewForItemAtIndex calls for indexes that aren't exists.

Try changing in your SwipeViewExample the amount of colors in the color array to under 5 and the app will crash.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.