I'm trying to find out how to calculate the left margin in the Today extension main view to align the contents to the rest of the Today view labels.
Here's an example with a clean Xcode project using a Today extensions (I've added color to the view backgrounds and drawn a dashed red line to illustrate where I'd like to align the Hello World UILabel
).
The result in iPhone 6 Plus simulator (left side landscape, right side portrait) can be found from the image below:
In the image, notice that the green main view left boundary is placed differently related to the app name UILabel
"testi2". It also seems that the red line - main views left border alignment is different in each device: iPhone 5x, iPhone 6 and iPads.
The behavior can be reproduced using a clean Xcode project (I'm using Xcode 6.1.1, iOS 8.1 and Swift):
UILabel
background red:
How do I align the the Hello World UILabel
(red background) to the dashed line? Or how do I align the main view (green background) to the dashed line?
Did you try this one ?
Objective-C:
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
return UIEdgeInsetsZero;
}
Swift:
func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
return UIEdgeInsetsZero
}
Otherwise it looks like you will have to set them manually according to this So-Thread:
EDIT:
Looks like this method is deprecated and is not called for devices running >= iOS10. However I could not find any documentation on an alternative. If you have any information on this please add to this post so everyone can profit. Just make sure when using this function that it will not be called on >= iOS10.
Source: Apple Documentation
I tried using the left
value of the defaultMarginInset
of -widgetMarginInsetsForProposedMarginInsets
with mixed results: On the iPhone 5S screen dimensions, it can be used to get the same inset as the default calendar widget of iOS (note that the right margin of the time label aligns with the blue line):
On the iPhone 6, you get similar results, i.e. it also aligns. However, on iPhone 6 Plus, the calendar widget somehow scales the inset:
Note that in the landscape version, neither the time nor the lines align to anything.
In conclusion, I would say that you can safely use defaultMarginInset.left
to get decent results.
Swift code:
class TodayViewController: UIViewController, NCWidgetProviding {
var defaultLeftInset: CGFloat = 0
var marginIndicator = UIView()
override func viewDidLoad() {
super.viewDidLoad()
marginIndicator.backgroundColor = UIColor.whiteColor()
view.addSubview(marginIndicator)
}
func widgetMarginInsetsForProposedMarginInsets(var defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
defaultLeftInset = defaultMarginInsets.left
defaultMarginInsets.left = 0
return defaultMarginInsets
}
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)!) {
marginIndicator.frame = CGRectMake(defaultLeftInset, 0, 10, view.frame.size.height)
completionHandler(NCUpdateResult.NewData)
}
}
My temporary solution goes as follows. I'm using constant values for setting the left and top margins. This way I can align the content exactly like it's, for example, in Tomorrow Summary widget.
First some helper methods for determining the device type (adapted from this answer):
struct ScreenSize {
static let SCREEN_WIDTH = UIScreen.mainScreen().bounds.size.width
static let SCREEN_HEIGHT = UIScreen.mainScreen().bounds.size.height
static let SCREEN_MAX_LENGTH = max(ScreenSize.SCREEN_WIDTH,
ScreenSize.SCREEN_HEIGHT)
static let SCREEN_MIN_LENGTH = min(ScreenSize.SCREEN_WIDTH,
ScreenSize.SCREEN_HEIGHT)
}
struct DeviceType {
static let iPhone4 = UIDevice.currentDevice().userInterfaceIdiom == .Phone
&& ScreenSize.SCREEN_MAX_LENGTH < 568.0
static let iPhone5 = UIDevice.currentDevice().userInterfaceIdiom == .Phone
&& ScreenSize.SCREEN_MAX_LENGTH == 568.0
static let iPhone6 = UIDevice.currentDevice().userInterfaceIdiom == .Phone
&& ScreenSize.SCREEN_MAX_LENGTH == 667.0
static let iPhone6Plus = UIDevice.currentDevice().userInterfaceIdiom == .Phone
&& ScreenSize.SCREEN_MAX_LENGTH == 736.0
static let iPad = UIDevice.currentDevice().userInterfaceIdiom == .Pad
}
Then using widgetMarginInsetsForProposedMarginInsets:
as suggested I overwrite the left and top insets as follows:
func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets)
-> UIEdgeInsets {
var insets = defaultMarginInsets
let isPortrait = UIScreen.mainScreen().bounds.size.width
< UIScreen.mainScreen().bounds.size.height
insets.top = 10.0
if DeviceType.iPhone6Plus {
insets.left = isPortrait ? 53.0 : 82.0
} else if DeviceType.iPhone6 {
insets.left = 49.0
} else if DeviceType.iPhone5 {
insets.left = 49.0
} else if DeviceType.iPhone4 {
insets.left = 49.0
} else if DeviceType.iPad {
insets.left = isPortrait ? 58.0 : 58.0
}
return insets
}
However, this is not the solution I'm looking for - I'd like to get rid of hardcoding per-device-per-orientation pixel values.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With