Basically I want to remove all objects from a UIScrollView and I haven't yet found a solution to it because a simple "removeAllObjects" command doesn't work. Does anyone have an idea how to do it?
Even easier:
[[scrollView subviews] makeObjectsPerformSelector:#selector(removeFromSuperview)];
The easiest way:
for(UIView *subview in [scrollView subviews]) {
[subview removeFromSuperview];
}
Two solutions would be, without removing the scrollbars:
Add a tag to all of your subviews, remove them by using those tags.
Implementation:
Place this above your class
#define XPScrollViewSubviewStartTag 100
When you add the objects
for(NSInteger = 0;i<[viewArray count];i++){
UIView* view = [viewArray objectAtIndex:i];
view.tag = XPScrollViewSubviewStartTag + i;
[scrollView addSubview:view];
}
When you later want to delete the views use
for(UIView* view in [scrollView subviews]){
if(view.tag >= XPScrollViewSubviewStartTag)
[view removeFromSuperview];
}
Create a custom UIView class
When you want to remove the views
for(id view in [scrollView subviews]){
if(![view isKindOfClass:[CustomView class]])
continue;
//not necessary, but just to make things understandable
CustomView* customView = (CustomView*)view;
[customView removeFromSuperview];
}
Oritm's solution is nice, but if you don't want to bother using tags, you can manually remove which views you want to remove from the scrollview. This will assume that you know which view to remove. For example, my scrollview only has UILabels so when I run the following:
// This will remove the scrollview but the scrollbars will remain
for (UIView *subview in [self.detailsExpander.scrollView subviews]) {
if ([NSStringFromClass([subview class]) isEqualToString:#"UILabel"])
[subview removeFromSuperview];
}
This will only remove all the labels but keep the scrollbars (which are image views). Note: this won't work if you want to keep specific image views while at the same time you want to keep the scrollbars.
Related
I want to have precise control over the custom view I add to my UINavigationController toolbar. More specifically.. i want to display a UILable ontop of the items in my toolbar.
I have a toolbarItems initially set up with some UIBarButtonItems. The effect I'm trying to achieve is programmatically expand the height of the toolbar, and then display a UILabel ontop of the rest of the buttons.. this is what I currently have:
-(void)expandToolBar:(NSString *)title {
UIToolbar* toolBar =self.navigationController.toolbar;
CGRect toolbarFrame = toolBar.frame;
[UIView animateWithDuration:0.25f delay:0
options:UIViewAnimationOptionLayoutSubviews animations:^{
// expand toolbar frame vertically
[toolBar setFrame:
CGRectMake(toolbarFrame.origin.x,
toolbarFrame.origin.y-15,
toolbarFrame.size.width,
toolbarFrame.size.height + 15)];
} completion:^(BOOL finished){
[UIView animateWithDuration:0.50f animations:^{
// some code here to move the existing toolbar items lower
// ie to make space for the label
UILabel* label = [[UILabel alloc] initWithFrame:labelFrame];
[label setBackgroundColor:[UIColor clearColor]];
label.text = title;
UIBarButtonItem *labelItem = [[UIBarButtonItem alloc]
initWithCustomView:label];
// add label to toolbar
NSMutableArray *newItems = [self.toolbarItems mutableCopy];
[newItems addObject:labelItem];
self.toolbarItems = newItems;
}];
}];
}
the result of this is that all the existing buttons get squashed, and the label takes their place. The problem is that If I try to get a little too creative and start manually messing with the subviews of the toolbar, I start wandering into undocumented API land, something Apple won't tolerate. Ideas?
What's your actual question? If what you're doing is legal or not? I use some similar tricks to get from the UIBarButtonItem to the view that is represented from it, and it has never been a problem.
For example, I use following snippet without any issues. Technically this isn't using private API per so, but relying on undocumented view structure and here also part of the class names, so you really should know what you're doing. Please also file a radar that UIBarButtonItem is messed up and misses an obvious flag to get to the actual view.
static UIView *PSToolbarViewForBarButtonItem(UIToolbar *toolbar, UIBarButtonItem *barButtonItem) {
UIView *barButtonView = nil;
for (UIControl *subview in toolbar.subviews) {
if ([NSStringFromClass([subview class]) hasPrefix:#"UIToolbarB"] && [subview isKindOfClass:[UIControl class]]) {
for (UIBarButtonItem *aBarButtonItem in [subview allTargets]) {
if (barButtonItem == aBarButtonItem) { barButtonView = subview; break; }
}
}
}
return barButtonView;
}
Also, if you go that route, write code that will fail gracefully if for any reason the view for the toolbar can't be found. I know some apps that go my route, while lots of others don't even bother and simply write their own code to create a toolbar.
I am trying to implement a view with a mainScrollView. Inside that mainScrollView I have 10 UIView, each one is having subScrollView.Now, I want to add many (around 150 to 200) views(imageview,label,textview,uiview,webview,etc) inside each subScrollView.
something like this:
Timeline ww2 and
History of Jazz
I have tried following:
Method 1:
Lazy loading for each subScrollView to add views.
code for this:
-(void)loadInnerScrollViewLazily:(int)tag pageNo:(int)pageNo{
/// this array will contain all the views for subScrollView
NSMutableArray *array=[NSMutableArray array];
array=[self.tlScrollContentArray objectAtIndex:tag];
if (pageNo < 0)
return;
if (pageNo >= [array count])
return;
UIView *controller = [array objectAtIndex:pageNo];
CGRect frame = [[array objectAtIndex:0] frame];
frame.origin.x = 350;
frame.origin.y = 0;
controller.frame = frame;
for (UIView* view in [mainScrollView subviews]) {
for (UIScrollView* scroll in [view subviews]) {
if ([scroll isKindOfClass:[UIScrollView class]]) {
if (scroll.tag == tag+11) {
[scroll addSubview:controller]; /// adds view in particular subScrollView
}
}
}
}
}
This method is called in scrollViewDidScroll method, which checks perticular scrollView and removes view which is out of screen and then it will add views depending upon the condition.
This code is slowing down app as scrolling rate increases.
Method 2:
With the reference of this tutorial:
Add three UIView(each with subScrollView) in to mainScrollView. Updating content of subScrollView depending upon the condition.
But this solution is also slowing down my app as it is updating subScrollView every time it appears.
Is there any library or code available to manage this.
Any help will be appreciated.
Thanks in Advance!
I think your code has many, many errors, and you would need to post your complete source to be helped. It's unclear if you are ever removing images from your scrollview. If not, that is your problem.
Look at Apple's sample PhotoScroller code: http://developer.apple.com/library/ios/#samplecode/PhotoScroller/Introduction/Intro.html
This dequeues and manages the ImageViews on the scrollview... I implemented something similar based on this.
Experts!!
Please help me in this!!!!!
In my project I am programatically creating multiple UIImageviews. I want to add Pinch gesture on each ImageView.i
My code is below....
-(IBAction)addSymbols:(UIButton *)sender{
if (sender.tag ==1) {
CGRect frame =sender.frame;
[self.imgView setFrame:frame];
self.imgView.userInteractionEnabled = YES;
[imgView setImage:[sender imageForState:UIControlStateNormal]];
[self.view addSubview:imgView];
[self addGestureRecognizersToPiece:imgView];}
Like this I am adding 5 imageViews. Now code of [self addGestureRecognizersToPiece:imgView]
- (void)addGestureRecognizersToPiece:(UIView *)piece{
UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(scalePiece:)];
[piece addGestureRecognizer:pinchGesture];
//In above add gesture on UIImageView directly its not working..
//if replace this line by [self.view addGestureRecognizer:pinchGesture]; it's working..
//but while pinch whole UIview scale
[pinchGesture setDelegate:self]; }
Another bug is UIPinchgesture is not correctly working on multiple UIImageViews individually.
So please help me.. Reply me soon..
- (void) scalePiece:(UIPinchGestureRecognizer*)paramSender{
if (paramSender.state == UIGestureRecognizerStateEnded) {
self.currentScale = paramSender.scale;
}
else if (paramSender.state == UIGestureRecognizerStateBegan && self.currentScale != 0.0f){
paramSender.scale = self.currentScale; }
if (paramSender.scale != NAN && paramSender.scale != 0.0){
[paramSender view].transform= CGAffineTransformMakeScale(paramSender.scale, paramSender.scale);
}
As you told me I added userInteractionEnabled = YES for each UIImageView. I mention in my code also
You should enable userInteractionEnabled on the UIImageViews. This is disabled by default.
If you need more help, please show us your scalePiece:code.
Add the imageViews as subview of ScrollView.
Then set the scrollView zoomScale of the scrollView.
Also implement the delegate methods of scrollView especially the one below.
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
return the imageView object you want to zoom.
refer these
UIScrollView
UIScrollViewDelegate
What I want to do is ideally loop through all buttons in a UIView (I have a lot, over 40 buttons), and depending on the tag, change the image that the button is displaying. Does anyone know how I can do this?
Thanks!!!!
I would say use the subviews property, as devilaether said, but do an additional check to make sure the subview is a UIButton before you do anything else with it:
for(UIView *view in [rootView subviews]) {
if([view isKindOfClass:[UIButton class]]) {
if([view tag] == 0) {
// First image
} /* ... */
else {
NSLog(#"didn't recognize tag");
}
} else {
NSLog(#"view is not a button");
}
}
You could also make your life easier if you stored an NSArray somewhere with the UIButtons you wanted to iterate over; this would take out the isKindOfClass: check. See the NSObject protocol for more info.
Use the subview property of the UIView containing the buttons. For each UIView element in that NSArray, inspect the tag property. If the tag matches what your logic needs, change the image displayed in that UIView instance - which in this case is one of the buttons.
for(i=0; i<numberOfTags; i++){
UIButton *tempBtn = [yourView viewWithTag:i];
[tempBtn setImage:yourImage];
}
I added one UIScrollView in my project... and I added 10 more button "fieldButton" once, then the same UIScrollView I want add other 5 button. it I try to do this first added 10 button also coming in the scrollview .. how to remove first added 10 button before adding other item. in the same scrollview...
if(a == 1){
for(int i = 0; i< 10; i++){
UIButton *fieldButton_area = [[Mos_component alloc]getComboButton:title andFrame:CGRectMake(0, y, 180, 40)];
[fieldButton_area addSubview:cid];
[fieldButton_area addTarget:self action:#selector(get_Area:) forControlEvents:UIControlEventTouchUpInside];
[state_scroll addSubview:fieldButton_area];
}
}
else{
UIButton *fieldButton_state = [[Mos_component alloc]getComboButton:title andFrame:CGRectMake(0, y, 180, 40)];
[fieldButton_state addSubview:cid];
[fieldButton_state addTarget:self action:#selector(get_Area:) forControlEvents:UIControlEventTouchUpInside];
[state_scroll addSubview:fieldButton_state];
}
If you want just to clear your scrollview (i.e. remove all its subviews) then you can do that following way:
for (UIView* subView in [state_scroll subviews])
[subView removeFromSuperView];
If you want to remove some specific views you can check its types:
for (UIView* subView in [state_scroll subviews])
if ([subView isKindOfClass:[Mos_component class]]) // remove Mos_components only
[subView removeFromSuperView];
You can also assign tag property to you views and remove them following way:
[[fieldButton_area viewWithTag:yourTag] removeFromSuperView];
Also note that you must release your buttons somewhere or you will get memory leak.
You could also try animating the button(s) off of the screen or set the alpha's to 0 then add the new UIButton's to the view. This may use more memory, but in some cases look better.
[UIView BeginAnimation];
// set time and speed here
// Perform animation here
[UIView setAnimationDidStopSelector /* here call the method for the new button's animation into the view*/];
[UIView CommitAnimations];
// Then set the button's enabled property to NO
button.enabled = NO;
I hope this is of some assistance