Есть ли в WatchKit ActivityIndicator для Apple Watch?
Есть ли ActivityIndicator (или что-то подобное) в WatchKit для Apple Watch? Как вы все даете пользователю обратную связь о более длительной фоновой активности?
9 ответов
Изменить:Этот ответ был первоначально опубликован до появления моделей Apple Watch с сотовой связью и Wi-Fi, и, следовательно, может больше не применяться на более новых моделях устройства (учитывая значительные улучшения производительности).
Эта ветка на форумах Apple Developer содержит авторитетный ответ инженера Apple о том, почему вы не должны выполнять сетевые операции с Apple Watch.
Есть две веские причины не выполнять сетевые операции из вашего приложения / расширения для часов:
Пользователи взаимодействуют со своими часами только в течение короткого периода времени. Смотрите руководство по интерфейсу для человека на этом.
Если вы измеряете взаимодействия с вашим iOS-приложением за считанные минуты, вы можете ожидать, что взаимодействия с вашим приложением WatchKit будут измеряться за считанные секунды. Поэтому взаимодействия должны быть краткими, а интерфейсы - простыми.
Система может заблокироваться, если сетевой запрос не выполнен.
Мы рекомендуем не выполнять сложные сетевые операции внутри расширения WatchKit...
[Apple рекомендует разработчикам] иметь единый процесс, который отвечает за обновление информации в вашей базе данных (вероятно, в вашем приложении iOS), и тогда ваши расширения будут иметь (по существу) доступ только для чтения к этой [кэшированной] базе данных...,
Что, как говорится. Если вам действительно нужен UIActivityIndicator, rdar://19363748 (я не думаю, что этот еще был открытым радаром), разработчики уже подали запросы на официальную поддержку.
Вы можете создать серию изображений в выбранном вами стиле индикатора активности, а затем анимировать их, используя startAnimatingWithImagesInRange:duration:repeatCount:
API. См. Приложение Apple Lister для примера анимации /questions/tagged/wkinterfaceimage.
В качестве альтернативы, посмотрите здесь учебник WatchKit Animation и включенную графику "spinner".
Просто чтобы добавить к опциям, я создал JBWatchActivityIndicator
проект на GitHub, который позволяет создавать собственные последовательности изображений: https://github.com/mikeswanson/JBWatchActivityIndicator
Он также включает в себя Apple-анимацию индикатора активности, если вы не хотите создавать свою собственную.
Я построил простой индикатор активности для Apple Watch, доступный здесь https://github.com/tijoinc/WatchActivityIndicator
На всякий случай, если кто-то еще его ищет, у SwiftUI есть встроенное решение:
ProgressView()
Я сделал его похожим на индикатор watchOS с помощью swiftUI.
import SwiftUI
struct ActivityIndicatorView: View {
// MARK: - Value
// MARK: Public
@Binding var isAnimating: Bool
// MARK: Private
private let radius: CGFloat = 24.0
private let count = 18
private let interval: TimeInterval = 0.1
private let point = { (index: Int, count: Int, radius: CGFloat, frame: CGRect) -> CGPoint in
let angle = 2.0 * .pi / Double(count) * Double(index)
let circleX = radius * cos(CGFloat(angle))
let circleY = radius * sin(CGFloat(angle))
return CGPoint(x: circleX + frame.midX, y: circleY + frame.midY)
}
private let timer = Timer.publish(every: 1.8, on: .main, in: .common).autoconnect() // every(1.8) = count(18) / interval(0.1)
@State private var scale: CGFloat = 0
@State private var opacity: Double = 0
// MARK: - View
var body: some View {
GeometryReader { geometry in
ForEach(0..<self.count) { index in
Circle()
.fill(Color.white)
.frame(width: 3.0, height: 3.0)
.animation(nil)
.opacity(self.opacity)
.scaleEffect(self.scale)
.position(self.point(index, self.count, self.radius, geometry.frame(in: .local)))
.animation(
Animation.easeOut(duration: 1.0)
.repeatCount(1, autoreverses: true)
.delay(TimeInterval(index) * self.interval)
)
}
.onReceive(self.timer) { output in
self.update()
}
}
.rotationEffect(.degrees(10.0))
.opacity(isAnimating == false ? 0 : 1.0)
.onAppear {
self.update()
}
}
// MARK: - Function
// MARK: Private
private func update() {
scale = 0 < scale ? 0 : 1.0
opacity = 0 < opacity ? 0 : 1.0
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.scale = 0
self.opacity = 0
}
}
}
#if DEBUG
struct ActivityIndicatorView_Previews: PreviewProvider {
static var previews: some View {
let view = ActivityIndicatorView(isAnimating: .constant(true))
return Group {
view
.previewDevice("Apple Watch Series 5 - 44mm")
view
.previewDevice("Apple Watch Series 4 - 40mm")
view
.previewDevice("Apple Watch Series 3 - 42mm")
view
.previewDevice("Apple Watch Series 3 - 38mm")
}
}
}
#endif
Нет метода для отображения ActivityIndicator в WatchKit Framework. Однако вы можете подготовить несколько круговых изображений и легко создать бесконечную анимацию самостоятельно. Подготовьте изображения и назовите их такframe-0, frame-1, frame-2...frame-n
а затем в вашем коде:
[self.yourInterfaceImage setImageNamed:@"firstFrame-"]; //setting first frame
[self.yourInterfaceImage startAnimatingWithImagesInRange:[self.model imageRange]
duration:0.4
repeatCount:0];
// [self.model imageRange] will return NSRange from 0 to n
// repeatCount == 0 means infinity. Of course you can set some limit, like 100.
Надеюсь это поможет.
На мой взгляд, попытка создать свой собственный Spinner требует чрезмерных ресурсов. Если бы Apple думала, что это хорошая идея, они бы предложили это.
Я бы вместо этого просто имел изображение, которое вы настраиваете альфа. Используйте логическое значение, чтобы увидеть, должны ли вы добавлять или вычитать альфу.
if (add)
{
count=count+5;
if (count==100)
{
add=false;
}
}
else
{
count=count-5;
if (count==0)
{
add=true;
}
}
float thealpha=((float)count/100);
[self.scanb setAlpha:thealpha];
}
Вот простой текстовый индикатор, использующий атрибут @State:
struct MyView: View {
private let loaderSpeed = 0.1 // seconds per state
private let loaderStates = [
"• ",
" • ",
" • ",
" • ",
" • ",
" • ",
" • ",
" •",
" • ",
" • ",
" • ",
" • ",
" • ",
" • ",
]
@State private var loaderMessage = ""
@State private var loaderState = 0 {
didSet {
if self.loaderState > 0 {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + self.loaderSpeed) {
if self.loaderState > 0 {
self.loaderMessage = self.loaderStates[self.loaderState-1]
if self.loaderState >= self.loaderStates.count {
self.loaderState = 1
} else {
self.loaderState += 1
}
}
}
}
}
}
var body: some View {
HStack() {
Spacer()
Text("Loading:")
Text(loaderMessage).onAppear { self.loaderState = 1 }
Spacer()
}
}
}
задавать loaderState = 1
запустить загрузчик
задавать loaderState = 0
остановить погрузчик
Watch Kit не имеют объекта индикатора. поэтому используйте изображение, чтобы показать индикатор. Добавьте свое изображение в активы
И используйте этот код, чтобы запустить анимацию изображения
image.setImageNamed("Small_Indicator")
image.startAnimatingWithImages(in: NSMakeRange(0, 39), duration: 1.0, repeatCount: 0)
И используйте этот код, чтобы остановить
image.stopAnimating()
image.setHidden(true)
Перейдите по ссылке и используйте этот образец проекта, чтобы отобразить индикатор https://github.com/Abishekt97/AppleWatchIndicator