【问题标题】:How to determine the Today extension left margin properly in iOS 8?如何在 iOS 8 中正确确定 Today 扩展左边距?
【发布时间】:2015-02-25 01:29:57
【问题描述】:

我正在尝试找出如何计算今日扩展主视图中的左边距,以将内容与今日视图标签的其余部分对齐。

这是一个使用 Today 扩展的干净 Xcode 项目的示例(我为视图背景添加了颜色并绘制了一条红色虚线来说明我希望将 Hello World UILabel 对齐的位置)。

iPhone 6 Plus 模拟器中的结果(左侧横向,右侧纵向)如下图所示:

在图片中,请注意绿色主视图左边界与应用名称UILabel“testi2”相关的位置不同。似乎红线 - 每个设备的主视图左边框对齐方式都不同:iPhone 5x、iPhone 6 和 iPad。

可以使用干净的 Xcode 项目重现该行为(我使用的是 Xcode 6.1.1、iOS 8.1 和 Swift):

  1. 创建一个空的 Xcode 项目(单视图应用程序)
  2. 添加新目标:扩展程序 > 今天扩展程序
  3. 在 Today 扩展组中,找到 MainInterface.storyboard 并将主视图背景设为绿色,Hello world UILabel 背景设为红色:

如何将 Hello World UILabel(红色背景)与虚线对齐?或者如何将主视图(绿色背景)与虚线对齐?

【问题讨论】:

  • 图像坏了,至少在这里。 “您在 CloudFlare 网络上的网站 (i.stack.imgur.com) 上请求了一个页面。CloudFlare 当前无法解析您请求的域 (i.stack.imgur.com)。”
  • 其实这似乎是 StackOverflow 的问题。刚刚注意到另一个损坏的图像,它是与站点相关的图像。忽略。
  • 好的,这里有另一个图片链接:ibin.co/w800/1mDY3ckx95h7
  • 如果您没有设置任何边距,我会认为“今天”视图会正确对齐这些,尽管我没有对此进行测试。在屏幕截图中产生结果的代码是什么?
  • 查看已编辑的问题:只需向默认的 Today 扩展界面生成器模板添加颜色,就会在纵向和横向模式下产生奇怪的对齐方式。

标签: ios iphone ipad ios8 today-extension


【解决方案1】:

你试过这个吗?

Objective-C

- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
    return UIEdgeInsetsZero;
}

斯威夫特:

func widgetMarginInsetsForProposedMarginInsets(defaultMarginInsets: UIEdgeInsets) -> UIEdgeInsets {
        return UIEdgeInsetsZero
}

否则看起来你将不得不根据这个So-Thread手动设置它们:

编辑:

看起来此方法已被弃用,并且不会为运行 >= iOS10 的设备调用。但是我找不到任何关于替代方案的文档。如果您对此有任何信息,请添加到此帖子中,以便每个人都可以获利。 请确保在使用此函数时不会在 >= iOS10 上调用它。

来源:Apple Documentation

【讨论】:

  • 谢谢,让我试试。我正在寻找一种解决方案,该解决方案不需要需要为每个设备和方向输入魔术像素值。
  • 您提供的示例(我正在使用 Swift,如问题中所述,顺便说一句)确实取出了 所有边距。但是,它没有回答如何计算小部件名称UILabel 的位置(我的屏幕截图中的红色条纹线)。
【解决方案2】:

我尝试使用defaultMarginInsetdefaultMarginInsetleft 值,结果好坏参半:在iPhone 5S 屏幕尺寸上,它可用于获取与iOS 的默认日历小部件相同的插图(注意时间标签的右边距与蓝线对齐):

在 iPhone 6 上,您会得到类似的结果,即它也对齐。但是,在 iPhone 6 Plus 上,日历小部件会以某种方式缩放插图:

请注意,在横向版本中,时间和线条都不对齐。

最后,我想说您可以放心地使用defaultMarginInset.left 来获得不错的结果。


Swift 代码:

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)
    }
}

【讨论】:

  • 不错,但不准确。苹果正在以某种方式进行对齐,我想知道如何。我敢打赌,他们没有针对每个设备和方向的一组固定像素值。
  • 对此我不太确定。此外,正如您在 6 Plus 上看到的那样,它并没有真正与任何东西对齐。此外,如果您将提醒小部件的插图与日历小部件进行比较,您会注意到它根本没有对齐任何东西。在我看来,他们对此并不那么严格,不幸的是......
  • 在 iPhone 6 Plus 横屏中,文本“你明天没有安排活动”。与“Tomorrow”小部件标题(Apple 的“Tomorrow Summary”Today 小部件)完美对齐。
  • 啊,我没注意到。尽管如此,Apple 也可能已经硬编码了一些他们没有公开公开的值:比如键盘的高度。
【解决方案3】:

我的临时解决方案如下。我使用常量值来设置左边距和上边距。通过这种方式,我可以将内容完全对齐,例如,在 Tomorrow Summary 小部件中。

首先是一些确定设备类型的辅助方法(改编自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
}

然后按照建议使用widgetMarginInsetsForProposedMarginInsets:,如下所示覆盖左侧和顶部插图:

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
}

但是,这不是我正在寻找的解决方案 - 我想摆脱对每个设备每个方向的像素值进行硬编码。

【讨论】:

  • 对于 iPad Portait 你应该使用 54 而不是 58,否则它对我有用
猜你喜欢
  • 2020-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多