Есть ли индикатор активности (или что-то подобное) в WatchKit для Apple Watch? Как вы все даете отзывы пользователей о какой-то более продолжительной фоновой активности?
Есть ли индикатор активности в WatchKit для Apple Watch?
Ответы (8)
Изменить: Этот ответ изначально был опубликован до появления моделей Apple Watch с возможностью подключения к сотовой сети и Wi-Fi, поэтому он больше не может применяться к более новым моделям устройства. (учитывая значительное повышение производительности).
В этой ветке на форумах разработчиков Apple есть авторитетный ответ от инженера Apple о почему вам не следует выполнять сетевые операции с Apple Watch.
Есть две серьезные причины не выполнять сетевые операции из вашего приложения/расширения для часов:
- #P4# <блочная цитата> #P5# блочная цитата>
- #P6# <блочная цитата> #P7# #P8# блочная цитата>
Что, как говорится. Если вам действительно нужен UIActivityIndicator, rdar://19363748 (я не думаю, что этот индикатор еще не был открыт), разработчики уже подали запросы на официальную поддержку.
Вы можете создать серию изображений в выбранном вами стиле индикатора активности, а затем анимировать их с помощью startAnimatingWithImagesInRange:duration:repeatCount:
API. См. приложение Apple Lister для примера анимации wkinterfaceimage.
Кроме того, здесь можно найти Учебник WatchKit Animation и включают графику "spinner".
Просто чтобы добавить к опциям, я создал проект JBWatchActivityIndicator
на GitHub, который позволяет вам создавать свои собственные последовательности изображений: https://github.com/mikeswanson/JBWatchActivityIndicator
Он также включает в себя анимацию индикатора активности в стиле Apple, если вы не хотите создавать свои собственные.
Я создал простой индикатор активности для Apple Watch, доступный здесь https://github.com/tijoinc/WatchActivityIndicator
В WatchKit Framework нет метода отображения ActivityIndicator. Однако вы можете подготовить некоторое круглое изображение и легко создать бесконечную анимацию самостоятельно. Подготовьте изображения и назовите их так 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.
Надеюсь это поможет.
Я сделал его похожим на индикатор 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
На мой взгляд, попытка создать свой собственный 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];
}
На случай, если кто-то еще его ищет, у SwiftUI есть встроенное решение: ProgressView()
Вот простой текстовый индикатор, в котором используется атрибут @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
, чтобы остановить загрузчик