AMSlideMenu UI mess up when receives a call (In-Call Status bar) - ios

Library : https://github.com/SocialObjects-Software/AMSlideMenu
Problem : When you are in closed menu state and receives a call(Simply simulate in iOS simulator) after ending call or while in the call if you try to open slide menu, Menu will appear as little bit smaller.
Any better workarounds for this?

Quick workaround,
Go to AMSlideMenuMainViewController.m
Replace below methods in the file,
- (void)openRightMenu
{
CGRect frame = self.rightMenu.view.frame;
frame.origin.x = [UIScreen mainScreen].bounds.size.width - [self rightMenuWidth];
frame.origin.y = 0;
frame.size = [UIScreen mainScreen].bounds.size;
frame.size.width = [self rightMenuWidth];
self.rightMenu.view.frame = frame;
[self openRightMenuAnimated:YES];
}
- (void)openLeftMenu
{
CGRect frame = self.leftMenu.view.frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size = [UIScreen mainScreen].bounds.size;
self.leftMenu.view.frame = frame;
[self openLeftMenuAnimated:YES];
}
And this,
- (void)configure3DTransformForMenu:(AMSlideMenu)menu panningView:(UIView *)panningView
{
float cx = 0;
float cy = 0;
float cz = 0;
float opacity = 0;
/********************************************* DEEPNESS EFFECT *******************************************************/
if (menu == AMSlideMenuLeft && panningView.frame.origin.x != 0 && [self deepnessForLeftMenu])
{
//Workaround for in-call status bar
CGRect frame = self.leftMenu.view.frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size = [UIScreen mainScreen].bounds.size;
self.leftMenu.view.frame = frame;
//end workaround for in-call status bar
cx = kMenuTransformScale.m11 + (panningView.frame.origin.x / [self leftMenuWidth]) * (1.0 - kMenuTransformScale.m11);
cy = kMenuTransformScale.m22 + (panningView.frame.origin.x / [self leftMenuWidth]) * (1.0 - kMenuTransformScale.m22);
cz = kMenuTransformScale.m33 + (panningView.frame.origin.x / [self leftMenuWidth]) * (1.0 - kMenuTransformScale.m33);
opacity = kMenuLayerInitialOpacity + (panningView.frame.origin.x / [self leftMenuWidth]) * (1.0 - kMenuLayerInitialOpacity);
self.leftMenu.view.layer.transform = CATransform3DMakeScale(cx, cy, cz);
self.leftMenu.view.layer.opacity = opacity;
}
else if (menu == AMSlideMenuRight && panningView.frame.origin.x != 0 && [self deepnessForRightMenu])
{
//Workaround for in-call status bar
CGRect frame = self.rightMenu.view.frame;
frame.origin.x = [UIScreen mainScreen].bounds.size.width - [self rightMenuWidth];
frame.origin.y = 0;
frame.size = [UIScreen mainScreen].bounds.size;
frame.size.width = [self rightMenuWidth];
self.rightMenu.view.frame = frame;
//end workaround for in-call status bar
cx = kMenuTransformScale.m11 + (-panningView.frame.origin.x / [self rightMenuWidth]) * (1.0 - kMenuTransformScale.m11);
cy = kMenuTransformScale.m22 + (-panningView.frame.origin.x / [self rightMenuWidth]) * (1.0 - kMenuTransformScale.m22);
cz = kMenuTransformScale.m33 + (-panningView.frame.origin.x / [self rightMenuWidth]) * (1.0 - kMenuTransformScale.m33);
opacity = kMenuLayerInitialOpacity + (-panningView.frame.origin.x / [self rightMenuWidth]) * (1.0 - kMenuLayerInitialOpacity);
self.rightMenu.view.layer.transform = CATransform3DMakeScale(cx, cy, cz);
self.rightMenu.view.layer.opacity = opacity;
}
/********************************************* DEEPNESS EFFECT *******************************************************/
/********************************************* STATUS BAR FIX *******************************************************/
if (menu == AMSlideMenuLeft && panningView.frame.origin.x != 0)
{
if (self.statusBarView)
{
self.statusBarView.layer.opacity = 1 - panningView.frame.origin.x / [self leftMenuWidth];
}
}
else if (menu == AMSlideMenuRight && panningView.frame.origin.x != 0)
{
if (self.statusBarView)
{
self.statusBarView.layer.opacity = 1 - abs(panningView.frame.origin.x) / [self rightMenuWidth];
}
}
/********************************************* STATUS BAR FIX *******************************************************/
/********************************************* DARKNESS EFFECT *******************************************************/
if (menu == AMSlideMenuLeft)
{
CGFloat alpha = [self maxDarknessWhileLeftMenu] * (panningView.frame.origin.x / [self leftMenuWidth]);
self.darknessView.alpha = alpha;
}
else if(menu == AMSlideMenuRight)
{
CGFloat alpha = [self maxDarknessWhileRightMenu] * (abs(panningView.frame.origin.x) / [self rightMenuWidth]);
self.darknessView.alpha = alpha;
}
/********************************************* DARKNESS EFFECT *******************************************************/
}

Related

Calculate new scroll view content inset when showing/hiding nav bar

I am replicating Facebook/Apple News hide/show nav bar functionality. I can hide/show the nav bar but I don't know how to calculate the scroll view's content inset as the nav bar frame.origin.y changes. I want the scroll view content inset to follow nav bar's position so that it all looks smooth.
Here's what I'm doing:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat navBarTopLength = self.navigationController.topLayoutGuide.length; // 20
CGRect frame = self.navigationController.navigationBar.frame;
CGFloat size = frame.size.height - (navBarTopLength + 1);
CGFloat framePercentageHidden = ((navBarTopLength - frame.origin.y) / (frame.size.height - 1));
CGFloat scrollOffset = scrollView.contentOffset.y;
CGFloat scrollDiff = scrollOffset - self.previousScrollViewYOffset;
CGFloat scrollHeight = scrollView.frame.size.height;
CGFloat scrollContentSizeHeight = scrollView.contentSize.height + scrollView.contentInset.bottom;
if (scrollOffset <= -scrollView.contentInset.top) {
frame.origin.y = navBarTopLength; // showing nav bar
} else if ((scrollOffset + scrollHeight) >= scrollContentSizeHeight) {
frame.origin.y = -size;
} else {
frame.origin.y = MIN(navBarTopLength, MAX(-size, frame.origin.y - scrollDiff));
}
CGFloat top;
if (self.previousScrollViewYOffset > scrollOffset) {
NSLog(#"scrolling down"); //scrolling down
top = self.navigationController.navigationBar.frame.size.height + frame.origin.y;
} else {
NSLog(#"scrolling up"); //scrolling up
top = (navBarTopLength + 1) + frame.origin.y;
}
[self.navigationController.navigationBar setFrame:frame];
[self updateBarButtonItems:(1 - framePercentageHidden)];
scrollView.contentInset = UIEdgeInsetsMake(top, 0, 0, 0);
self.previousScrollViewYOffset = scrollOffset;
}
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self stoppedScrolling];
}
- (void)updateBarButtonItems:(CGFloat)alpha {
[self.navigationItem.leftBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem *item, NSUInteger i, BOOL *stop) {
item.customView.alpha = alpha;
}];
[self.navigationItem.rightBarButtonItems enumerateObjectsUsingBlock:^(UIBarButtonItem *item, NSUInteger i, BOOL *stop) {
item.customView.alpha = alpha;
}];
self.navigationItem.titleView.alpha = alpha;
self.navigationController.navigationBar.tintColor =[self.navigationController.navigationBar.tintColor colorWithAlphaComponent:alpha];
}
- (void)animateNavBarTo:(CGFloat)y {
[UIView animateWithDuration:0.2
animations:^{
CGRect frame = self.navigationController.navigationBar.frame;
BOOL hide = frame.origin.y >= y;
CGFloat alpha = (hide ? 0 : 1);
frame.origin.y = y;
[self.navigationController.navigationBar setFrame:frame];
[self updateBarButtonItems:alpha];
self.navBarHidden = hide;
}];
}
- (void)stoppedScrolling {
CGRect frame = self.navigationController.navigationBar.frame;
if (frame.origin.y < 20) {
[self animateNavBarTo:-(frame.size.height - 21)];
}
}
I know that I should be changing the content inset in scrollViewDidScroll as I'm calculating a new frame for the nav bar. The way I'm currently calculating new top inset makes the whole UI shake and everything breaks shortly after with BAD ACCESS

Implementing Grid/table drawing algorithm

I'm trying to implement universal method for generating (drawing) grid formed with UIViews (or other controls). They all should have borders and my problem is I cannot find right algorithm to shift (combine) borders (so the "table" does not have double cell borders like now) and to increase size so the views exactly match given frame (red on picture).
Following code generates picture beneath:
////////
const CGFloat kOuterBorderWidth = 0.0;
const CGFloat kInnerBorderWidth = 1.0;
NSArray *rows;
NSArray *columns = rows = #[#0.065, #0.29, #0.29, #0.29, #0.065];
NSMutableArray *cells = [self drawGridWithFrame:self.frame
columns:columns
rows:rows
outerBorderWidth:kOuterBorderWidth
innerBordersWidth:kInnerBorderWidth];
///////
and the method itself
- (NSMutableArray*)drawGridWithFrame:(CGRect)frame
columns:(NSArray *)columns
rows:(NSArray *)rows
outerBorderWidth:(CGFloat)outerBorderWidth
innerBordersWidth:(CGFloat)innerBordersWidth
{
CGFloat x = 0, y = 0;
NSMutableArray *cells = [NSMutableArray new];
CGFloat height = [rows[0] floatValue] * frame.size.height;
for (int j = 0; j < columns.count; j++) {
CGFloat width = [columns[j] floatValue] * frame.size.width;
CGRect cellFrame = CGRectMake(x, y, width, height);
UIView *cellView = [[UIView alloc] initWithFrame:cellFrame];
cellView.layer.borderWidth = innerBordersWidth;
if (j == 0 || j == columns.count - 1) {
cellView.layer.borderColor = [UIColor magentaColor].CGColor;
}
if (j == 1) {
cellView.layer.borderColor = [UIColor orangeColor].CGColor;
}
if (j == 2) {
cellView.layer.borderColor = [UIColor brownColor].CGColor;
}
[cells addObject:cellView];
x += [columns[j] floatValue] * frame.size.width;
}
return cells;
}
Done it.
Note: outerBorderWidth is now not used here, if it is > 1.0pt, then we additionally should shift views and adjust their size
- (NSMutableArray*)drawGridWithFrame:(CGRect)frame
columns:(NSArray *)columns
rows:(NSArray *)rows
outerBorderWidth:(CGFloat)outerBorderWidth
innerBordersWidth:(CGFloat)innerBordersWidth
{
CGFloat x = 0, y = 0;
NSMutableArray *cells = [NSMutableArray new];
CGFloat heightAdjust = (CGFloat)(rows.count - 1) / (CGFloat)rows.count;
CGFloat widthAdjust = (CGFloat)(columns.count - 1) / (CGFloat)columns.count;
for (int i = 0; i < rows.count; i++) {
CGFloat height = [rows[i] floatValue] * frame.size.height + innerBordersWidth * heightAdjust;
for (int j = 0; j < columns.count; j++) {
CGFloat width = [columns[j] floatValue] * frame.size.width + innerBordersWidth * widthAdjust;
CGRect cellFrame = CGRectMake(x, y, width, height);
UIView *cellView = [[UIView alloc] initWithFrame:cellFrame];
cellView.layer.borderWidth = innerBordersWidth;
if (j == 0 || j == columns.count - 1) {
cellView.layer.borderColor = [UIColor magentaColor].CGColor;
}
if (j == 1) {
cellView.layer.borderColor = [UIColor orangeColor].CGColor;
}
if (j == 2) {
cellView.layer.borderColor = [UIColor brownColor].CGColor;
}
[cells addObject:cellView];
x += width - innerBordersWidth;
}
x = 0;
y += height - innerBordersWidth;
}
return cells;
}
Result:

Objective C. UIScrollView. How scrolled to one page if velocity is more then one

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?

How to zoom from min to max coordinates positions in UIScrollView?

I have a UIScrollView, which hold an UIImageView. I have a requirements to reach and zoom to particular location in UIImageView.
So for e.g. I want to start from (x: 0, y: 0) to specified location.
What's the best practice to do that?
This is how I'm achieving this:
- (void) setInitialZoomLevelAndShowImageInCenter {
CGRect scrollViewFrame = scrollViewMap.frame;
CGFloat scaleWidth = scrollViewFrame.size.width / scrollViewMap.contentSize.width;
CGFloat scaleHeight = scrollViewFrame.size.height / scrollViewMap.contentSize.height;
CGFloat minScale = MIN(scaleWidth, scaleHeight);
scrollViewMap.minimumZoomScale = minScale/1.5;
scrollViewMap.maximumZoomScale = 10.0f;
scrollViewMap.zoomScale = minScale;
CGFloat newZoomScale = scrollViewMap.zoomScale * 2.80f;
CGFloat xPos = 0;
CGFloat yPos = 0;
BOOL isMatched = NO;
while (!isMatched) {
[self zoomToPoint:CGPointMake(xPos, yPos) withScale:newZoomScale animated:YES];
BOOL isAnyChange = NO;
if(xPos <= slotItem.xCord) {
xPos+=1.0f;
isAnyChange = YES;
}
if(yPos <= slotItem.yCord) {
yPos+=1.0f;
isAnyChange = YES;
}
if(!isAnyChange) {
isMatched = YES;
}
}
}
- (void)zoomToPoint:(CGPoint)zoomPoint withScale: (CGFloat)scale animated: (BOOL)animated
{
//Normalize current content size back to content scale of 1.0f
CGSize contentSize;
contentSize.width = (scrollViewMap.contentSize.width / scrollViewMap.zoomScale);
contentSize.height = (scrollViewMap.contentSize.height / scrollViewMap.zoomScale);
//derive the size of the region to zoom to
CGSize zoomSize;
zoomSize.width = scrollViewMap.bounds.size.width / scale;
zoomSize.height = scrollViewMap.bounds.size.height / scale;
//offset the zoom rect so the actual zoom point is in the middle of the rectangle
CGRect zoomRect;
zoomRect.origin.x = zoomPoint.x - zoomSize.width / 2.0f;
zoomRect.origin.y = zoomPoint.y - zoomSize.height / 2.0f;
zoomRect.size.width = zoomSize.width;
zoomRect.size.height = zoomSize.height;
//apply the resize
[scrollViewMap zoomToRect: zoomRect animated: animated];
}

ios - How to calculate how much memory a UIView animation will take?

I am new to IOS development.
In my application I've got several images that I am animating.
The number of images can vary.
When running on ipad 2 the animations works fine.
When running on ipad 1, which a large number of images (20+) the app just crashes with a memory warning.
I would like to calculate the amount of memory an animation would take in advance.
Based on this figure I could calculate if to go through with my animation or skip
to the final status.
How can this be done?
Edited:
My current code:
- (void)remix
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:animationDuration];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:
#selector(animationDidStop:finished:context:)];
self.currentStatus = canvas_status_animating;
NSMutableArray *circles = [[NSMutableArray alloc] init];
for (CircleView* view in self.subviews)
{
if(![view isKindOfClass:[CircleView class]])
continue;
[circles addObject:view];
}
[self animatePosition:circles];
[UIView commitAnimations];
}
-(void) animatePosition:(NSArray*)circles
{
int maxWidth = self.bounds.size.width;
int maxHeight = self.bounds.size.height;
for (CircleView* view in circles)
{
int selectedX = 0;
int selectedY = 0;
if ((arc4random()%200)+1 > 100)
{
selectedX = (arc4random() % maxWidth) + 1;
selectedY = (arc4random() % 200) + 1;
selectedY = (selectedY > 100) ? (maxHeight - selectedY) : selectedY;
}
else
{
selectedX = (arc4random() % 200) + 1;
selectedX = (selectedX > 100) ? (maxWidth - selectedX) : selectedX;
selectedY = (arc4random() % maxHeight) + 1;
}
view.frame = CGRectMake(selectedX - view.frame.size.width / 2,
selectedY - view.frame.size.height / 2,
view.frame.size.width,
view.frame.size.height);
}
}
You can call this function before and after, and calc the difference.
-(double)availableMemory
{
vm_statistics_data_t vmStats;
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);
if (kernReturn != KERN_SUCCESS)
{
return NSNotFound;
}
return ((vm_page_size * vmStats.free_count) / 1024.0) / 1024.0;
}

Resources