I have a search bar on top of a table view set up using auto layout like so:
_searchBar.translatesAutoresizingMaskIntoConstraints = NO;
_tableView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[_searchBar]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_searchBar)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"|[_tableView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_tableView)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[_searchBar][_tableView]|" options:0 metrics:nil views:NSDictionaryOfVariableBindings(_searchBar, _tableView)]];
Everything looks nice when I run it. But when I do _searchBar.showsScopeBar = YES; before I start editing the search bar, the search bar and table view do not resize automatically. Even when I do [_searchBar sizeToFit], the table view does not resize and move down. Why??
Note: I'm not putting the search bar as the table view's header; it's just a parent view and two subviews.
Note 2: I checked the intrinsicContentSize of _searchBar before and after I call _searchBar.showsScopeBar = YES; and the size does indeed change.
You have to invalidateIntrinsicContentSize:
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
searchBar.showsScopeBar = YES;
[searchBar invalidateIntrinsicContentSize];
[searchBar setShowsCancelButton:YES animated:YES];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
searchBar.showsScopeBar = NO;
[searchBar invalidateIntrinsicContentSize];
[searchBar setShowsCancelButton:NO animated:YES];
}
See UISearchBar's scope button won't show up iOS6
Related
self.refreshControl = [[UIRefreshControl alloc]init];
[self.objDiscussiontopic addSubview:self.refreshControl];
[self.refreshControl addTarget:self action:#selector(refreshTable) forControlEvents:UIControlEventValueChanged];
- (void)refreshTable {
//TODO: refresh your data
[self.refreshControl endRefreshing];
}
This is the code i am using to add refresh controller in my scroll view.
But when i pull down the scroll view the refresh control is not showing and the targeted method is also not called why ?
I am searching this for a while but didn't get any proper answer .
One more thing scrollview having VFL Constraint some thing like this :
//Pin scrolview to Parent View
[VFLConstraint allignSubViewViewHorizentallyWithSubView:self.objDiscussiontopic OverSuperView:[self view]];
[VFLConstraint allignSubViewViewVerticallyWithSubView:self.objDiscussiontopic OverSuperView:[self view] WithTopPading:[CommonFunction convertIphone6ToIphone5:0] AndBotomPading:[CommonFunction convertIphone6ToIphone5:57]];
+ (void)allignSubViewViewHorizentallyWithSubView:(UIView *)subView OverSuperView:(UIView *)superView{
NSDictionary *viewDict= NSDictionaryOfVariableBindings(subView);
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[subView]|" options:0 metrics: 0 views:viewDict]];
}
+ (void)allignSubViewViewVerticallyWithSubView:(UIView *)subView OverSuperView:(UIView *)superView WithTopPading:(float)topPading AndBotomPading:(float)bottomPading{
NSDictionary *viewDict= NSDictionaryOfVariableBindings(subView);
NSDictionary *metrics=[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithFloat:topPading],#"topPading",[NSNumber numberWithFloat:bottomPading],#"bottomPading", nil];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-topPading-[subView]-bottomPading-|" options:0 metrics: metrics views:viewDict]];
}
Try to:
[self.scrollView insertSubview:self.refreshControl atIndex:0];
Check the contentSize it can be less that frame size, if so use this line of code:
self.scrollView.alwaysBounceVertical = true
I don't think a UIRefreshControl is designed to work with plain scroll views. Apple's docs specifically refer to UITableViews when talking about refresh control.
You can look at third party pull to refresh libraries to add this to UIScrollView
I have 2 view controllers embedded in a view vertically. View controller A (uploader), and B (docList).
B contains a UICollectionView
All, methods except cellForItemAtIndexPath inside the datasource of the collection view get called correctly, and i double checked everything. There is 1 section. There are more than 0 rows. The size of the rows I return is smaller than the collection view, etc
Here's a diagram to illustrate the setup:
My issue is:
Unless i turn on setTranslatesAutoresizingMaskIntoConstraints to YES, cellForItemAtIndexPath will never be called. If i set that property to YES on the View Controller B's view, then it does get called. But the layout is then screwed up, because I am not using springs and struts. We only use constraints here.
Do you know what i can be doing wrong when embedding the view controller that contains the UICollectionView?
Here is the code that embeds the two view controllers' views, and sets them as child controllers:
- (MFFormBaseCell *)cellForComponent
{
self.cell = [[MFFormBaseCell alloc] initWithFrame:CGRectZero];
[self.cell addSubview: uploader.view];
[self.cell addSubview: docList.view];
UIView* uploaderView = uploader.view;
UIView* docListView = docList.view;
NSMutableArray* tempConstraints = [[NSMutableArray alloc]init];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: #"V:|-8-[uploaderView]-1-[docListView]-8-|"
options: NSLayoutFormatDirectionLeadingToTrailing metrics:nil
views: NSDictionaryOfVariableBindings(uploaderView, docListView)]];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: #"H:|-[uploaderView]-|"
options: NSLayoutFormatDirectionLeadingToTrailing metrics:nil
views: NSDictionaryOfVariableBindings(uploaderView)]];
[tempConstraints addObjectsFromArray:
[NSLayoutConstraint constraintsWithVisualFormat: #"H:|-[docListView]|"
options: NSLayoutFormatDirectionLeadingToTrailing metrics:nil
views: NSDictionaryOfVariableBindings(docListView)]];
uploaderConstraints = [tempConstraints copy];
[self.cell addConstraints: uploaderConstraints];
[self.embedder addChildViewController:uploader];
[uploader didMoveToParentViewController:self.embedder];
[self.embedder addChildViewController:docList];
[docList didMoveToParentViewController:self.embedder];
docList.view.frame = self.cell.bounds;
return self.cell;
}
And here is the code from View Controller B, that sets up the UICollectionView and a vertical flow layout for it.
- (void)modelDidLoad
{
_dataSource = [[MFCardDataSource alloc] initWithData: self.cardModel];;
UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
_collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:aFlowLayout];
[_collectionView setDelegate: self];
[_collectionView setDataSource:_dataSource];
[_collectionView setBackgroundColor:[UIColor clearColor]];
for (NSString* type in [MFCardCollectionModel typeArray])
[_collectionView registerClass:[MFImageCard class] forCellWithReuseIdentifier: type];
[_collectionView setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.view addSubview:_collectionView];
[self registerConstraintsForView:_collectionView];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
[super modelDidLoad];
}
And the contents of registerConstraintsForView:
-(void) registerConstraintsForView:(UIView*)collectionView
{
NSDictionary* metrics = #{ #"padding": #PADDING };
NSDictionary* views = NSDictionaryOfVariableBindings(_collectionView);
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|-padding-[_collectionView]-padding-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:metrics
views:views]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|-padding-[_collectionView]-padding-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:metrics
views:views]];
}
I got around the problem by Subclassing UICollectionView, and using the subclass instead.
On the subclass I overrode 2 methods:
- (void) setContentSize:(CGSize)contentSize
{
CGSize origSize = self.contentSize;
[super setContentSize:contentSize];
if (!CGSizeEqualToSize(contentSize, origSize))
{
[self invalidateIntrinsicContentSize];
}
}
- (CGSize) intrinsicContentSize
{
return CGSizeMake(UIViewNoIntrinsicMetric, self.contentSize.height);
}
Then, i have a method inside my view controller which contains the Collection View, which calculates the required Height needed for the collection view.
I then call setContentSize with the calculated height on my subclass of Collection View, and that makes sure that it returns an intrinsicContentSize as tall as it needs to be to show all the card records inside it.
my application needs help sceen on top of the home view controller.I have taken the tabbar controller as a root view controller and added navigation view controller .So in appearance of the first screen both tabbar and navigation bar appears along with view body.When i tried to place the help screens by pageviewcontroller examples at the time of view did load in the first screen tab view and navigation bar are coming front keeping the page view controller back .i have tried
[self addChildViewController:walkthrough];
[self.view addSubview:walkthrough.view];
[self.tabBarController.view bringSubviewToFront:walkthrough.view];
please help how to get the page view screen front.And is there any examples tutorial please help me
Note:Botn navigation bar and tabbar should not be hide
This is what I have done for walkthrough in my application. You can download this FXBlurView library from here:
https://github.com/nicklockwood/FXBlurView
In my .h file
#import "FXBlurView.h"
IBOutlet UIView *viewWalkThrough;
FXBlurView *overlayView;
In my .m file
#define SYSTEM_SCREEN_SIZE [[UIScreen mainScreen] bounds].size
#define kProfileWalkthrough #"ProfileWalkthrough"
if (![[[NSUserDefaults standardUserDefaults] valueForKey:kProfileWalkthrough] boolValue]) {
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kProfileWalkthrough];
[[NSUserDefaults standardUserDefaults] synchronize];
overlayView = [[FXBlurView alloc] initWithFrame:CGRectMake(0, 0, SYSTEM_SCREEN_SIZE.width, SYSTEM_SCREEN_SIZE.height)];
[overlayView setDynamic:YES];
[overlayView setBlurRadius:5.0f];
[overlayView setBlurEnabled:YES];
[overlayView setTintColor:[UIColor blackColor]];
[self.view.window addSubview:overlayView];
[self displayOverlay:viewWalkThrough aboveView:self.view.window];
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(closeWalkThrough:)];
[viewWalkThrough addGestureRecognizer:tapGesture];
}
- (void)closeWalkThrough:(UITapGestureRecognizer *)tapRecognizer {
[overlayView removeFromSuperview];
[self.viewWalkThrough removeFromSuperview];
}
- (void)displayOverlay:(UIView *)subView aboveView:(UIView *)superView {
subView.translatesAutoresizingMaskIntoConstraints = NO;
[superView addSubview:subView];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[subView]|" options:kNilOptions metrics:nil views:NSDictionaryOfVariableBindings(subView)]];
[superView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[subView]|" options:kNilOptions metrics:nil views:NSDictionaryOfVariableBindings(subView)]];
[superView layoutSubviews];
}
I am fairly new to iOS. I tried to look this up but couldn't find a definite answer to the following.
I have a SWRevealViewController to handle side menu bar from my FirstPage.
When the SWReveal appears after clicking btn_Menu (or by swiping left) I want the FirstPage to become grey and unusable.
I see that in FirstPage we have to do the following:
[btn_Menu addTarget:self.revealViewController action:#selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
I need to change the revealToggle method somehow, or write a new selector in FirstPage which darkens it first, and then calls revealToggle ? I am unsure what's the best and easiest way to get this done. Thanks a lot.
In your FirstPage viewDidLoad do this code.
- (void)viewDidLoad
{
SWRevealViewController * revealController=[[SWRevealViewController alloc]init];
revealController = [self revealViewController];
[self.view addGestureRecognizer:revealController.panGestureRecognizer];
revealController.delegate=self;
[revealController panGestureRecognizer];
[revealController tapGestureRecognizer];
[btnSideMenu addTarget:revealController action:#selector(revealToggle:) forControlEvents:UIControlEventTouchUpInside];
}
After that add this delegate method of SWRevealViewController in to your FirstPage.
- (void)revealController:(SWRevealViewController *)revealController didMoveToPosition:(FrontViewPosition)position
{
if (revealController.frontViewPosition == FrontViewPositionRight)
{
UIView *lockingView = [UIView new];
lockingView.translatesAutoresizingMaskIntoConstraints = NO;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:revealController action:#selector(revealToggle:)];
[lockingView addGestureRecognizer:tap];
[lockingView addGestureRecognizer:revealController.panGestureRecognizer];
[lockingView setTag:1000];
[revealController.frontViewController.view addSubview:lockingView];
lockingView.backgroundColor=[UIColor grayColor];
NSDictionary *viewsDictionary = NSDictionaryOfVariableBindings(lockingView);
[revealController.frontViewController.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"|[lockingView]|"
options:0
metrics:nil
views:viewsDictionary]];
[revealController.frontViewController.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[lockingView]|"
options:0
metrics:nil
views:viewsDictionary]];
[lockingView sizeToFit];
}
else
[[revealController.frontViewController.view viewWithTag:1000] removeFromSuperview];
}
I have a problem with a custom view and autolayout. To make things simple I will use two UILabels, the first one should change its background color when the device rotate. The problem is that it doesn't do it! Any hint?
Thanks!
Nicola
- (id)init
{
self = [super init];
if (self) {
//Add the subviews to the mainView
[self.view addSubview:self.label1];
[self.view addSubview:self.label2];
//Autolayout
//Create the views dictionary
NSDictionary *viewsDictionary = #{#"header":self.label1,
#"table": self.label2};
//Create the constraints using the visual language format
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat: #"H:|[header]|"
options:0
metrics:nil
views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat: #"H:|[table]|"
options:0
metrics:nil
views:viewsDictionary]];
[self.view addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|[header(==50)][table]|"
options:0
metrics:nil
views:viewsDictionary]];
}
return self;
}
-(UIView*) label1
{
_label1 = [UILabel alloc] init];
if (UIInterfaceOrientationIsPortrait(self.interfaceOrientation)){
_label1.backgroundColor = [UIColor redColor];
}else{
_label1.backgroundColor = [UIColor greenColor];
}
_label1.translatesAutoresizingMaskIntoConstraints=NO;
return _label1;
}
-(UIView*) label2
{
_label2 = [UILabel alloc] init];
_label2.backgroundColor = [UIColor yellowColor];
_label2.translatesAutoresizingMaskIntoConstraints=NO;
_return label2;
}
-(BOOL) shouldAutorotate
{
return YES;
}
-(NSUInteger) supportedInterfaceOrientations
{
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad){
//I am on a pad
return UIInterfaceOrientationMaskAll;
} else {
//I am on a Phone
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//I expect the label1 to change its background color
[self.view setNeedDisplay];
}
If you move the code related to [self.label1 setBackgroundColor:] to the delegate method didRotateFromInterfaceOrientation:, it should work better. Also, in your custom getters, you are allocating a new label every time you access the method. In most situations it's preferable to check if the ivar is not nil at the beginning, and returning the ivar, instead for allocating a fresh label.