UITableView scrolling resets UIImageViews - uitableview

I have some UIImageViews animated via facebook pop on a UIView. A UiTableView on top of the UIView holds the tweets. Somehow my ImageViews get reposition on scrolling. I'm not sure if it's facebook pop API related or there is a problem on how i setup the tableview ?
the UITableView with the tweets are done programmatically in the viewDidLoad of my controller
self.fireTweet = [[CustomUITableView alloc]initWithFrame:CGRectMake(/*160.0f*/self.MainView.frame.size.width, 200.0f, 320.0f, 340.0f)];
[self.fireTweet registerClass:[TWTRTweetTableViewCell class] forCellReuseIdentifier:TweetTableReuseIdentifierFire];
self.fireTweet.delegate = self;
self.fireTweet.dataSource = self;
self.fireTweet.layer.borderColor = [UIColor greenColor].CGColor;
self.fireTweet.layer.borderWidth = 2.0;
self.fireTweet.rowHeight = UITableViewAutomaticDimension;
self.fireTweet.estimatedRowHeight = 340;
...
And some facebook pop related animation code here
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPosition];
anim.springBounciness = 10.0;
anim.toValue = [NSValue valueWithCGPoint:CGPointMake((view.frame.size.width / 2.0) + x, (view.frame.size.height/2.0) + y) ];
//shrink
POPSpringAnimation *imgAnimShrink = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerSize];
imgAnimShrink.property = [POPAnimatableProperty propertyWithName:kPOPLayerSize];
imgAnimShrink.toValue = [NSValue valueWithCGSize:CGSizeMake(50, 50)];
[view pop_addAnimation:anim forKey:#"bottom"];
[view pop_addAnimation:imgAnimShrink forKey:#"imageShrink"];

Figured this out myself. Just turn off the autolayout and it got fixed

Related

Applying shadow on uibutton Makes the button text blury

Here is my code to add a shadow on my uibutton which is created using a .XIB file
UIBezierPath *shadowPathEndbtn = [UIBezierPath bezierPathWithRect:CGRectMake(0, self->_navigationView.frame.size.height - 70,[UIScreen mainScreen].bounds.size.width , 2)];
self->_EndButton.layer.masksToBounds = NO;
self->_EndButton.layer.shadowColor = [UIColor blackColor].CGColor;
self->_EndButton.layer.shadowOffset = CGSizeMake(0.0f, 5.0f);
self->_EndButton.layer.shadowOpacity = 0.7f;
self->_EndButton.layer.shouldRasterize = YES;
self->_EndButton.layer.shadowPath = shadowPathForEndbtn.CGPath;
I am able to set the shadow using this code but this code makes my button text look blury. I am unable to figure out the exact reason behind this. Any help is Appreciated!
self->_EndButton.layer.masksToBounds = false
self->_EndButton.layer.shadowColor = [UIColor blackColor].CGColor
self->_EndButton.layer.contentsScale = [[UIScreen mainScreen]scale];
self->_EndButton.layer.shadowOpacity = 0.7f;
self->_EndButton.layer.shadowRadius = 10.0;
self->_EndButton.layer.shadowOffset = CGSizeMake(0,0)
This will give shadow and also the test is not blurry
Set button background color
self.EndButton.BackgroundColor=[UIColor WhiteColor];

How do I create a growing iOS Button?

My friend gave me the following designs for iOS buttons, and I'm not sure the best way to implement this.
I need to make the reusable button shown below (in Objective-C).
I've tried:
Subclassing the button, but read that I shouldn't do that
Animating the border (while subclassed), but the border only goes inwards, so it seems like I need to animate the frame too
So how do I approach this? I'm assuming making a CustomButtonView class which has a button (composition) as well as an inner and outer circle view? How would I then animate that to grow? Would I have to animate the frame change too, or could I use insets?
What is the simplest code to make this work? Thanks!
Here Is the approach I took to create this:
Subclass UIView to create your custom button
Use UITapGestureRecognizer or touchesBegan, touchesEnded... for your interaction
Add two CALayer's for your foreground and background layers
Add your icon layer (This can be an UIImageView or any other way of displaying an image)
- (id)initWithIcon:(UIImage *)icon backgroundColor:(UIColor *)backgroundColor foregroundColor:(UIColor *)foregroundColor {
if (self = [super init]) {
// Background Layer Setup
_backgroundLayer = [CALayer new];
[_backgroundLayer setBackgroundColor:backgroundColor.CGColor];
[self.layer addSublayer:_backgroundLayer];
// Foreground Layer Setup
_foregroundLayer = [CALayer new];
[_foregroundLayer setBackgroundColor:foregroundColor.CGColor];
[self.layer addSublayer:_foregroundLayer];
// Icon Setup
_icon = [[UIImageView alloc] initWithImage:icon];
[_icon setContentMode:UIViewContentModeCenter];
[self addSubview:_icon];
UIGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(buttonTapped:)];
[self addGestureRecognizer:tapGesture];
}
return self;
}
- (void)setFrame:(CGRect)frame {
// Make sure super is called
[super setFrame:frame];
// Build the layout of backgroundLayer
[self.backgroundLayer setFrame:CGRectMake(frame.size.width*0.1, frame.size.width*0.1, frame.size.width*0.8, frame.size.width*0.8)];
[self.backgroundLayer setCornerRadius:frame.size.width*0.8/2];
// Build the layout of forgroundLayer
[self.foregroundLayer setFrame:CGRectMake(frame.size.width*0.05, frame.size.width*0.05, frame.size.width*0.9, frame.size.width*0.9)];
[self.foregroundLayer setCornerRadius:frame.size.width*0.9/2];
// Build the frame of your icon
[self.icon setFrame:CGRectMake(0, 0, frame.size.width, frame.size.width)];
}
- (void)buttonTapped:(UIGestureRecognizer*)gesture {
// Animate the foreground getting smaller
CABasicAnimation *foregroundFrameChange = [CABasicAnimation animationWithKeyPath:#"frame"];
foregroundFrameChange.fromValue = [NSValue valueWithCGRect:_foregroundLayer.frame];
foregroundFrameChange.toValue = [NSValue valueWithCGRect:CGRectMake(self.frame.size.width*0.1,self.frame.size.width*0.1, self.frame.size.width*0.8, self.frame.size.width*0.8)];
self.foregroundLayer.frame = CGRectMake(self.frame.size.width*0.1,self.frame.size.width*0.1, self.frame.size.width*0.8, self.frame.size.width*0.8);
// Animate the forground cornerRadius to stay rounded
CABasicAnimation *foregroundRadiusChange = [CABasicAnimation animationWithKeyPath:#"cornerRadius"];
foregroundRadiusChange.fromValue = [NSNumber numberWithDouble:self.foregroundLayer.cornerRadius];
foregroundRadiusChange.toValue = [NSNumber numberWithDouble:self.frame.size.width*0.8/2];
[self.foregroundLayer setCornerRadius:self.frame.size.width*0.8/2];
// Animate the background getting larger
CABasicAnimation *backgroundFrameChange = [CABasicAnimation animationWithKeyPath:#"frame"];
backgroundFrameChange.fromValue = [NSValue valueWithCGRect:self.backgroundLayer.frame];
backgroundFrameChange.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.width)];
self.backgroundLayer.frame = CGRectMake(0, 0, self.frame.size.width, self.frame.size.width);
// Animate the background cornerRadius to stay rounded
CABasicAnimation *backgroundRadiusChange = [CABasicAnimation animationWithKeyPath:#"cornerRadius"];
backgroundRadiusChange.fromValue = [NSNumber numberWithDouble:self.backgroundLayer.cornerRadius];
backgroundRadiusChange.toValue = [NSNumber numberWithDouble:self.frame.size.width/2];
[self.backgroundLayer setCornerRadius:self.frame.size.width/2];
// Group all the animations to run simultaneously
CAAnimationGroup *allAnimations = [CAAnimationGroup animation];
allAnimations.duration = 2;
allAnimations.animations = #[foregroundFrameChange, foregroundRadiusChange, backgroundFrameChange, backgroundRadiusChange];
allAnimations.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.layer addAnimation:allAnimations forKey:#"animate"];
// Create your button action callback here
}
This was a quick mock up and not a complete solution but it will give you something to play with.

iOS UITextView Always scroll to bottom

I have this scenario: when I click on a UITextView, it will either expand or shrink. But every time the UITextView shrinks, the content scroll down to the bottom.
I've tried
[textView setContentOffset:CGPointZero animated:YES];
textView.scrollsToTop = YES;
But none of them works.
Here is the screenshot:
Here is the code:
- (IBAction)tapText:(id)sender {
NSLog(#"tap text view");
[self addBoundsSpringAnimationToView:self.movieTextView];
}
- (void) addBoundsSpringAnimationToView:(UITextView *)textView {
POPSpringAnimation *anim = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerBounds];
if (expand) {
NSLog(#"expand");
self.bgUIImageView.hidden = YES;
self.blurredImageView.hidden = NO;
anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 0.0f, 320.0f, 807.0f)];
anim.springBounciness = 18;
} else {
NSLog(#"Shrink");
self.bgUIImageView.hidden = NO;
self.blurredImageView.hidden = YES;
anim.toValue = [NSValue valueWithCGRect:CGRectMake(0, 355.0f, 320.0f, 225.0f)];
}
expand = !expand;
anim.springSpeed = 10;
[textView pop_addAnimation:anim forKey:#"popBounds"];
}
Is it related to the Facebook Pop animation?
Thanks!

Animate UIView height from bottom to top

I'm doing a simple animation of UIView height so that it reveals.
By default it seems to be revealing from top to bottom, and I want it to reveal bottom to top.
I have the UIView anchored to the bottom of the screen.
I'm sure it something simple i'm missing..... any tips?
Thanks
I really think the simplest way to accomplish this would be to animate BOTH the height and the y properties of the view. If they happen along the same curve, it should look completely seamless to the user. As you are animating the height to 0, also animate the y component to the original y + the original height.
UIView *view = ...;
float originalY = view.frame.origin.y;
float originalH = view.bounds.size.height;
[UIView animateWithDuration:1.2f delay:1.0f options:UIViewAnimationCurveEaseInOut animations:^{
view.frame = CGRectMake(view.frame.origin.x, (originalY + originalH), view.bounds.size.width, 0);
}completion:^(BOOL finished) {
NSLog(#"Animation is complete");
}];
I believe this would give the look and feel of a collapsing view. I haven't tried this out in code, but I see no reason why it wouldn't be possible like this.
hide under bottom
[self animateViewHeight:myView withAnimationType:kCATransitionFromBottom];
for reverse animation
[self animateViewHeight:myView withAnimationType:kCATransitionFromTop];
...
- (void)animateViewHeight:(UIView*)animateView withAnimationType:(NSString*)animType {
CATransition *animation = [CATransition animation];
[animation setType:kCATransitionPush];
[animation setSubtype:animType];
[animation setDuration:0.5];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[[animateView layer] addAnimation:animation forKey:kCATransition];
animateView.hidden = !animateView.hidden;
}
Like a dog with a bone I figured this out....
Instead of animating the frame height, I applied a transform to the view and set the anchor point of the layer.
//set the anchor point to the bottom of the view
[self setAnchorPoint:CGPointMake(0.5, 1.0) forView:hostView];
//Scale the height to close to zero
hostView.transform = CGAffineTransformMakeScale(1, 0.00001);
If I put 0 as the y scale, the view behaves weird.... at the end of the animation i just set it to hidden.
On the way back up I just use the Identity Transform (reset it)
hostView.transform = CGAffineTransformIdentity;
Note that changing my anchor point shifted the position of my view. See this post for the setAnchorPoint method which normalises the view after setting the anchorPoint
Changing my CALayer's anchorPoint moves the view
Instead you could try putting it in a view with clipsToBounds = YES and then animate it from the bottom to the middle of the view, like so:
viewToAnimate.frame = CGRectMake(viewToAnimate.frame.origin.x,
viewToAnimate.superview.frame.size.height,
viewToAnimate.frame.size.width,
viewToAnimate.frame.size.height);
[UIView animateWithDuration:0.5 animations:^{
viewToAnimate.center = viewToAnimate.superview.center;
}];
This way, you don't have to set the height to 0, and it solves any problems with autoresizing within the view.
As requested, this is the code that I'm using... I'm using a CAKeyFrameAnimation, which may be a bit more than what you're looking for. It would probably work the same with a CABasicAnimation, I'm just showing you this code because I already have it written.
-(id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
springLayer = [[CALayer alloc] init];
springLayer.backgroundColor = [UIColor redColor].CGColor;
springLayer.anchorPoint = CGPointMake(0, 1);
springLayer.frame = CGRectMake(125, 285, 100, 115);
[springLayer setNeedsDisplay];
[self.layer addSublayer:springLayer];
[self test];
}
return self;
}
-(void)test {
CAKeyframeAnimation *heightAnim = [[CAKeyframeAnimation alloc] init];
heightAnim.duration = 3;
heightAnim.removedOnCompletion = NO;
heightAnim.fillMode = kCAFillModeForwards;
heightAnim.beginTime = CACurrentMediaTime() + 0.25;
NSMutableArray *v = [[NSMutableArray alloc] init];
NSMutableArray *t = [[NSMutableArray alloc] init];
float dest = 250;
float difference = 135;
while (difference > 1.0) {
[v addObject:[NSNumber numberWithFloat:dest-difference]];
[t addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
difference *= 0.7;
[v addObject:[NSNumber numberWithFloat:dest+difference]];
[t addObject:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut]];
difference *= 0.7;
}
heightAnim.values = v;
heightAnim.timingFunctions = t;
[springLayer addAnimation:heightAnim forKey:#"bounds.size.height"];
}
one way I've done it with an AdWhirlView, hide it below the screen, then animate it up;
AdWhirlView *adWhirlView = [AdWhirlView requestAdWhirlViewWithDelegate:self];
adWhirlView.delegate = self;
adWhirlView.frame = CGRectMake(0, 430+kAdWhirlViewHeight, kAdWhirlViewWidth, kAdWhirlViewHeight);
[self.parentViewController.view insertSubview:adWhirlView belowSubview:self.view];
[UIView beginAnimations:#"AdWhirlIn" context:nil];
[UIView setAnimationDuration:.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
adWhirlView.frame = CGRectMake(0, 430, kAdWhirlViewWidth, kAdWhirlViewHeight);
[UIView commitAnimations];

How can I access the standard viewForHeaderInSection for a tableView?

I've got an indexed UITableView with individual sections. I would like to use a different background color for the header views in each section. I know I can completely roll my own view by implementing tableView:viewForHeaderInSection: (for example, see question # 2898361), but that seems to be "too much work" to me - the standard view looks fine, I would just have to change its background color.
But how do I access this standard view? I can't use [super tableView:viewForHeaderInSection:] because this is a question of implementing a protocol and not an issue of inheritance. Any other way I can get the standard view?
I'm almost certain you can't do this easily. I used one of my tech support request on my dev account recently asking about altering the background and borders of UITableView sections. The apple engineer told me that this really wasn't an easy thing to do, and even if you managed to do it, you would probably affect performance. He also pointed me to cocoawithlove and an article about editing uitableviews:
http://cocoawithlove.com/2009/08/adding-shadow-effects-to-uitableview.html
Really, creating your own header isn't that much effort. Below is some code I pulled out of one of my projects - it was commented out, so might not work straight away - but you can get the idea:
- (CAGradientLayer *) greyGradient {
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.startPoint = CGPointMake(0.5, 0.0);
gradient.endPoint = CGPointMake(0.5, 1.0);
UIColor *color1 = [UIColor colorWithRed:255.0f/255.0f green:255.0f/255.0f blue:255.0f/255.0f alpha:1.0];
UIColor *color2 = [UIColor colorWithRed:240.0f/255.0f green:240.0f/255.0f blue:240.0f/255.0f alpha:1.0];
[gradient setColors:[NSArray arrayWithObjects:(id)color1.CGColor, (id)color2.CGColor, nil]];
return gradient;
}
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
CGFloat width = CGRectGetWidth(tableView.bounds);
CGFloat height = [self tableView:tableView heightForHeaderInSection:section];
UIView *container = [[[UIView alloc] initWithFrame:CGRectMake(0,0,width,height)] autorelease];
container.layer.borderColor = [UIColor grayColor].CGColor;
container.layer.borderWidth = 1.0f;
CAGradientLayer *gradient = [self greyGradient];
gradient.frame = container.bounds;
[container.layer addSublayer:gradient];
UILabel *headerLabel = [[[UILabel alloc] initWithFrame:CGRectMake(12,0,width,height)] autorelease];
headerLabel.backgroundColor = [UIColor clearColor];
headerLabel.font= [UIFont boldSystemFontOfSize:19.0f];
headerLabel.shadowOffset = CGSizeMake(1, 1);
headerLabel.textColor = [UIColor whiteColor];
headerLabel.shadowColor = [UIColor darkGrayColor];
NSString *title = [self tableView:tableView titleForHeaderInSection:section];
headerLabel.text = title;
return container;
}
Make sure to
#import <QuartzCore/QuartzCore.h>
By the way... this isn't supposed to mimic the look of the standard headers - its just an example. But I'm sure with a bit of trial and error you could alter this to mimic the standard ones and then change the colors slightly.
Although the other answers correctly point out you cannot access the default view to make simple modifications to it, if you have nothing to customize for a particular section header, you can return nil from tableView:viewForHeaderInSection: and the table view will use the default view.
This is helpful if you only need to customize some of your headers.
For whatever reason this is undocumented.
There is one problem with #bandejapalsa solution: the previous cell's separator is still visible with this implementation where as it is not on the default iOS sectionHeaderView. The solution I found was to use a CALayer and offset it by 1 pix. The image needs to be 1pix taller than the view frame itself.
// Create the view for the header
CGRect aFrame =CGRectMake(0, 0, tableView.contentSize.width, IMIUICustomisation.sectionHeaderViewHeight);
UIView * aView = [[UIView alloc] initWithFrame:aFrame];
aView.backgroundColor = UIColor.clearColor;
// Create a stretchable image for the background that emulates the default gradient, only in green
UIImage *viewBackgroundImage = [[UIImage imageNamed:#"greenheader.png"] stretchableImageWithLeftCapWidth:12 topCapHeight:0];
// Cannot set this image directly as the background of the cell because
// the background needs to be offset by 1pix at the top to cover the previous cell border (Alex Deplov's requirement ^_^)
CALayer *backgroungLayer = [CALayer layer];
backgroungLayer.frame = CGRectMake(0, -1, tableView.contentSize.width, IMIUICustomisation.sectionHeaderViewHeight+1);
backgroungLayer.contents = (id) viewBackgroundImage.CGImage;
backgroungLayer.masksToBounds = NO;
backgroungLayer.opacity = 0.9;
[aView.layer addSublayer:backgroungLayer];
// Take care of the section title now
UILabel *aTitle = [[UILabel alloc] initWithFrame: CGRectMake(10, 0, aView.bounds.size.width-10, aView.bounds.size.height)];
aTitle.text = [delegate tableView:tableView titleForHeaderInSection:section];
aTitle.backgroundColor = UIColor.clearColor;
aTitle.font = [UIFont boldSystemFontOfSize:18];
aTitle.textColor = UIColor.whiteColor;
// Text shadow
aTitle.layer.shadowOffset = CGSizeMake(0, 1);
aTitle.layer.shadowRadius = .2;
aTitle.layer.masksToBounds = NO;
aTitle.layer.shadowOpacity = 0.5;
aTitle.layer.shadowColor = IMIUICustomisation.selectedElementTextShadowColor.CGColor;
[aView addSubview:aTitle];
return aView;

Resources