WatchKit for Apple Watch 中有 ActivityIndicator 吗?

问题描述 投票:0回答:9

Apple Watch 的 WatchKit 中是否有 ActivityIndicator(或类似的东西)?你们如何向用户提供有关某些更持久的后台活动的反馈?

uiactivityindicatorview watchkit
9个回答
22
投票

为了添加选项,我在 GitHub 上创建了一个

JBWatchActivityIndicator
项目,可让您生成自己的图像序列:https://github.com/mikeswanson/JBWatchActivityIndicator

如果您不想创建自己的动画,它还包括类似 Apple 的活动指示器动画。


17
投票

编辑此答案最初是在推出具有蜂窝和 WiFi 连接功能的 Apple Watch 型号之前发布的,因此可能不再适用于较新的设备型号(考虑到显着的性能改进)。


Apple 开发者论坛上的这个帖子有一位 Apple 工程师关于为什么不应该使用 Apple Watch 执行网络操作的权威答案。

不从手表应用程序/扩展程序执行网络操作有两个重要原因:

  1. 用户与手表的交互时间很短。请参阅有关此内容的人机界面指南

    如果您在几分钟内测量与 iOS 应用程序的交互,那么您可以期望在几秒钟内测量与 WatchKit 应用程序的交互。因此交互应该简短,界面应该简单。

  2. 如果网络请求没有完成,系统可能会死锁。

    我们的建议是,一般来说,您不应在 WatchKit 扩展中执行复杂的网络操作...

    [Apple 建议开发人员] 有一个进程负责更新数据库(可能是您的 iOS 应用程序)中的信息,然后您的扩展将(本质上)对此 [缓存] 数据库具有只读访问权限。 ..


话虽这么说。如果你确实需要一个 UIActivityIndicator,rdar://19363748 (我认为这个还没有开放雷达),开发者已经提出了官方支持的请求。

您可以按照您选择的活动指示器样式创建一系列图像,然后使用

startAnimatingWithImagesInRange:duration:repeatCount:
API 将它们设置为动画。有关 动画的示例,请参阅 Apple 的 Lister 应用程序。

或者,请在此处查找 WatchKit 动画教程并包含“旋转器”图形


5
投票

我为 Apple Watch 构建了一个简单的活动指示器,可在此处获取 https://github.com/tijoinc/WatchActivityIndicator


5
投票

SwiftUI 有一个内置的解决方案:

ProgressView()

它看起来像这样:


4
投票

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.

希望这有帮助。


4
投票

我用 swiftUI 将其制作得与 watchOS 指示器类似。

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

2
投票

在我看来,尝试创建自己的 Spinner 正在使用过多的资源。如果苹果认为这是一个好主意,他们就会建议它。

我只想有一个可以调整 Alpha 的图像。使用布尔值来查看是否应该添加或减去 Alpha。

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];

}


1
投票

这是一个简单的文本指示器,它使用 @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
以停止装载机


0
投票

使用默认的ProgressView() watchos 支持https://developer.apple.com/documentation/SwiftUI/ProgressView

© www.soinside.com 2019 - 2024. All rights reserved.