How to set scrollView document view to be pinned to top left corner? If scrollView is big enough/bigger than its content, everything is drawn from bottom to up and it not looks right. I have to override isFlipped of scrollView?
I was searching internet and overriding isFlipped to return trueis not everything. I don't want to make my documentView flipped because then I have to make changes in that class to make everything looks like I want.
I created simple NSView class as an container for elements that i want to have inside my scrollView and everything looks perfect. I hope this will help someone!
#interface FlippedView : NSView
#end
and implementation:
#implementation FlippedView
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
// Drawing code here.
}
- (BOOL) isFlipped
{
return YES;
}
#end
Swift 4 Method to invert axises :
from https://stackoverflow.com/a/40381180/5464805 thank's to Ben Leggiero :
import Cocoa
class FlippedView: NSView {
override var isFlipped: Bool { return true }
}
Then in the storyboard, set this class to the NSView below the NSClipView and it do the trick.
However it won't appear in StoryBoard so you'll have to build and run
Related
I have a simple layout, which consists of NSView and its subview NSTextView. NSTextView is programmatically filled with some text that spawns multiple lines. I tie everything together using auto-layout (all done programmatically). However, when everything is displayed NSTextView is cut off, only one line is showing.
After searching the web, the best answer I could find was:
Using Autolayout with expanding NSTextViews
However, this only works if I manually change the text in NSTextView after everything is displayed (which is not really my use case). The views are readjusted and the whole NSTextView is displayed.
I am trying to figure out when NSViewController is done with laying out subviews so that I could call invalidateIntrinsicContentSize on the NSTextView. The equivalent of viewDidLayoutSubviews in UIViewController.
Nothing I tried worked so far. I attempted calling invalidateIntrinsicContentSize for NSTextView:
At the end of loadView
After I filled NSTextView with my text
Is there a better way to achieve this?
After further research, found the answer:
Create custom NSView subclass that contains NSTextView
In NSView subclass override layout method that calls invalidateIntrinsicContentSize
Also check out this link that explains subtleties of auto layout and intrinsic content size (among many other things):
http://www.objc.io/issue-3/advanced-auto-layout-toolbox.html
Sample code:
#interface MyView : NSView
#property MyTextView *textView;
#end
#implementation MyView
// init & create content & set constraints
-(void) layout {
[super layout];
[self.textView invalidateIntrinsicContentSize];
}
#end
Implementation of MyTextView:
#implementation MyTextView
- (NSSize) intrinsicContentSize {
NSTextContainer* textContainer = [self textContainer];
NSLayoutManager* layoutManager = [self layoutManager];
[layoutManager ensureLayoutForTextContainer: textContainer];
return [layoutManager usedRectForTextContainer: textContainer].size;
}
- (void) didChangeText {
[super didChangeText];
[self invalidateIntrinsicContentSize];
}
#end
as all we know Apple, we always need to change something for each update. Did somebody solve the moving problem for map legal link?
I tried many ways to control legal label but, just it can be hidden?
what else I can do?
thanks in advance
You need to change bottomLayoutGuide for your UIViewController. Create a class with following code:
MapLayoutGuide.h
#interface MapLayoutGuide : NSObject <UILayoutSupport>
-(id)initWithLength:(CGFloat)length;
#end
MapLayoutGuide.m
#import "MapLayoutGuide.h"
#implementation MapLayoutGuide
#synthesize length = _length;
- (id)initWithLength:(CGFloat)length
{
if (self = [super init])
{
_length = length;
}
return self;
}
#end
And then in your UIViewController, that is displaying map, add this:
-(id <UILayoutSupport>)bottomLayoutGuide
{
return [[MapLayoutGuide alloc] initWithLength:kMapViewBottomContentInset];
}
where kMapViewBottomContentInset - how much do you want to lift up Legal link. Typically size of UITabBar, if you have one.
This solution works even if you don't use AutoLayout on your view.
You can increase the height of the map so that the legal label is hidden by another view or something. I saw that some people placed a "locate me" button on top of it. I don't think that there is an easy (or legal) way to reposition or remove it.
override func viewWillLayoutSubviews() {
positionLegalMapLabel()
}
func positionLegalMapLabel() {
let legalMapLabel = self.mapView.subviews[1]
legalMapLabel.frame.origin = CGPointMake(self.mapView.bounds.size.width - legalMapLabel.frame.size.width - 7, legalMapLabel.frame.origin.y)
}
I'm programming a game using the new Sprite-Kit framework and want to use the mouse scroll wheel to change the player's gun. First of all i want to handle when the scroll wheel moves. I tried the following method, from the Cocoa Event Handling Guide
- (void)scrollWheel:(NSEvent *)theEvent
{
NSLog(#"SCROOOOOOOLL iN MOVeMENT");
}
Result: nothing, i didn't handle when i moved the mouse wheel.
Any idea of how can i handle this event ?
UPDATE:
I saw two answers talking about class derivative from NSResponder or NSView but my class derives from SKScene, i'm programming using the Sprite-kit framework and obj-c doesn't allow multiple inheritance.
Here the class definition:
#import <SpriteKit/SpriteKit.h>
#interface OpcionesMenu : SKScene
#end
Even though SKScene derives from NSResponder, it isn't a direct recipient of AppKit events. Rather, the SKView (derived from NSView/UIView) that houses the scene handles the events. You can observe this by setting a breakpoint on your scene's mouseDown method:
-[TWTMyScene mouseDown:]
-[SKView mouseDown:] ()
-[NSWindow sendEvent:] ()
-[NSApplication sendEvent:] ()
-[NSApplication run] ()
NSApplicationMain ()
So you can subclass SKView and forward the scrollWheel event yourself. Or, if you like living dangerously, you can just paste this category at the end of any of your code and it will take care of it for you:
#implementation SKView(ScrollTouchForwarding)
- (void)scrollWheel:(NSEvent *)event {
[self.scene scrollWheel:event];
}
#end
I think that could help:
- (void)scrollWheel:(NSEvent *)theEvent
{
[super scrollWheel:theEvent];
NSLog(#"user scrolled %f horizontally and %f vertically", [theEvent deltaX], [theEvent deltaY]);
}
I know this is an old question, but I was having this exact problem with a collection view. So I have a NSScrollView that contains a NSCollectionView and some other views such as labels and buttons.
Anyway I wanted to get the collection view to be able to scroll horizontally and parent scroll view to to scroll vertically. I achieved this by storing and comparing the deltaX and deltaY values.
I made a custom scroll view class and set it to the collection view's scroll view.
Here is the header code:
#import <Cocoa/Cocoa.h>
#interface CustomCollectionScrollView : NSScrollView {
// Current scroll position.
CGFloat positionAxisX;
CGFloat positionAxisY;
}
#end
And here is the implementation code:
#import "CustomCollectionScrollView.h"
#implementation CustomCollectionScrollView
/// DRAW RECT METHOD ///
-(void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
positionAxisX = 0.0;
positionAxisY = 0.0;
}
/// SCROLL METHODS ///
-(void)scrollWheel:(NSEvent *)theEvent {
// Move the parent scroll view scroll view if the user is
// scrolling vertically otherwise move the collection scroll view.
if ((theEvent.deltaX == positionAxisX) && (theEvent.deltaY != positionAxisY)) {
[self.nextResponder scrollWheel:theEvent];
} else if ((theEvent.deltaX != positionAxisX) && (theEvent.deltaY == positionAxisY)) {
[super scrollWheel:theEvent];
}
// Update the current position values.
positionAxisX = theEvent.deltaX;
positionAxisY = theEvent.deltaY;
}
#end
I don't know much about SpriteKit, but I see that there is an SKView class that is a subclass of NSView. I would guess that you should subclass SKView and put your scrollWheel: method there.
SKScene is part of SpriteKit which is an iOS framework, not an AppKit framework. Hence there is no scroll wheel handling at all (and no NSResponder (but UIResponder) in the inheritance chain). You can only work with touch events in the sprite kit.
I'm a newbie to iOS and i'm trying to develop an application based on news.
In my application , I have a Root View Controller which is a Table View Controller to display news' title and news' images. Well, when users click on the table cell ,there is another View Controller to be displayed which is more detailed and scrollable.
In the View Controller,users can share the news in Facebook and Twitter so that i have two buttons at least. What i want to do is displaying these two button when users scroll up. When users scroll down,i want to make them disappear. There is something like in Pulse News. I have already looked Scroll View delegate methods,but i didn't make it work. How can i accomplish what i want to do ?
Thanks in advance.
Create button at the position where you want in scroll according to scroll position.
origin x of scrollview : scroll.frame.origin.x;
origin y of scrollview : scroll.frame.origin.y;
height of scrollview : scroll.frame.size.height;
width of scrollview : scroll.frame.size.width;
Now you can put the button as you wish on scroll view:
button = [[UIButton alloc] initWithFrame:CGRectMake(x,y,x1,y1);
UPDATED WITH WORKING CODE: Outside of having the buttons scroll off the page so they are not visible
I know you said you looked at the scrollview delegates but this how you would solve this issue. In looking at Pulse the only tricky action is when you scroll down, which is when what look like UIToolbars fade away. The most important thing you need to have is anything that inherits from UIView at the very bottom and top of the visible screen of iPhone so when the user scrolls down or up the contentoffset has a value.
Every other actions cause them to appear sooo Pulse probably did something like this.
#import <UIKit/UIKit.h>
#interface C1ViewController : UIViewController
{
CGPoint _y;
}
#property (weak, nonatomic) IBOutlet UIScrollView *scroller;
#property (weak, nonatomic) IBOutlet UIToolbar *toolbar;
#end
#import "C1ViewController.h"
#interface C1ViewController ()
#end
#implementation C1ViewController
#synthesize scroller = _scroller;
#synthesize toolbar = _toolbar;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.scroller.contentSize = CGSizeMake(self.scroller.frame.size.width, self.scroller.frame.size.height + 100);
self.toolbar.hidden = TRUE;
_y = [self.scroller contentOffset];
}
// this method is getting deprecated, so don't worry about it to much
// but don't forget to dealloc...which I did not include.
- (void)viewDidUnload
{
[self setScroller:nil];
[self setToolbar:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
NSLog(#"content offset %f", self.scroller.contentOffset);
if (_y.y < [self.scroller contentOffset].y){
self.toolbar.hidden = TRUE;
}
else {
self.toolbar.hidden = FALSE;
}
}
#end
What my view hierarchy looks like in Interface Builder
I have just converted from .nib files to storyboard, but suddenly the view wont rotate topbar in landscape view. All the settings are "inferred" in my view, and i have not really made any changes since the conversion.
Is this a common problem when upgrading? I have not found any specific info.
And furthermore i do not force any view rotations in my code.
If any more info is needed i can supply anything!
Thanks in advance.
ViewController:
- (void) viewDidLoad {
[super viewDidLoad];
self.view.autoresizingMask = UIViewAutoresizingNone;
self.view.autoresizesSubviews = UIViewAutoresizingNone;
}
I've taken a look at your code and you seem to be missing a method that allows your view controller to rotate freely.
Subclass UIViewController e.g. like this:
// .h file
#interface OrientationAwareViewController : UIViewController
#end
// m.file
#implementation OrientationAwareViewController
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
{
return YES;
}
#end
Then set OrientationAwareViewController in the storyboard as your main view controller's class name. That said, I have no idea how this worked for you when using nibs :) Documentation says clearly:
By default, this method returns YES for the UIInterfaceOrientationPortrait orientation only. If your view controller supports additional orientations, override this method and return YES for all orientations it supports.