Подтвердить что ты не робот

Как правильно определить левый край верхнего уровня Today в iOS 8?

Я пытаюсь выяснить, как вычислить левое поле в главном окне расширения Today, чтобы выровнять содержимое с остальными метками представления Today.

Вот пример с чистым проектом Xcode с использованием расширений Today (я добавил цвет к фону представления и нарисовал пунктирную красную линию, чтобы проиллюстрировать, где я хотел бы выровнять Hello World UILabel).

Результат в симуляторе iPhone 6 Plus (левый альбом, правый портрет) можно найти на изображении ниже:

enter image description here

На изображении обратите внимание, что левая граница зеленого главного изображения по-разному связана с именем приложения UILabel "testi2". Также кажется, что красная линия - основные виды слева выравнивания границы различны в каждом устройстве: iPhone 5x, iPhone 6 и iPads.

Поведение может быть воспроизведено с использованием чистого проекта Xcode (я использую Xcode 6.1.1, iOS 8.1 и Swift):

  • Создать пустой проект Xcode (одноразовое приложение)
  • Добавить новую цель: Расширения > Расширение Today
  • В расширенной группе "Сегодня" найдите MainInterface.storyboard и сделайте основной фон для фона зеленым и Hello world UILabel background red: enter image description here

Как выровнять строку Hello World UILabel (красный фон) пунктирной линией? Или как выровнять основной вид (зеленый фон) с пунктирной линией?

4b9b3361

Ответ 1

Вы попробовали этот?

Objective-C

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

Swift:

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

В противном случае вам будет необходимо установить их вручную в соответствии с этим So-Thread:

EDIT:

Похоже, этот метод устарел и не вызывается для устройств с запуском >= iOS10. Однако я не мог найти никакой документации по альтернативе. Если у вас есть какая-либо информация по этому вопросу, пожалуйста, добавьте к этому сообщению, чтобы каждый мог получить прибыль. Просто убедитесь, что при использовании этой функции она не будет вызываться нa >= iOS10.

Источник: Документация Apple

Ответ 2

Я попытался использовать значение left defaultMarginInset of -widgetMarginInsetsForProposedMarginInsets со смешанными результатами: на габаритах экрана iPhone 5S его можно использовать для получения той же вставки, что и виджет календаря по умолчанию для iOS (обратите внимание, что правый край метки времени совпадает с синей линией):

5S Portrait

5S Landscape

На iPhone 6 вы получаете похожие результаты, то есть также выравнивает. Однако на iPhone 6 Plus календарный виджет как-то масштабирует вставку:

6P Portrait

6P Landscape

Обратите внимание, что в альбомной версии ни время, ни строки не выравниваются ни с чем.

В заключение я бы сказал, что вы можете безопасно использовать defaultMarginInset.left для получения достойных результатов.


Быстрый код:

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

Ответ 3

Мое временное решение выглядит следующим образом. Я использую постоянные значения для установки левого и верхнего полей. Таким образом, я могу выровнять содержимое точно так же, как это, например, в виджетах Tomorrow Summary.

Сначала некоторые вспомогательные методы для определения типа устройства (адаптированы из этого ответа):

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
}

Однако это не то решение, которое я ищу - я бы хотел избавиться от жесткого кодирования для пиксельных значений на устройство для ориентации.