UIButton is not displaying below the TableView - ios

I have a view-controller, to which I add a tableView, and a “Done” Button.
I’m able to add the tableview to my view controller successfully, but my “Done” button does not display.
The tableview is supposed to display at the top of the view, and the done button is supposed to display at the bottom, beneath the tableview.
Only the tableview displays and it takes up the whole screen.
Can you please advise what the issue is? Is there something wrong with my constraints?
Thanks!
#interface MyView : UIViewController<UITableViewDelegate, UITableViewDataSource>
#end
#interface MyView ()
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) UIButton *doneButton;
#end
#implementation MyView
- (void)viewDidLoad {
[super viewDidLoad];
_tableView = [[UITableView alloc] initWithFrame:CGRectZero];
_tableView.delegate = self;
_tableView.dataSource = self;
self.view.backgroundColor = [UIColor yellowColor];
[_tableView registerClass:UITableViewCell.class forCellReuseIdentifier:#"cell"];
[self.view addSubview:_tableView];
[_tableView setTranslatesAutoresizingMaskIntoConstraints:NO];
[NSLayoutConstraint activateConstraints:#[
[_tableView.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:10],
[_tableView.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-10],
[_tableView.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20],
[_tableView.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
]];
self.view.largeContentTitle = #"Title";
self.title = #"Title";
_doneButton = [UIButton buttonWithType:UIButtonTypeSystem];
_doneButton.backgroundColor = [UIColor blueColor];
[self.view addSubview:_doneButton];
[_doneButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[NSLayoutConstraint activateConstraints:#[
[_doneButton.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor],
[_doneButton.trailingAnchor constraintEqualToAnchor:_tableView.trailingAnchor],
[_doneButton.topAnchor constraintEqualToAnchor:_tableView.bottomAnchor],
[_doneButton.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor]
]];
//[_tableView.bottomAnchor constraintEqualToAnchor:_doneButton.topAnchor].active = YES;
// Do any additional setup after loading the view.
}
Here's a screenshot, attached. The tableview appears in white and pink, while the view (which contains that tableview) is yellow. This yellow viewcontroller is presented on top of another view controller...
Attached screenshot, tableView contained inside a Yellow View - Done button is not displaying:

Related

iOS Header StackView with correct alignment?

I am trying to implement a UIView which will be a header. Note I am only focused on implementing the header (as shown below) in this question.
Here is how it is supposed to be look like (the HEADER is in yellow)
Basically, the header UIView should have a UIBUTTON all the way to the left and a UILabel exactly in the middle, nothing on the right
The problem I am having is how I will make the UIView for this.
My idea was have a main horizontal UIStackView, but if I put a UILabel and UIButton into it, how can I (in code) align it in the way I've described? I am unable to use the UI Builder for this, but have to lay it out in Objective C code.
#interface HeaderView : UIView
#implementation HeaderView {
UIStackView mainHorizontalStackView;
UIButton leftButton;
UILabel middleLabel;
}
-(instanceType) initializer(){
mainHorizontalStackView = ... //alloc
leftButton = ...
middleLabel = ...
// how do I set up the constraints to make it fit the desired setup?
}
This is a very basic example of creating your custom view:
HeaderView.h
//
// HeaderView.h
// Created by Don Mag on 4/7/20.
//
#import <UIKit/UIKit.h>
#interface HeaderView : UIView
#end
HeadView.m
//
// HeaderView.m
// Created by Don Mag on 4/7/20.
//
#import "HeaderView.h"
#interface HeaderView ()
#property (strong, nonatomic) UIButton *leftButton;
#property (strong, nonatomic) UILabel *centeredLabel;
#end
#implementation HeaderView
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// default background color
self.backgroundColor = [UIColor colorWithRed:1.0 green:0.95 blue:0.8 alpha:1.0];
self.layer.borderColor = [UIColor brownColor].CGColor;
self.layer.borderWidth = 1.0;
self.layer.cornerRadius = 8.0;
_leftButton = [UIButton new];
[_leftButton setTitle:#"BUTTON" forState:UIControlStateNormal];
[_leftButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
_leftButton.translatesAutoresizingMaskIntoConstraints = NO;
_centeredLabel = [UILabel new];
_centeredLabel.text = #"LABEL";
_centeredLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:_leftButton];
[self addSubview:_centeredLabel];
// adjust constant values if "padding" from edges desired
[NSLayoutConstraint activateConstraints:#[
// constrain button to left, top, bottom
[_leftButton.leadingAnchor constraintEqualToAnchor:self.leadingAnchor constant:4.0],
[_leftButton.topAnchor constraintEqualToAnchor:self.topAnchor constant:8.0],
[_leftButton.bottomAnchor constraintEqualToAnchor:self.bottomAnchor constant:-8.0],
// constrain label centered horizontally in view, centered vertically to button
[_centeredLabel.centerXAnchor constraintEqualToAnchor:self.centerXAnchor],
[_centeredLabel.centerYAnchor constraintEqualToAnchor:_leftButton.centerYAnchor],
]];
}
return self;
}
#end
TestViewController.h
//
// TestViewController.h
// Created by Don Mag on 4/7/20.
//
#import <UIKit/UIKit.h>
#interface TestViewController : UIViewController
#end
TestViewController.m
//
// TestViewController.m
// Created by Don Mag on 4/7/20.
//
#import "TestViewController.h"
#import "HeaderView.h"
#interface TestViewController ()
#end
#implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
HeaderView *v = [HeaderView new];
v.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:v];
// respect safe area
UILayoutGuide *g = self.view.safeAreaLayoutGuide;
[NSLayoutConstraint activateConstraints:#[
// constrain header view top / leading / trailing to self.view (safe area)
// adjust constant values if "padding" from edges desired
[v.topAnchor constraintEqualToAnchor:g.topAnchor constant:0.0],
[v.leadingAnchor constraintEqualToAnchor:g.leadingAnchor constant:8.0],
[v.trailingAnchor constraintEqualToAnchor:g.trailingAnchor constant:-8.0],
]];
}
#end
Result:

How to calculate UIViewController height before adding view to view tree?

I need to measure the height of a simple autolayout based VC for a given width. For example a simple UIViewController with only one label which is positioned using leading, trailing, top and bottom constraints to the VCs root view. The VC should not have a fixed size but automatically adapt to the label content.
This is only an example, of course the VC could have other content which is influences the size.
How can I calculate the VCs size for a given width and label content without adding it to the view hierarchy?
Background:
I am using a third party FormSheet control which allows to easily show any ViewController as form sheet with different styles, transitions, etc. The only downside is, that one has to specify a fixed sheet size before the VC is presented.
While this works great for VCs with "static" content / fixed sizes even a label with different texts for different languages might break the design.
Thus I am look for something like this:
ContentViewController *contentVC = [ContentViewController new];
CGRect contentBounds = [SomeClass calculateAutoLayoutHeightForView:contentVC.view withFixedWidth:500];
[ThirPartyFormSheetController presentController:contentVC withSize:contentBounds];
How can this be done?
Given a width, you can use systemLayoutSizeFittingSize:UILayoutFittingCompressedSize to determine what the height will be after auto-layout does its work.
Assuming constraints in the view-to-show are set up correctly:
CGFloat w = 500.0;
[loadedView.widthAnchor constraintEqualToConstant:w].active = YES;
// caluclate the size using FittingCompressedSize
CGSize contentBounds = [loadedView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
Here is a simple example (only need to assign the ViewController class to a view controller in Storyboard... no IBOutlets needed). Lots of comments in the code should make everything clear:
//
// ViewController.h
// Created by Don Mag on 4/8/19.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
//
// ViewController.m
// Created by Don Mag on 4/8/19.
//
#import "ViewController.h"
#import "FormViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// add a button we'll use to show the form VC
UIButton *b = [UIButton new];
b.translatesAutoresizingMaskIntoConstraints = NO;
[b setTitle:#"Show Form" forState:UIControlStateNormal];
[b setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[b setBackgroundColor:[UIColor redColor]];
[self.view addSubview:b];
[NSLayoutConstraint activateConstraints:
#[
[b.topAnchor constraintEqualToAnchor:self.view.safeAreaLayoutGuide.topAnchor constant:20.0],
[b.widthAnchor constraintEqualToAnchor:self.view.widthAnchor multiplier:0.75],
[b.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor]
]
];
[b addTarget:self action:#selector(loadAndShowForm:) forControlEvents:UIControlEventTouchUpInside];
}
- (void) loadAndShowForm:(id)sender {
// instantiate the form view controller
FormViewController *vc = [FormViewController new];
// get a reference to its view
UIView *v = vc.view;
// use auto-layout
v.translatesAutoresizingMaskIntoConstraints = NO;
// set the label text in the form view
vc.topLabel.text = #"This is a bunch of text for the TOP label in the Form VC";
vc.bottomLabel.text = #"This is a bunch of text for the BOTTOM label in the Form VC. It's enough text to cause a few lines of word-wrap, assuming we're running on an iPhone.";
// specify a width for the form view
// we'll use width of current view minus 60 (30-pts on each side)
CGFloat w = self.view.frame.size.width - 60.0;
[v.widthAnchor constraintEqualToConstant:w].active = YES;
// caluclate the size using FittingCompressedSize
CGSize contentBounds = [v systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
// because we set the width constraint, we now have the "compressed" height
//[ThirdPartyFormSheetController presentController:contentVC withSize:contentBounds];
// debugging from here down
NSLog(#"Auto-layout resulting size: %#", [NSValue valueWithCGSize:contentBounds]);
// set the height for the form view
[v.heightAnchor constraintEqualToConstant:contentBounds.height].active = YES;
// add it to the view, so we can confirm the height calculation
[self.view addSubview:v];
// center it on the view
[NSLayoutConstraint activateConstraints:
#[
[v.centerXAnchor constraintEqualToAnchor:self.view.centerXAnchor],
[v.centerYAnchor constraintEqualToAnchor:self.view.centerYAnchor]
]
];
}
#end
//
// FormViewController.h
// Created by Don Mag on 4/8/19.
//
#import <UIKit/UIKit.h>
#interface FormViewController : UIViewController
#property (strong, nonatomic) UILabel *topLabel;
#property (strong, nonatomic) UITextField *theTextField;
#property (strong, nonatomic) UILabel *bottomLabel;
#end
//
// FormViewController.m
// Created by Don Mag on 4/8/19.
//
#import "FormViewController.h"
#interface FormViewController ()
#end
#implementation FormViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor redColor];
// create a multi-line "top label"
_topLabel = [UILabel new];
_topLabel.backgroundColor = [UIColor cyanColor];
_topLabel.text = #"Hello Top Label";
_topLabel.numberOfLines = 0;
// create a text field
_theTextField = [UITextField new];
_theTextField.backgroundColor = [UIColor greenColor]; // just to make it easy to see
_theTextField.borderStyle = UITextBorderStyleRoundedRect;
_theTextField.text = #"The Text Field";
// create a multi-line "bottom label"
_bottomLabel = [UILabel new];
_bottomLabel.backgroundColor = [UIColor cyanColor];
_bottomLabel.text = #"Hello Bottom Label";
_bottomLabel.numberOfLines = 0;
// we're using auto-layout and constraints
_topLabel.translatesAutoresizingMaskIntoConstraints = NO;
_theTextField.translatesAutoresizingMaskIntoConstraints = NO;
_bottomLabel.translatesAutoresizingMaskIntoConstraints = NO;
// add to view
[self.view addSubview:_topLabel];
[self.view addSubview:_theTextField];
[self.view addSubview:_bottomLabel];
// these elements and constraints will define the height of the content
[NSLayoutConstraint activateConstraints:
#[
// constrain top label leading, trailing and top to top of view, all at 20-pts
[_topLabel.topAnchor constraintEqualToAnchor:self.view.topAnchor constant:20.0],
[_topLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0],
[_topLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0],
// constrain text field leading and trailing, and top to bottom of top label, all at 20-pts
[_theTextField.topAnchor constraintEqualToAnchor:_topLabel.bottomAnchor constant:20.0],
[_theTextField.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0],
[_theTextField.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0],
// constrain bottom label leading, trailing and top to bottom of text field, all at 20-pts
[_bottomLabel.topAnchor constraintEqualToAnchor:_theTextField.bottomAnchor constant:20.0],
[_bottomLabel.bottomAnchor constraintEqualToAnchor:self.view.bottomAnchor constant:-20.0],
[_bottomLabel.leadingAnchor constraintEqualToAnchor:self.view.leadingAnchor constant:20.0],
// AND constrain bottom label to bottom of view at 20-pts
[_bottomLabel.trailingAnchor constraintEqualToAnchor:self.view.trailingAnchor constant:-20.0]
]
];
}
#end
The result (adding the loaded VC's view as a subview - see the comments in the code):
and with more text to show the automatic height calculation:
If you change the amount of text for the labels (set in ViewController.m), you will see that the height is calculated correctly.
Swift:
If all you need is to calculate height on the basis of label's text, you can use this solution
https://stackoverflow.com/a/25187891/7848711

UIScrollView is not scrolling in UiView

when I scroll on UIScrollView that not scrolling . Also I am setting scrollview's contentSize.
When I show one other subView and after when I show my view , it's scrolling.
You can see what is problem on this video . How can I solve this problem?
myViewController.h file
#import <UIKit/UIKit.h>
#interface myViewController : UIViewController
#property(nonatomic,retain)UIView * rightTabView;
#property(nonatomic,retain)UIView * leftTabView;
#property(nonatomic,retain)UIView * middleTabView;
#property(nonatomic,retain)UIScrollView *myscrollview;
#end
myViewController.m file
- (void)viewDidLoad
{
// Do any additional setup after loading the view from its nib.
[super viewDidLoad];
//create Tab views and addSubview
CGFloat barHeight=58;
self.rightTabView=[[UIView alloc] initWithFrame:CGRectMake(0, barHeight+55,self.view.bounds.size.width,self.view.bounds.size.height-barHeight-55)];
[self.view addSubview:self.rightTabView];
self.leftTabView=[[UIView alloc] initWithFrame:CGRectMake(0, barHeight+5,self.view.bounds.size.width,self.view.bounds.size.height-barHeight-55)];
self.leftTabView.backgroundColor=[UIColor redColor];
[self.view addSubview:self.leftTabView];
self.middleTabView=[[UIView alloc] initWithFrame:CGRectMake(0, barHeight+55,self.view.bounds.size.width,self.view.bounds.size.height-barHeight-55)];
[self.view addSubview:self.middleTabView];
//add Subview to leftTabView
myscrollview=[[UIScrollView alloc]initWithFrame:CGRectMake(10, 10,300, 340)];
myscrollview.userInteractionEnabled=YES;
myscrollview.backgroundColor = [UIColor greenColor];
myscrollview.delegate = self;
[self.leftTabView addSubview:myscrollview];
myscrollview.contentSize = CGSizeMake(2000, 2000);
}
It looks like your middleTabView is obscuring your leftTabView (which is the superview of your scrollview). Either bring the leftTabView to the top of the view hierarchy:
[self.leftTabView.superview bringSubViewToFront:self.leftTabView];
or disable user interactions or visibility of your middleTabView (or add the leftTabView last).

Two UISearchBars showing up in a view controller when only one is instantiated

I have two search bars shhowing up in a view controller. It's strange because I have the same exact code in another vc and it works fine. (the search bar in the background shouldn't be there)
here's a screenshot:
I added the delegates: <UISearchBarDelegate, UISearchDisplayDelegate>
then in the .h:
#property (nonatomic,retain) IBOutlet UISearchBar *searchBar;
in the .m:
#synthesize searchBar;
in the viewDidLoad:
self.searchBar.frame = CGRectMake(204, 11, 107,44);
self.searchBar.delegate = self;
//customize the searchbar
UITextField *searchField = [self.searchBar valueForKey:#"_searchField"];
[searchField setBackground:[UIImage imageNamed:#"search_panel.png"]];
[self.searchBar setTintColor:[UIColor redColor]];
UIImage *searchimg = [UIImage imageNamed:#"searchfield_bg.png"];
for (UIView *subview in self.searchBar.subviews) {
if ([subview isKindOfClass:NSClassFromString(#"UISearchBarBackground")]) {
UIView *bg = [[UIView alloc] initWithFrame:subview.frame];
bg.backgroundColor = [UIColor colorWithPatternImage:searchimg];
[self.searchBar insertSubview:bg aboveSubview:subview];
[subview removeFromSuperview];
break;
}
}
[self.view addSubview:self.searchBar];
and that's it. I have nothing to do with the searchBar in the Storyboard view controller xib it's added programmatically in the viewDidLoad method
thanks for any help
If you're using an outlet, your UISearchBar very likely also exists in the storyboard or the xib. Since you're also creating it in the viewDidLoad, you're making a second copy of it. Take another look at your storyboard.

How to add multiple UIViews in a UIScrollView

I have a UIView that draws a pie chart and I would like to put 3 or maybe 4 charts in a UIScrollView programatically. How can I do that?
my h file is like this
#class PieChart;
#interface ViewController : UIViewController {
}
#property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
and m file
- (void)viewDidLoad
{
[super viewDidLoad];
[scrollView setBackgroundColor:[UIColor blackColor]];
[scrollView setCanCancelContentTouches:NO];
scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite;
scrollView.clipsToBounds = YES;
scrollView.scrollEnabled = YES;
scrollView.pagingEnabled = YES;
PieChart *chart = [[PieChart alloc]initWithFrame:CGRectZero];
[chart setFrame:CGRectMake(100, 100, 200, 200)];
[scrollView addSubview:chart];
}
If you need to add subview to the view you need to use [view addSubview:subview]. This is common practice.
Read about frames and bounds (coordinate systems for view and sub views):
https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaViewsGuide/Coordinates/Coordinates.html
As I understand you have a problem due to content size of scroll view. Read more here:
http://developer.apple.com/library/ios/#DOCUMENTATION/WindowsViews/Conceptual/UIScrollView_pg/Introduction/Introduction.html
Hope it helps.
You can just add it with:
[scrollView addSubview:singleView];
You add multiple subviews to a UIScrollView just like you add a single subview; with addSubview:. What problems are you running into?

Resources