How to Rotate Text in Nsview? (Mac Os, Cocoa, Swift)

Draw text at 90 degree on NSImage

Here is demo of approach with calculable location

demo

class DemoView: NSView {
override func draw(_ rect: NSRect) {

// .. your drawing code here

NSColor.red.set() // just for demo
rect.fill() // just for demo

if let context = NSGraphicsContext.current?.cgContext {
context.saveGState()

let text: NSString = "Hello World"
let attributes = [
NSAttributedString.Key.foregroundColor: NSColor.white,
NSAttributedString.Key.font: NSFont.systemFont(ofSize: 24)
]

let size = text.size(withAttributes: attributes)
context.translateBy(x: size.height, y: (rect.height - size.width) / 2)
context.rotate(by: CGFloat.pi / 2)

text.draw(at: .zero, withAttributes: attributes)

context.restoreGState()
}
}
}

NSButton rotate animation clockwise in cocoa mac application

Add [btnScan setWantsLayer:YES]; before you do your animation. NSView unlike UIView doesn't have a backing layer by default.

from Apple Docs:

In iOS apps, Core Animation is always enabled and every view is backed
by a layer. In OS X, apps must explicitly enable Core Animation
support by doing the following:

  • Link against the QuartzCore framework. (iOS apps must link against this framework only if they use Core Animation interfaces explicitly.)

  • Enable layer support for one or more of your NSView objects by doing one of the following:

    • In your nib files, use the View Effects inspector to enable layer support for your views. The inspector displays checkboxes for the
      selected view and its subviews. It is recommended that you enable
      layer support in the content view of your window whenever possible.

    • For views you create programmatically, call the view’s setWantsLayer: method and pass a value of YES to indicate that the
      view should use layers.

How to apply a view transformation that works for a UIView to a NSView?

There is an important difference between UIButton and NSButton. Even if NSButton is at the end a subclass of NSView, the rendering of an NSButton is done by its cell, NSButtonCell. Cells were created as a "lighter" version of NSView. As Apple's documentation states:

The NSCell class provides a mechanism for displaying text or images in
an NSView object without the overhead of a full NSView subclass. It’s
used heavily by most of the NSControl classes to implement their
internal workings.

While this was useful in the early Mac OS X days, now it is no longer the case and hopefully Apple will change this in AppKit at some stage.

What is happening to you is that the cell gets rotated, but then it is clipped by the view, in your case the button itself.

To solve the issue, make the NSButton's superview layer-backed too, and I believe that the clipping will go away:

[nsView.superview setWantsLayer:YES];

Widget flip behavior in Core Animation/Cocoa

Mike Lee has an implementation of the flip effect for which he has released some sample code. (Unfortunately, this is no longer available online, but Drew McCormack built off of that in his own implementation.) It appears that he grabs the layers for the "background" and "foreground" views to be swapped, uses a CATransform3D to rotate the two views in the animation, and then swaps the views once the animation has completed.

By using the layers from the views, you avoid needing to cache into a bitmap, since that's what the layers are doing anyways. In any case, his view controller looks to be a good drop-in solution for what you want.

Core Animation: set anchorPoint on 10.8 to rotate a layer about its center

I don't see any methods on NSView that are a direct “cover” for anchorPoint.

What I do see in the 10.8 release notes, besides what you quoted, is this:

The anchorPoint is also always set to be (0,0), …

The anchorPoint controls which point of the layer is at position in the superlayer's coordinate system. NSView sets self.layer.anchorPoint to (0,0), which means the layer's lower-left corner is at self.layer.position.

When you set anchorPoint to (0.5,0.5), that means the center of the layer should be at the layer's position. Since you didn't modify position, this has the effect of moving the layer down and to the left, as you are seeing.

You need to compute the position you want the layer to have when its anchorPoint is (0.5,0.5), like this:

CGRect frame = _refreshButton.layer.frame;
CGPoint center = CGPointMake(CGRectGetMidX(frame), CGRectGetMidY(frame));
_refreshButton.layer.position = center;
_refreshButton.layer.anchorPoint = CGPointMake(0.5, 0.5);


Related Topics



Leave a reply



Submit