Slider(YouTubeの下部にあるように、ビデオのコントロールとして動作)を作成し、最大値(持続時間)と最小値を設定しました。次に、SeekToTime
を使用してcurrentTimeを変更しました。これで、ユーザーはスライダーのつまみをスライドして値を変更できます
私が達成したいのは、ユーザーがスライダーのどこかをタップして、ビデオの現在の時間を設定できるようにすることです。
この答え からアプローチを得て、それを私のケースに適用しようとしましたが、機能させることができませんでした
_class ViewController: UIViewController, PlayerDelegate {
var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Setup the slider
}
func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")
let pointTapped: CGPoint = gestureRecognizer.locationInView(self.view)
let positionOfSlider: CGPoint = slider.frame.Origin
let widthOfSlider: CGFloat = slider.frame.size.width
let newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)
slider.setValue(Float(newValue), animated: true)
}
}
_
これはうまくいくと思いましたが、うまくいきませんでした。次に、「A」をログに出力してデバッグを試みましたが、明らかにsliderTapped()
関数には入りません。
何が悪いのですか?または、私が達成しようとしていることを達成するためのより良い方法はありますか?
上記のコード例に従って、viewDidLoad()でタップジェスチャレコグナイザを実際に初期化する必要があるようです。そこにはコメントがありますが、認識機能がどこにも作成されていないようです。
Swift 2:
class ViewController: UIViewController {
var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Setup the slider
// Add a gesture recognizer to the slider
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "sliderTapped:")
self.slider.addGestureRecognizer(tapGestureRecognizer)
}
func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")
let pointTapped: CGPoint = gestureRecognizer.locationInView(self.view)
let positionOfSlider: CGPoint = slider.frame.Origin
let widthOfSlider: CGFloat = slider.frame.size.width
let newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)
slider.setValue(Float(newValue), animated: true)
}
}
Swift 3:
class ViewController: UIViewController {
var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Setup the slider
// Add a gesture recognizer to the slider
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(sliderTapped(gestureRecognizer:)))
self.slider.addGestureRecognizer(tapGestureRecognizer)
}
func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")
let pointTapped: CGPoint = gestureRecognizer.location(in: self.view)
let positionOfSlider: CGPoint = slider.frame.Origin
let widthOfSlider: CGFloat = slider.frame.size.width
let newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)
slider.setValue(Float(newValue), animated: true)
}
}
UISliderをサブクラス化し、常にtrueをbeginTrackingに返すだけで、望ましい効果が得られるようです。
iOS 10およびSwift
class CustomSlider: UISlider {
override func beginTracking(_ touch: UITouch, with event: UIEvent?) -> Bool {
return true
}
}
その後、コードでUISliderの代わりにCustomSliderを使用します。
これは「myuiviews」の回答に基づいた私のコードです。
元のコードの2つの小さな「バグ」を修正しました。
1-0をタップするのが難しかったので、簡単にした
2-スライダーの親指を少しだけスライドすると、「tapGestureRecognizer」が起動され、初期位置に戻るため、最小距離フィルターを追加してそれを回避しました。
Swift 4
class ViewController: UIViewController {
var slider: UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Setup the slider
// Add a gesture recognizer to the slider
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(sliderTapped(gestureRecognizer:)))
self.slider.addGestureRecognizer(tapGestureRecognizer)
}
@objc func sliderTapped(gestureRecognizer: UIGestureRecognizer) {
// print("A")
var pointTapped: CGPoint = gestureRecognizer.location(in: self.view)
pointTapped.x -= 30 //Subtract left constraint (distance of the slider's Origin from "self.view"
let positionOfSlider: CGPoint = slider.frame.Origin
let widthOfSlider: CGFloat = slider.frame.size.width
//If tap is too near from the slider thumb, cancel
let thumbPosition = CGFloat((slider.value / slider.maximumValue)) * widthOfSlider
let dif = abs(pointTapped.x - thumbPosition)
let minDistance: CGFloat = 51.0 //You can calibrate this value, but I think this is the maximum distance that tap is recognized
if dif < minDistance {
print("tap too near")
return
}
var newValue: CGFloat
if pointTapped.x < 10 {
newValue = 0 //Easier to set slider to 0
} else {
newValue = ((pointTapped.x - positionOfSlider.x) * CGFloat(slider.maximumValue) / widthOfSlider)
}
slider.setValue(Float(newValue), animated: true)
}
}
私はこのアプローチが好きです
extension UISlider {
public func addTapGesture() {
let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
addGestureRecognizer(tap)
}
@objc private func handleTap(_ sender: UITapGestureRecognizer) {
let location = sender.location(in: self)
let percent = minimumValue + Float(location.x / bounds.width) * maximumValue
setValue(percent, animated: true)
sendActions(for: .valueChanged)
}
}
後で電話するだけ
let slider = UISlider()
slider.addTapGesture()
おそらく最も簡単な解決策は、「内部の修正」アクションを使用して、インターフェイスビルダーを介して接続することです。
@IBAction func finishedTouch(_ sender: UISlider) {
finishedMovingSlider(sender)
}
これは、指が電話画面から離れるとすぐに呼び出されます。
プテオフィルの答えはここで受け入れられる答えでなければなりません。
以下は、すべての人が興味を持つXamarinのソリューションです。
public override bool BeginTracking(UITouch uitouch, UIEvent uievent)
{
return true;
}
Pteofilが言及したように、これを機能させるにはUISliderをサブクラス化する必要があります。