Last active
April 25, 2020 13:05
-
-
Save macneko-ayu/c4ba1df605cc7da1e9cdafeaca86c48f to your computer and use it in GitHub Desktop.
WKInterfaceLabel to automatically scroll horizontally
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import WatchKit | |
import Foundation | |
class InterfaceController: WKInterfaceController { | |
@IBOutlet var notEndlessLabel: WKInterfaceLabel! | |
@IBOutlet var endlessLabel: WKInterfaceLabel! | |
override func awake(withContext context: Any?) { | |
super.awake(withContext: context) | |
notEndlessLabel.setAutoHorizontalScrollText("レノくんかわいい。ごんたかわいい。あゆさんかわいい") | |
endlessLabel.setAutoHorizontalScrollText("レノくんかわいい。ごんたかわいい。あゆさんかわいい", isEndless: true) | |
} | |
override func willActivate() { | |
// This method is called when watch view controller is about to be visible to user | |
super.willActivate() | |
} | |
override func didAppear() { | |
super.didAppear() | |
notEndlessLabel.startTimer() | |
endlessLabel.startTimer() | |
} | |
override func didDeactivate() { | |
// This method is called when watch view controller is no longer visible | |
super.didDeactivate() | |
notEndlessLabel.stopTimer() | |
endlessLabel.stopTimer() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import WatchKit | |
private var ScrolledTextKey: UInt8 = 0 | |
private var OriginTextKey: UInt8 = 0 | |
private var TimerKey: UInt8 = 0 | |
private var EndlessKey: UInt8 = 0 | |
private var TimerStartedKey: UInt8 = 0 | |
extension WKInterfaceLabel { | |
// MARK: - Public method | |
/// テキストを横方向に自動でスクロールする | |
/// | |
/// - Parameter text: text | |
func setAutoHorizontalScrollText(_ text: String?, isEndless endless: Bool = false) { | |
guard let text = text else { | |
return | |
} | |
setEndless(endless) | |
setOriginText(NSAttributedString(string: text + " ")) | |
initializeText() | |
self.startTimer() | |
} | |
/// 自動スクロール開始 | |
@objc func startTimer() { | |
// タイマーの多重起動を防ぐため、スクロール開始済の場合はreturn | |
if getTimerStarted() { | |
return | |
} | |
setTimerStarted(true) | |
DispatchQueue.main.async { | |
let timer = Timer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(self.timerUpdate), userInfo: nil, repeats: true) | |
self.setTimer(timer) | |
} | |
} | |
/// 自動スクロール停止 | |
func stopTimer() { | |
getTimer().invalidate() | |
setTimerStarted(false) | |
// テキストを初期化 | |
initializeText() | |
} | |
// MARK: - Private method | |
/// ラベルのテキストを更新 | |
@objc private func timerUpdate() { | |
if getScrolledText().length > 1 { | |
let scrolledText = NSMutableAttributedString(attributedString: getScrolledText()) | |
guard let firstCharacter = scrolledText.string.first else { | |
return | |
} | |
// テキストの先頭の文字を削除 | |
scrolledText.deleteCharacters(in: NSRange(location: 0, length: 1)) | |
// エンドレスの場合はテキストの末尾に削除した文字を追加する | |
if getEndless() { | |
scrolledText.append(addAttribute(String(firstCharacter))) | |
} | |
setScrolledText(scrolledText) | |
setAttributedText(getScrolledText()) | |
} else { | |
// タイマーを停止 | |
stopTimer() | |
if !getEndless() { | |
// 少し間をおき、スクロール開始 | |
let timer = Timer(timeInterval: 2, target: self, selector: #selector(startTimer), userInfo: nil, repeats: false) | |
RunLoop.main.add(timer, forMode: .commonModes) | |
} | |
} | |
} | |
/// ラベルのテキストを初期化 | |
private func initializeText() { | |
let attributeText = addAttribute(getOriginText().string) | |
setOriginText(attributeText) | |
setScrolledText(getOriginText()) | |
setAttributedText(getScrolledText()) | |
} | |
private func addAttribute(_ text: String) -> NSAttributedString { | |
// ラベルにLineBreakModeのプロパティが存在しないので、NSAttributedStringで設定する | |
let paragraphStyle = NSMutableParagraphStyle() | |
paragraphStyle.lineBreakMode = .byClipping | |
let attributes: [NSAttributedStringKey: Any] = [.paragraphStyle: paragraphStyle] | |
return NSAttributedString(string: text, attributes: attributes) | |
} | |
// MARK: - getter/setter | |
private func setScrolledText(_ text: NSAttributedString) { | |
objc_setAssociatedObject(self, &ScrolledTextKey, text, .OBJC_ASSOCIATION_RETAIN) | |
} | |
private func getScrolledText() -> NSAttributedString { | |
guard let object = objc_getAssociatedObject(self, &ScrolledTextKey) as? NSAttributedString else { | |
return NSAttributedString(string: "") | |
} | |
return object | |
} | |
private func setOriginText(_ text: NSAttributedString) { | |
objc_setAssociatedObject(self, &OriginTextKey, text, .OBJC_ASSOCIATION_RETAIN) | |
} | |
private func getOriginText() -> NSAttributedString { | |
guard let object = objc_getAssociatedObject(self, &OriginTextKey) as? NSAttributedString else { | |
return NSAttributedString(string: "") | |
} | |
return object | |
} | |
private func setTimer(_ timer: Timer) { | |
objc_setAssociatedObject(self, &TimerKey, timer, .OBJC_ASSOCIATION_RETAIN) | |
} | |
private func getTimer() -> Timer { | |
guard let object = objc_getAssociatedObject(self, &TimerKey) as? Timer else { | |
return Timer() | |
} | |
return object | |
} | |
private func setEndless(_ endless: Bool) { | |
objc_setAssociatedObject(self, &EndlessKey, endless, .OBJC_ASSOCIATION_RETAIN) | |
} | |
private func getEndless() -> Bool { | |
guard let object = objc_getAssociatedObject(self, &EndlessKey) as? Bool else { | |
return false | |
} | |
return object | |
} | |
private func setTimerStarted(_ timerStarted: Bool) { | |
objc_setAssociatedObject(self, &TimerStartedKey, timerStarted, .OBJC_ASSOCIATION_RETAIN) | |
} | |
private func getTimerStarted() -> Bool { | |
guard let object = objc_getAssociatedObject(self, &TimerStartedKey) as? Bool else { | |
return false | |
} | |
return object | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Line 70 now needs to be:
RunLoop.main.add(timer, forMode: .common)
.Thank you!