iPhone: TableView inside UIScrollview, show vaccillating scrollbars around - iphone

I have added some table and other vies in a scrollview. scrolling in tables are working fine. But in the parent scrollview, when scrolling, a vacillating vertical scrollbars are shown, sometimes it even come to the middle of the screen. sometime show at the left side of the screen. and not limited to the vertical scrollbar region. When I set the showsVerticalScrollIndicator = NO, it is not shown. But do you know why the scrollbar is moving around.
DashboardView is a subclass of UIScrollView.
dashboard=[[DashboardView alloc] initWithFrame:fullScreenRect];
dashboard.contentSize = CGSizeMake(320,700); // must do!
dashboard.showsVerticalScrollIndicator = YES;
dashboard.bounces = YES;
self.view = dashboard;
#implementation DashboardView
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void) layoutSubviews{
NSArray *views = self.subviews;
[UIView beginAnimations:#"CollapseExpand" context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
UIView *view = [views objectAtIndex: 0];
CGRect rect = view.frame;
for (int i = 1; i < [views count]; i++ ) {
view = [views objectAtIndex:i];
view.frame = CGRectMake(rect.origin.x, rect.origin.y + rect.size.height, view.frame.size.width, view.frame.size.height);
rect = view.frame;
}
[UIView commitAnimations];
}

Remember that scrollbars is subviews of scroll too. Exclude it from views array, before doing something with views.

Yap. that solved my problem. It seems Scrollbars are a kind of UIImageView. If anybody need it, this is my new code which works fine.
(void) layoutSubviews{
NSArray *views = self.subviews;
[UIView beginAnimations:#"CollapseExpand" context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn];
//CGRect fullScreenRect=[[UIScreen mainScreen] applicationFrame];
// [self.view insertSubview:balanceView belowSubview:profileView];
UIView *view = [views objectAtIndex: 0];
CGRect rect = view.frame;
for (int i = 1; i < [views count]; i++ ) {
view = [views objectAtIndex:i];
if ([view isMemberOfClass: [UIView class] ]) {
//CFShow(view);
view.frame = CGRectMake(rect.origin.x, rect.origin.y + rect.size.height, view.frame.size.width, view.frame.size.height);
rect = view.frame;
}
}
[UIView commitAnimations];
}

Related

UIAnimation - Show UIView from button.frame.origin.y

I have a UIButton somewhere on my view. On touch event of button I making a UIView appear. The UIAnimation I have used make the view appear from top of window. But I want it to appear from button.frame.origin.y . Before touching the button the view is not visible. On touching the button view should start appearing from above position.
Here is the code :
-(IBAction) ShowInfowView:(id)sender{
CGRect rect = viewInfo.frame;
rect.origin.y = rect.size.height - rect.size.height+58.0;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.70];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
viewInfo.frame = rect;
[UIView commitAnimations];
}
This is how I am hiding the view again :
-(IBAction) HideInfoView:(id)sender{
CGRect rect = viewInfo.frame;
rect.origin.y = -rect.size.height;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.70];
[UIView setAnimationDelay:0.0];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
viewInfo.frame = rect;
[UIView commitAnimations];
}
In viewDidLoad I am doing the following :
CGRect rect = viewInfo.frame;
rect.origin.y = -rect.size.height;
viewInfo.frame = rect;
UPDATE:
Please see this example. Here view is appearing from top of screen. I want it to appear from button y axis. For that matter please consider button y position a bit upwards.
So you want a slide-in effect, but not from the top of the screen, just some arbitrary value?
One way to do it:
1) You should create a view that has the dimensions and position of your desired view AFTER animation finishes, we'll call it baseview.
2) Set this baseview property clipsToBounds to YES. This will make all subviews that are outside of the baseview's frame invisible.
3) Add your animating view as a subview of the baseview, but set the frame so it is invisible (by plcacing it above the baseview):
frame = CGRectMake(0, -AnimViewHeight, AnimViewWidth, AnimViewHeight);
4) Animate the animview frame:
//put this inside of an animation block
AnimView.frame = CGRectMake(0, 0, AnimViewWidth, AnimViewHeight);
EDIT:
Example:
//define the tags so we can easily access the views later
#define BASEVIEW_TAG 100
#define INFOVIEW_TAG 101
- (void) showInfo
{
//replace the following lines with preparing your real info view
UIView * infoView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
[infoView setBackgroundColor: [UIColor yellowColor]];
[infoView setTag: INFOVIEW_TAG];
//this is the frame of the info view AFTER the animation finishes (again, replace with real values)
CGRect targetframe = CGRectMake(100, 100, 100, 100);
//create an invisible baseview
UIView * baseview = [[UIView alloc] initWithFrame:targetframe];
[baseview setBackgroundColor: [UIColor clearColor]];
[baseview setClipsToBounds: YES]; //so it cuts everything outside of its bounds
[baseview setTag: BASEVIEW_TAG];
//add the nfoview to the baseview, and set it above the bounds frame
[baseview addSubview: infoView];
[infoView setFrame:CGRectMake(0, -infoView.bounds.size.height,
infoView.bounds.size.width, infoView.bounds.size.height)];
//add the baseview to the main view
[self.view addSubview: baseview];
//slide the view in
[UIView animateWithDuration: 1.0 animations:^{
[infoView setFrame: baseview.bounds];
}];
//if not using ARC, release the views
[infoview release];
[baseview release];
}
- (void) hideinfo
{
//get the views
UIView * baseView = [self.view viewWithTag: BASEVIEW_TAG];
UIView * infoView = [baseView viewWithTag: INFOVIEW_TAG];
//target frame for infoview - slide up
CGRect out_frame = CGRectMake(0, -infoView.bounds.size.height,
infoView.bounds.size.width, infoView.bounds.size.height);
//animate slide out
[UIView animateWithDuration:1.0
animations:^{
[infoView setFrame: out_frame];
} completion:^(BOOL finished) {
[baseView removeFromSuperview];
}];
}
I have done exactly what you're trying in my recent project.
The following steps should make this work:
1. In your viewDidLoad: you init your viewToFadeIn like this:
viewToFadeIn = [[UIView alloc] initWithFrame:CGRectMake(20,self.view.frame.size.height+10, self.view.frame.size.widh-40, 200)];
//its important to initalize it outside your view
//your customization of this view
[self.view addSubview:viewToFadeIn];
2.your ShowInfowView: Method should look like this:
` -(IBAction) ShowInfowView:(id)sender{
[UIView beginAnimations:#"fadeIn" context:NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(animationFinished:finished:context:)];
viewToFadeIn.transform = CGAffineTransformMakeTranslation(0, -290);
//290 is in my case, try a little for your correct value
[UIView commitAnimations];
}
3.yourHideInfoView:` Method looks like this
-(IBAction) HideInfoView:(id)sender{
[UIView beginAnimations:#"fadeOut" context:NULL];
[UIView setAnimationDuration:0.25];
[UIView setAnimationDelegate:self];
viewToFadeIn.transform = CGAffineTransformMakeTranslation(0, 0);
[UIView commitAnimations];
}
EDIT:
4. animationFinishedMethod:
- (void)animationFinished:(NSString *)animationID finished:(BOOL)finished context:(void *)context{
if ([animationID isEqual:#"fadeIn"]) {
//Do stuff
}
if ([animationID isEqual:#"fadeOut"]) {
//Do stuff
}
}
SEE THIS
This should do the trick. Good luck
Your problem is not clear (for me).
What is this?
rect.origin.y = rect.size.height - rect.size.height+58.0;
Is 58 origin of your UIButton?
You should use sender.frame etc
Use blocks to animate like this
[UIView animateWithDuration:0.5f animations:^{
// Animation here
} completion:^(BOOL finished) {
// onComplete
}];
- (void) slideIn{
//This assumes the view and the button are in the same superview, if they're not, you'll need to convert the rects
//I'm calling the animated view: view, and the button: button...easy enough
view.clipToBounds = YES;
CGRect buttonRect = button.frame;
CGRect viewRect = CGRectMake(buttonRect.origin.x, buttonRect.origin.y + buttonRect.size.height, view.bounds.size.width, 0);
CGFloat intendedViewHeight = view.height;
view.frame = viewRect;
viewRect.size.height = intendedViewHeight;
[UIView animateWithDuration:.75 delay:0.0f options:UIViewAnimationOptionCurveEaseOut animations:^{
view.frame = viewRect;
}completion:nil];
}
This will cause the the view to appear to slide out from under the button. To slide the view back in, you just reverse the animations. If you wish to slide it up from the button, you'll need to make sure your starting 'y' is the 'y' value of the button (rather than the 'y' + 'height') and animate both the height and y values of the view that needs animating.

UITableView won't scroll after keyboard is hidden

I have a UITableView with custom cells. Based on an answer to this question I am resizing the view when to accommodate the keyboard and resizing when the keyboard is dismissed. After dismissing the keyboard the table view no longer scrolls.
These are the methods called when showing and hiding the keyboard:
-(void)keyboardWillShow:(NSNotification *)note
{
NSDictionary* userInfo = [note userInfo];
NSValue* keyboardFrameValue = [userInfo objectForKey:#"UIKeyboardBoundsUserInfoKey"];
if (!keyboardFrameValue) {
keyboardFrameValue = [userInfo objectForKey:#"UIKeyboardFrameEndUserInfoKey"];
}
// Reduce the tableView height by the part of the keyboard that actually covers the tableView
CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;
CGRect viewRectAbsolute = [myTableView convertRect:myTableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];
CGRect frame = myTableView.frame;
frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];
myTableView.frame = frame;
[UIView commitAnimations];
UITableViewCell *textFieldCell = (id)((UITextField *)self.textFieldBeingEdited).superview.superview;
NSIndexPath *textFieldIndexPath = [myTableView indexPathForCell:textFieldCell];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[myTableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
}
-(void)keyboardWillHide:(NSNotification *)note
{
CGRect keyboardRect = [[[note userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
NSTimeInterval animationDuration = [[[note userInfo] objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];
CGRect frame = self.myTableView.frame;
frame.size.height += keyboardRect.size.height + 49;
[UIView beginAnimations:#"ResizeForKeyboard" context:nil];
[UIView setAnimationDuration:animationDuration];
self.myTableView.frame = frame;
[UIView commitAnimations];
myTableView.scrollEnabled = YES;
}
Any ideas what I am missing?
I've used the same question you link to to solve the same problem. It's been working great for me although I don't remember how much of the original code I ended up using.
For your problem, (though I imagine you've tried this) the first thing that comes to mind is to look in your code to see if your doing
self.tableView.scrollEnabled = NO;
and if so you should verify that you have a corresponding statement somewhere sets it back to YES; in fact you might set scrollEnabled to YES in keyboardWillHide just to test if that helps.
The problematic line is:
frame.size.height += keyboardRect.size.height + 49;
it should be:
frame.size.height += keyboardRect.size.height - self.navigationController.toolbar.frame.size.height;

How to animate a UITextView that is a subview?

I am trying to animate a UITextView (myTextView) that is a subview inside a UIScrollView (scrollView).
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:myTextView cache:YES];
[scrollView addSubview:myTextView];
[UIView commitAnimations];
myTextView appears without animation!
What kind of animation do you want to do? If you want to fade in, for example, you have to do
[scrollView addSubview:myTextView];
myTextView.alpha = 0.0;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionCurlDown forView:myTextView cache:YES];
myTextView.alpha = 1.0;
[UIView commitAnimations];
You can change several properties (e.g.: frame, transform) to make animations.
http://www.4shared.com/dir/-PGqZEXR/zoominzoomout.html just add this file with your project and call it through this functions
here im2 is UIVIEW and i paste image on it then passing this through view didload like this
- (void)viewDidLoad {
[self loadFlowersInView:im2];
[self.view addSubview:im2];
}
now attach this function like this
- (void) loadFlowersInView: (UIView *) backdrop {
NSString *create_button = nil; // Add the flowers to random points on the screen
for (int i = 0; i < 1; i++) {
MagPicAppDelegate *appdelegate = (MagPicAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *whichFlower = appdelegate.imageName;
UIImage *stemp = [UIImage imageNamed:#"approve.png"];
DragView *dragger = [[DragView alloc] initWithImage:stemp];
dragger.userInteractionEnabled = YES;
dragger.center = CGPointMake(160.0f, 140.0f);
[im2 addSubview:dragger];
[dragger release];
}
[self.view addSubview:im2];
[im2 release];
}

keyboard hiding my textview

i have a simple app, it consist of 2 textview, 1 uiview as a coretext subclass, and then 1 scrollview. the others part is subviews from scrollview. I use this scrollview because i need to scroll the textviews and uiview at the same time. I already scroll all of them together, but the problem is, the keyboard hiding some lines in the textview. I have to change the frame of scrollview when keyboard appear, but it still not help.
This is my code :
UIScrollView *scrollView;
UIView *viewTextView;
UITextView *lineNumberTextView;
UITextView *codeTextView;
-(void) viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(keyboardWillAppear:)
name:UIKeyboardWillShowNotification
object:nil];
[[NSNotificationCenter defaultCenter]
addObserver:self
selector:#selector(keyboardWillDisappear:)
name:UIKeyboardWillHideNotification
object:nil];
self.scrollView.frame = CGRectMake(0, 88, self.codeTextView.frame.size.width,
self.codeTextView.frame.size.height);
scrollView.contentSize = CGSizeMake(self.view.frame.size.width, viewTextView.frame.size.height);
[scrollView addSubview:viewTextView];
CGAffineTransform translationCoreText = CGAffineTransformMakeTranslation(60, 7);
[viewTextView setTransform:translationCoreText];
[scrollView addSubview:lineNumberTextView];
[self.scrollView setScrollEnabled:YES];
[self.codeTextView setScrollEnabled:NO];
}
-(void)keyboardWillAppear:(NSNotification *)notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[[notification userInfo]
objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
CGRect keyboardEndingUncorrectedFrame = [[[notification userInfo]
objectForKey:UIKeyboardFrameEndUserInfoKey ] CGRectValue];
CGRect keyboardEndingFrame =
[self.view convertRect:keyboardEndingUncorrectedFrame
fromView:nil];
self.scrollView.frame = CGRectMake(0, 88, self.codeTextView.frame.size.width,
self.codeTextView.frame.size.height - keyboardEndingFrame.size.height);
[UIView commitAnimations];
}
-(void)keyboardWillDisappear:(NSNotification *) notification {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:[[[notification userInfo]
objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
CGRect keyboardEndingUncorrectedFrame = [[[notification userInfo]
objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue];
CGRect keyboardEndingFrame =
[self.view convertRect:keyboardEndingUncorrectedFrame
fromView:nil];
self.scrollView.frame = CGRectMake(0, 88, self.codeTextView.frame.size.width,
self.codeTextView.frame.size.height + keyboardEndingFrame.size.height);
[UIView commitAnimations];
}
can somebody help me please?
UPDATE
this is a pic from this problem :
some text still hiding by the keyboard after i do my code
UPDATE AGAIN
i think the keyboard still hiding the text because i set the textview scroll enable to be NO. is that right??
i have add this code to the keyboardwillappear method
codeBuilderSelectedRange = self.codeTextView.selectedRange;
[self.viewTextViewScroll setContentOffset:CGPointMake(0, (CGFloat)codeBuilderSelectedRange.location) animated:YES];
but it just make the textview dissappear from the view...can somebody tell the answer?
#pragma mark -------------------------
#pragma mark TextView delegate Methods
- (void)textViewDidBeginEditing:(UITextView *)textView {
UIView *parentView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 60, 44)];
UIButton *infoButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 6, 60, 32)];
[infoButton setBackgroundImage:[UIImage imageNamed: #"back-btn.png"] forState:UIControlStateNormal];
[infoButton setTitle:#"Done" forState:UIControlStateNormal];
infoButton.titleLabel.font = [UIFont systemFontOfSize:13.0f];
[infoButton addTarget:self action:#selector(resignTextView) forControlEvents:UIControlEventTouchUpInside];
[parentView addSubview:infoButton];
[infoButton release];
UIBarButtonItem *customBarButtomItem = [[UIBarButtonItem alloc] initWithCustomView:parentView];
[parentView release];
self.navigationItem.rightBarButtonItem = customBarButtomItem;
[customBarButtomItem release];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView commitAnimations];
CGRect frame = self.scrollView.frame;
self.scrollView.frame.size.height = 206;
//[self.view setContentOffset:CGPointMake(0,320)];
}
- (void)resignTextView {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
[UIView commitAnimations];
CGRect frame = self.scrollView.frame;
self.scrollView.frame.size.height = 460;
[messageTextView resignFirstResponder];
self.navigationItem.rightBarButtonItem = nil;
}
Here is some code that I have used. Basically, what we're going to do is animate the position of the view whenever a UITextField gets focus. To do this, we must make our UIViewController a delegate of our UITextFields
The first delegate method you need to implement is - (void)textFieldDidBeginEditing:(UITextField *)textField
static const CGFloat KEYBOARD_ANIMATION_DURATION = 0.3;
static const CGFloat MINIMUM_SCROLL_FRACTION = 0.2;
static const CGFloat MAXIMUM_SCROLL_FRACTION = 0.8;
static const CGFloat PORTRAIT_KEYBOARD_HEIGHT = 216;
static const CGFloat LANDSCAPE_KEYBOARD_HEIGHT = 162;
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
CGRect textFieldRect = [self.view.window convertRect:textField.bounds
fromView:textField];
CGRect viewRect = [self.view.window convertRect:self.view.bounds
fromView:self.view];
CGFloat midline = textFieldRect.origin.y + 0.5
* textFieldRect.size.height;
CGFloat numerator = midline - viewRect.origin.y
- MINIMUM_SCROLL_FRACTION * viewRect.size.height;
CGFloat denominator = (MAXIMUM_SCROLL_FRACTION - MINIMUM_SCROLL_FRACTION)
* viewRect.size.height;
CGFloat heightFraction = numerator / denominator;
if (heightFraction < 0.0)
{
heightFraction = 0.0;
}
else if (heightFraction > 1.0)
{
heightFraction = 1.0;
}
UIInterfaceOrientation orientation =
[[UIApplication sharedApplication] statusBarOrientation];
if (orientation == UIInterfaceOrientationPortrait ||
orientation == UIInterfaceOrientationPortraitUpsideDown)
{
animatedDistance = floor(PORTRAIT_KEYBOARD_HEIGHT * heightFraction);
}
else
{
animatedDistance = floor(LANDSCAPE_KEYBOARD_HEIGHT * heightFraction);
}
CGRect viewFrame = self.view.frame;
viewFrame.origin.y -= animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
}
Now that the view has been 'pushed up' when a UITextField is selected, we want to make sure that we slide it back down when we're done:
- (void) textFieldDidEndEditing:(UITextField *)textField
{
CGRect viewFrame = self.view.frame;
viewFrame.origin.y += animatedDistance;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:KEYBOARD_ANIMATION_DURATION];
[self.view setFrame:viewFrame];
[UIView commitAnimations];
}
This was taken from one of my favorite Cocoa blogs, Cocoa With Love. Cheezy name, but Matt's got some great posts on Objective-C development.
Specifically for UITextView (not UITextField)
you may have a look at the following tutorial: http://codingcluster.blogspot.in/2012/03/iphone-make-uitextview-move-up-when.html
i have implemented it and it is working as expected(at least for me)

Any good way to position UITableViewCellEditingStyleDelete icon within a grouped tableview?

as title, can i position the UITableViewCellEditingStyleDelete button/icon to be within the tableviewcell of a grouped tableview rather than outside of it?
An excerpt from a Matt Gallagher blog post reveals a method
This is the original code to mimic the behavior you DON'T want:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[self setNeedsLayout];
}
- (void)layoutSubviews
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[super layoutSubviews];
if (((UITableView *)self.superview).isEditing)
{
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = EDITING_HORIZONTAL_OFFSET;
self.contentView.frame = contentFrame;
}
else
{
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = 0;
self.contentView.frame = contentFrame;
}
[UIView commitAnimations];
}
So if we made a change, we can make it do what you do want:
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
{
[self setNeedsLayout];
}
- (void)layoutSubviews
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationBeginsFromCurrentState:YES];
[super layoutSubviews];
if (((UITableView *)self.superview).isEditing)
{
//don't resize and and move your frame here
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = 0;
self.contentView.frame = contentFrame;
}
else
{
CGRect contentFrame = self.contentView.frame;
contentFrame.origin.x = 0;
self.contentView.frame = contentFrame;
}
[UIView commitAnimations];
}
You'll proabably have to tweak this, but it is a good start.