Is anyone able to do this properly?
Here's a tutorial that covers the gesture http://www.raywenderlich.com/22174/how-to-make-a-gesture-driven-to-do-list-app-part-33. And here's the project files: https://github.com/ColinEberhardt/iOS-ClearStyle
It is far from as smooth as the original Clear app:
#pragma mark - UIScrollViewDelegate methods
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
// this behaviour starts when a user pulls down while at the top of the table
_pullDownInProgress = scrollView.contentOffset.y <= 0.0f;
if (_pullDownInProgress)
{
// add our placeholder
[_tableView insertSubview:_placeholderCell atIndex:0];
}
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (_pullDownInProgress && _tableView.scrollView.contentOffset.y <= 0.0f)
{
// maintain the location of the placeholder
_placeholderCell.frame = CGRectMake(0, - _tableView.scrollView.contentOffset.y - SHC_ROW_HEIGHT,
_tableView.frame.size.width, SHC_ROW_HEIGHT);
_placeholderCell.label.text = -_tableView.scrollView.contentOffset.y > SHC_ROW_HEIGHT ?
#"Release to Add Item" : #"Pull to Add Item";
_placeholderCell.alpha = MIN(1.0f, - _tableView.scrollView.contentOffset.y / SHC_ROW_HEIGHT);
}
else
{
_pullDownInProgress = false;
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
// check whether the user pulled down far enough
if (_pullDownInProgress && - _tableView.scrollView.contentOffset.y > SHC_ROW_HEIGHT)
{
[_tableView.datasource itemAdded];
}
_pullDownInProgress = false;
[_placeholderCell removeFromSuperview];
}
#end
Related
I have setup scrollView delegate and implemented the logic into scrollViewDidScroll protocol method as follows, it never goes into the second condition. I wonder what I am missing?
-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
float scrollViewHeight = scrollView.frame.size.height;
float scrollOffset = scrollView.contentOffset.y;
if (scrollOffset == 0)
{
// then we are at the top
}
else if (scrollOffset + scrollViewHeight == 700.0)
{
// never calls here
[self loadSecondFromURL];
}
}
I think scrollOffset is zero so, its entering only first loop. I changed the code like this and it works fine for me
if (scrollOffset == 0)
{
// then we are at the top
}
if (scrollOffset + scrollViewHeight == 700.0)
{
// never calls here
[self loadSecondFromURL];
}
In this time I'm write pod, custom pageViewController.
And in this work I have one problem.
I have scrollView. On this scrollView I have 3\5\7 ViewControllers.
They are small and on Scroll view We can see half of first VC, second VC and third VC.
pagingEnabled on ScrollView is On. And if we scroll VC move and scrollView change focused zone.
If we move scroll fast or touch for one size of screen and move to other size then we move from first screen to third VC.
http://prntscr.com/bhfqfn
http://prntscr.com/bhfqr8
http://prntscr.com/bhfrdq
pragma mark - UIScrollViewDelegate
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if (0 > velocity.x) {
if ([self.dataSource respondsToSelector:#selector(pageViewController:viewControllerBeforeViewController:)]) {
if (self.scrollView.contentOffset.x <= self.internalViewControllers.firstObject.view.frame.size.width + self.view.frame.size.width) {
UIViewController *newViewController = [self.dataSource pageViewController:self viewControllerBeforeViewController:self.internalViewControllers.firstObject];
if (newViewController) {
[self popRightViewCintroller];
[self pushLeftViewController:newViewController];
[self moveViewControllers];
targetContentOffset->x = scrollView.contentOffset.x;
[scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x + self.scrollView.frame.size.width, 0) animated:NO];
}
}
}
}
if (0 < velocity.x) {
if ([self.dataSource respondsToSelector:#selector(pageViewController:viewControllerAfterViewController:)]) {
if (self.scrollView.contentOffset.x >= self.internalViewControllers.lastObject.view.frame.origin.x - self.view.frame.size.width * 2) {
UIViewController *newViewController = [self.dataSource pageViewController:self viewControllerAfterViewController:self.internalViewControllers.lastObject];
if (newViewController) {
[self popLeftViewCintroller];
[self pushRightViewController:newViewController];
[self moveViewControllers];
targetContentOffset->x = scrollView.contentOffset.x;
[scrollView setContentOffset:CGPointMake(self.scrollView.contentOffset.x - self.scrollView.frame.size.width, 0) animated:NO];
}
}
}
} }
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
[self moveViewControllers]; }
pragma mark - Helpers
- (void)moveViewControllers {
int numberOfFocusetView = floor(self.scrollView.contentOffset.x / self.scrollView.frame.size.width);
CGFloat contentOffsetView;
if (numberOfFocusetView > 0) {
contentOffsetView = self.scrollView.contentOffset.x - (numberOfFocusetView * self.scrollView.frame.size.width);
} if (numberOfFocusetView == 0) {
contentOffsetView = self.scrollView.contentOffset.x;
}
if (numberOfFocusetView >= 0) {
UIViewController* centralVC = self.internalViewControllers[numberOfFocusetView];
contentOffsetView = contentOffsetView / (self.scrollView.frame.size.width / (self.scrollView.frame.size.width - self.childVCSize.width - self.sizeBetweenVC));
CGFloat form = 0;
if (self.animationSpeed == 0) {
self.animationSpeed = 1;
}
switch (self.animation) {
case defaultAnimation:
form = 0;
break;
case easeIn:
form = sinf(contentOffsetView / (self.scrollView.frame.size.width - self.childVCSize.width - self.sizeBetweenVC) * M_PI) * self.animationSpeed;
break;
case easeOut:
form = -sinf(contentOffsetView / (self.scrollView.frame.size.width - self.childVCSize.width - self.sizeBetweenVC) * M_PI) * self.animationSpeed;
break;
case easeBorder:
form = sinf(contentOffsetView / (self.scrollView.frame.size.width - self.childVCSize.width - self.sizeBetweenVC) * M_PI*2) * self.animationSpeed;
break;
case easeCenter:
form = -sinf(contentOffsetView / (self.scrollView.frame.size.width - self.childVCSize.width - self.sizeBetweenVC) * M_PI*2) * self.animationSpeed;
break;
default:
break;
}
CGFloat originX = (self.spaceHorizontal + (self.scrollView.frame.size.width * numberOfFocusetView) + contentOffsetView);
centralVC.view.frame = CGRectMake(originX + form, self.spaceVertical, self.childVCSize.width, self.childVCSize.height);
[self changeViewControllersOriginXBy:centralVC withNumber:numberOfFocusetView];
} }
- (void) changeViewControllersOriginXBy:(__kindof UIViewController *) centralVC withNumber:(NSInteger) numberOfFocusetView {
for (int i = 0; i < self.internalViewControllers.count; i++) {
if (i != numberOfFocusetView) {
CGFloat originXForView = centralVC.view.frame.origin.x + (self.childVCSize.width + self.sizeBetweenVC) * (i - numberOfFocusetView);
self.internalViewControllers[i].view.frame = CGRectMake(originXForView, self.spaceVertical, self.childVCSize.width, self.childVCSize.height);
}
} }
Someone can help me?
Very similar to a UIRefreshControl, I'm trying to put a UIView on top of a UITableView. Dragging down the table view should reveal the view and have it stay there. Dragging up should hide it again and then scroll the table view. When hidden the table view should scroll normally. Scrolling back to the top should either reveal the hidden view again, or snap to the hidden state. Ultimately the revealed view should contain some buttons or a segmented control. It should look and behave very similar to the OmniFocus App.
Hidden View in OmniFocus
Revealed View in OmniFocus
This is how far I got. Especially the snapping back to the hidden state when the table view scrolls back up does not work. If you time it right you'll end up stuck in the middle of top view, which is exactly not what I want.
static CGFloat const kTopViewHeight = 40;
#interface ViewController ()
#property (nonatomic, weak) UIView *topView;
#property (nonatomic, assign) CGFloat dragStartY;
#end
#implementation ViewController
#pragma mark - View Lifecycle
- (void)viewDidLoad
{
CGRect topViewFrame = CGRectMake(0.0, -kTopViewHeight, 320, kTopViewHeight);
UIView *myView = [[UIView alloc] initWithFrame:topViewFrame];
myView.backgroundColor = [UIColor greenColor]; // DEBUG
self.topView = myView;
[self.tableView addSubview:myView];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
NSLog(#"scrollViewWillBeginDragging %#", NSStringFromCGPoint(scrollView.contentOffset));
self.dragStartY = scrollView.contentOffset.y;
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
NSLog(#"scrollViewDidScroll %#", NSStringFromCGPoint(scrollView.contentOffset));
if (scrollView.contentOffset.y > 0) {
// reset the inset
scrollView.contentInset = UIEdgeInsetsZero;
} else if (scrollView.contentOffset.y >= -kTopViewHeight) {
// set the inset for the section headers
scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (scrollView.contentOffset.y < -kTopViewHeight) {
// don't scroll further when the topView's height is reached
scrollView.contentInset = UIEdgeInsetsMake(-kTopViewHeight, 0, 0, 0);
scrollView.contentOffset = CGPointMake(0, -kTopViewHeight);
}
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
NSLog(#"scrollViewDidEndDragging %#", NSStringFromCGPoint(scrollView.contentOffset));
CGFloat yOffset = scrollView.contentOffset.y;
if (yOffset < 0) {
BOOL dragDown = self.dragStartY > yOffset;
CGFloat dragThreshold = 10;
if (dragDown) {
if (yOffset <= -dragThreshold) {
[self snapDown:YES scrollView:scrollView];
} else {
[self snapDown:NO scrollView:scrollView];
}
} else if (!dragDown) {
if (yOffset >= dragThreshold - kTopViewHeight) {
[self snapDown:NO scrollView:scrollView];
} else {
[self snapDown:YES scrollView:scrollView];
}
}
}
}
- (void)snapDown:(BOOL)down scrollView:(UIScrollView *)scrollView
{
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionAllowUserInteraction|UIViewAnimationOptionCurveEaseOut|UIViewAnimationOptionBeginFromCurrentState
animations:^{
if (down) {
// snap down
scrollView.contentOffset = CGPointMake(0, -kTopViewHeight);
scrollView.contentInset = UIEdgeInsetsMake(kTopViewHeight, 0, 0, 0);
} else {
// snap up
scrollView.contentOffset = CGPointMake(0, 0);
scrollView.contentInset = UIEdgeInsetsZero;
}
}
completion:nil];
}
//paging for data you can use this spinner
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[spinner stopAnimating];
spinner.hidesWhenStopped = NO;
spinner.frame = CGRectMake(0, 0, 320, 44);
tblView.tableFooterView = spinner;
tblView.tableFooterView.hidden = YES;
#pragma mark Table pull to refresh data....
- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
willDecelerate:(BOOL)decelerate{
CGPoint offset = aScrollView.contentOffset;
CGRect bounds = aScrollView.bounds;
CGSize size = aScrollView.contentSize;
UIEdgeInsets inset = aScrollView.contentInset;
float y = offset.y + bounds.size.height - inset.bottom;
float h = size.height;
float reload_distance = 50;
if(y > h + reload_distance && _nextPage) {
NSLog(#"load more data");
tblView.tableFooterView.hidden = NO;
// index for new page of data will increment here
index = index + 1;
[spinner startAnimating];
[self performSelector:#selector(requestData) withObject:nil afterDelay:1.0f];
}
}
// when you request for data and wants to stop spinner
CGPoint offset = tblView.contentOffset;
// if new page is there set bool
_nextPage = YES;
// want to remove spinner
tblView.tableFooterView.hidden = YES;
[spinner stopAnimating];
[tblView setContentOffset:offset animated:NO];
I need to get event then UITableView scrolling up and down. How can I do it?
this not working
- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView
try this method.
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
CGPoint offset = aScrollView.contentOffset;
if (offset.y > 0)
{
NSLog(#"scorlling up");
}
else
{
NSLog(#"scorlling down");
}
}
How do i make it so that when the user scrolls to a new page in UIScrollView, the UIPageControl updates?
I have used this before and it seemed to work well. Be sure to set the UIScrollView.delegate to self.
#pragma mark - UIScrollViewDelegate methods
- (void)scrollViewDidEndDecelerating:(UIScrollView *)sender {
uint page = sender.contentOffset.x / width;
[self.pageControl setCurrentPage:page];
}
Where you defined your UIScrollView and UIPageControl, you have to implement this method :
- (void)scrollViewDidScroll:(UIScrollView *)_scrollView
{
if (pageControlIsChangingPage)
return;
CGFloat pageWidth = _scrollView.frame.size.width;
int page = floor((_scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
pageControl.currentPage = page;
}
and this one :
- (void)scrollViewDidEndDecelerating:(UIScrollView *)_scrollView
{
pageControlIsChangingPage = NO;
}
where pageControlIsChangingPage is :
BOOL pageControlIsChangingPage;
Here is an update of this answer for Swift as well:
func scrollViewDidEndDecelerating(scrollView: UIScrollView) {
pageControl.currentPage = Int(myScrollView.contentOffset.x) / Int(myScrollView.frame.width)
}