I have IBOutlet 2 property, scrollview and contentview, i create my view via xib, I Set all consraint inside contentview, now I need to put contentview inside scrollview, I try to do something like this:
[_scrollView addSubview:_scrollViewContent];
[_scrollView setContentSize:_scrollViewContent.frame.size];
_scrollView.translatesAutoresizingMaskIntoConstraints = NO;
_scrollViewContent.translatesAutoresizingMaskIntoConstraints = NO;
NSDictionary *views = NSDictionaryOfVariableBindings(_scrollView, _scrollViewContent);
NSArray *scrollViewLabelConstraints = [NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_scrollViewContent(_scrollView)]" options:0 metrics:nil views:views];
[_scrollView addConstraints:scrollViewLabelConstraints];
initially not work, contentview is a bit larger then scrollview, when I scroll horizontally I see the view in the correct way.
Where is the error?
Related
So I've been burned by this a few times. I'm trying to create an NSTextView that can be scrolled.
The only way I've gotten it to work is by having a Xib—but right now that stopped working after I added a Stack View in an adjacent Split View for God-knows-what-reason.
So what have I done?
I have code for code copied down the Apple Docs like for Text in Scroll View like so:
// https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/TextUILayer/Tasks/TextInScrollView.html
BOOL deviateFromAppleScrollDoc = NO;
_scrollView = [[NSScrollView alloc]
initWithFrame:[[self view] frame]];
// Apple Has
// [[theWindow contentView] frame]];
// but we are in a sub-View-Controller
NSSize contentSize = [_scrollView contentSize];
[_scrollView setBorderType:NSNoBorder];
[_scrollView setHasVerticalScroller:YES];
[_scrollView setHasHorizontalScroller:NO];
[_scrollView setAutoresizingMask:NSViewWidthSizable |
NSViewHeightSizable];
_editorView = [[EditorView alloc]
initWithFrame:NSMakeRect(
0, 0,
contentSize.width, contentSize.height)];
[_editorView setMinSize:NSMakeSize(0.0, contentSize.height)];
[_editorView setMaxSize:NSMakeSize(FLT_MAX, FLT_MAX)];
[_editorView setVerticallyResizable:YES];
[_editorView setHorizontallyResizable:NO];
if (deviateFromAppleScrollDoc)
{
[_editorView setAutoresizesSubviews:YES];
[_editorView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
}
else
{
[_editorView setAutoresizingMask:NSViewWidthSizable];
}
[[_editorView textContainer]
setContainerSize:NSMakeSize(contentSize.width, FLT_MAX)];
[[_editorView textContainer] setWidthTracksTextView:YES];
if (deviateFromAppleScrollDoc)
{
[[_editorView textContainer] setHeightTracksTextView:YES];
}
if (deviateFromAppleScrollDoc)
{
NSClipView *clipView = [[NSClipView alloc] init];
[clipView setDocumentView:_editorView];
[_scrollView setContentView:clipView];
}
else
{
[_scrollView setDocumentView:_editorView];
}
[[self view] addSubview:_scrollView];
What does that get me?
As you can tell, there is an NSTextView. It does not fill the Container as I would like it to.
There is also a Scroll View and I can tell it is active. You can pull down and get a rebound effect—but it does not scroll the document as I would like. This text is cut off mid-sentence and when I add to it, the View does not scroll with my typing—and even if I scroll I can't get to it.
The Scroll View is "stuck".
I can make it fill the entire window if I change the Autoresizing mask to inlcude NSViewHeightSizable like so:
[_editorView setAutoresizingMask:NSViewWidthSizable|NSViewHeightSizable];
See here:
Unfortunatley, it still does not scroll and the "Scroll View" is still "Stuck".
I don't know what to change.
I have tried to add a "NSClipView" and set the Content View instead like so:
NSClipView *clipView = [[NSClipView alloc] init];
[clipView setDocumentView:_editorView];
[_scrollView setContentView:clipView];
This does not work either.
Moreover it does something funky to the width and some of the letters get cut off. Not acceptable. No solution yet.
What am I missing?
What do I need to try / set / do?
Thank you!
UPDATE:
The Scroll View does scroll the document when I activate the find menu in the NSTextView.
Still mystified.
See here:
My application contains a main container view in which three different views(subviewA, subviewB and subviewC) are swapped in and out. Both subviewA and subviewB are to resize with the window and I do this as follows
NSView *myCurrentView = [_myCurrentViewController view];
if ([[_myCurrentViewController title] isEqualToString:subviewA] ||
[[_myCurrentViewController title] isEqualToString:subViewB]) {
[_myScrollView setHidden:YES];
[myCurrentView setTranslatesAutoresizingMaskIntoConstraints:NO];
[_mainWindowView addSubview: [_myCurrentViewController view]];
[_mainWindowView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|[myCurrentView]|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(myCurrentView)]];
[_mainWindowView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|[myCurrentView]|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(myCurrentView)]];
}
This works fine, however for subviewC i would like to have the horizontal size of the subview, resize with the window, but use scrolling for the vertical. So, in IB I added a NSScrollView as a subview of my mainWindowView. I hide the scroll view if subViewA or subviewB are selected, but I don't know how to properly configure the constraints for subviewC. I figured I could add horizontal constraints simliar to subviewA or subviewB, since I woulk like the view to resize with the window, however I don't know what to add for constraints in the vertical to allow scrolling, so far I have this
[[_myCurrentViewController view] setTranslatesAutoresizingMaskIntoConstraints:YES];
[_myScrollView setHidden:NO];
[_myScrollView setDocumentView:[_myCurrentViewController view]];
[_myScrollView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|[myCurrentView]|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(myCurrentView)]];
Thanks
I am trying to build an NSTableView similar to how Things does it's layout.
I assume what they are doing is using an NSTableView with a custom-drawn NSTableCell -- or perhaps it's an NSSegmentedControl. I am attempting to go down the NSTableCell route. I attempted to subclass an NSTableCellView and draw a custom cell (this is all in the init method for testing);
- (id)init {
self = [super init];
if (self) {
_checkbox = [[NSButton alloc] init];
[_checkbox setButtonType:NSSwitchButton];
_textview = [[NSTextView alloc] init];
[self addSubview:_checkbox];
[self addSubview:_textview];
[self setTranslatesAutoresizingMaskIntoConstraints:NO];
NSDictionary *views = NSDictionaryOfVariableBindings(_checkbox, _textview);
[self addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[_checkbox]-[_textview]|"
options:0
metrics:nil
views:views]];
}
return self;
}
#end
Seems pretty self-explanatory, but it doesn't actually work. I am getting errors on constraints not being able to be satisfied. Is it not possible to use autolayout inside a subclassed NSTableCellView?
It is possible although you have to introduce some additional code to the table view controller:
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
NSTableCellView *rowView = [self.tableView makeViewWithIdentifier: RVIssueSelectionTableRowViewContentKey owner: self];
[rowView setObjectValue: yourDataObject]; // or update your cell with the according data the way you prefer
[rowView setNeedsLayout: YES];
[rowView layoutSubtreeIfNeeded];
return [rowView fittingSize].height;
}
This will cause the cell to update it's layout and you can return it's desired height. Because this call can be kind of expensive you should cache the calculated cell height.
This answer has been taken from another SO answer which I could not find right now (will update the solution when I've found it).
Your error messages for the constraints are generated because you force the cell to have a height of x (through the table view datasource methods). But your constraints want to set the height of the cell so they are satisfied. Both at the same time can not work.
I'm wondering how to crop image inside UIscrollView with autolayout
I'm trying to make UIscrollView scroll only horizontally. if image is higher than view height it should be cropped. I've tried a lot properties but can't make all images inside uiscrollview same height as view to avoid scrolling vertically.
Do i miss something?
#import "WelcomeController.h"
#interface WelcomeController ()
#property (strong, nonatomic) UIScrollView *scrollView;
#property (nonatomic,strong) NSArray *contentList;
#end
#implementation WelcomeController
#synthesize contentList =_contentList;
- (void)updateUI
{
UIScrollView* sv = self.scrollView;
id previousLab = nil;
for (UIView *lab in _contentList) {
lab.translatesAutoresizingMaskIntoConstraints = NO;
lab.backgroundColor = [UIColor blackColor];
lab.contentMode = UIViewContentModeScaleAspectFit;
[sv addSubview:lab];
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[lab]|"
options:0 metrics:nil
views:#{#"lab":lab}]];
if (!previousLab) { // first one, pin to top
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[lab]"
options:0 metrics:nil
views:#{#"lab":lab}]];
} else { // all others, pin to previous
[sv addConstraints:
[NSLayoutConstraint
constraintsWithVisualFormat:#"H:[prev][lab]"
options:0 metrics:nil
views:#{#"lab":lab, #"prev":previousLab}]];
}
previousLab = lab;
}
// last one, pin to bottom and right, this dictates content size height
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[lab]|"
options:0 metrics:nil
views:#{#"lab":previousLab}]];
[sv addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:[lab]|"
options:0 metrics:nil
views:#{#"lab":previousLab}]];
}
-(void)setContentList:(NSArray *)contentList
{
_contentList = contentList;
[self updateUI];
}
- (void)setupScrollView
{
UIScrollView* sv = [UIScrollView new];
sv.backgroundColor = [UIColor redColor];
sv.translatesAutoresizingMaskIntoConstraints = NO;
sv.pagingEnabled = YES;
sv.showsHorizontalScrollIndicator =NO;
sv.showsVerticalScrollIndicator = NO;
sv.bounces =NO;
[self.view addSubview:sv];
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[sv]|"
options:0 metrics:nil
views:#{#"sv":sv}]];
[self.view addConstraints:
[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[sv]|"
options:0 metrics:nil
views:#{#"sv":sv}]];
self.scrollView = sv;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self setupScrollView];
//for testing
UIImageView *image1=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"welcome1.jpg"]];
UIImageView *image2=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"welcome2.jpg"]];
UIImageView *image3=[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"welcome3.jpg"]];
self.contentList = [NSArray arrayWithObjects:image1,image2,image3,nil];
}
#end
Have you tried setting the height of the scroll view explicitly?
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[_sv(123)]" options:0 metrics:nil views:views]];
You would need to replace the height above (123) with the height you need, obviously, as well as views.
Autolayout automatically manages the UIScrollView's contentSize (the scrollable area). So if you stick a subview in there with an intrinsic size that is larger than the height, it will increase the contentSize. I can think of two things:
Stick images in a plain UIView with the same height as the scrollview.
Subclass the UIImageView and override the intrinsicContentSize method to return a fixed height for all images. This seems like a poor solution, though.
I think you should be able to set the image view's frames to a fixed height (via constraints). Then add constraints to have the image views top and bottom fixed with x constant from the scrollview.
This will let the scrollview know its exact content size to use. As long as its frame, then, (determined by whatever constraints you give it in relation to its superview) is >= the image view's fixed heights, it won't scroll vertically.
Considering the following structure:
| UIScrollView | UITextField | (UIScrollView on the left and a UITextField the right)
I am trying to add a UILabel into the UIScrollView and make the UIScrollView grow according to the UILabel size. The UITextFiled would then get smaller according to the grow of the UIScrollView.
- (IBAction)makeScrollViewGrow:(id)sender
self.myScrollView.translatesAutoresizingMaskIntoConstraints = NO;
self.myTextField.translatesAutoresizingMaskIntoConstraints = NO;
UILabel *myLabel = [[UILabel alloc] init];
myLabel.text = #"THIS IS A LONG MESSAGE";
myLabel.translatesAutoresizingMaskIntoConstraints = NO;
[self.myScrollView addSubview:myLabel];
UITextField *theTextField = self.myTextField;
[self.myTextField removeConstraint:self.titleTextFieldWidthConstraint];
[self.myScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|[myLabel]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(myLabel)]];
[self.myScrollView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[myLabel]|" options:0 metrics:0 views:NSDictionaryOfVariableBindings(myLabel)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-20-[theSCrollView]-8-[theTextField]-20-|" options:0 metrics: 0 views:NSDictionaryOfVariableBindings(theSCrollView, theTextField)]];
[self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|[theSCrollView]|" options:0 metrics: 0 views:NSDictionaryOfVariableBindings(theSCrollView)]];
}
The issue here is that the UIScrollView is not being resized because the UITextField has a fixed width. If I remove programatically the width UITextField constraint the UIScrollView takes over the all width without considering the text Label (intrinsicContentSize).
Will I need to set the Scrollview contentsize manually or can I do this automatically using autolayout?
Thanks