Подтвердить что ты не робот

IOS - UISlider прыгает при первом касании

Я добавил приложение UISlider в приложение iOS, которое я разрабатываю с помощью Xcode 5.1, и я не могу избавиться от следующего раздражающего поведения. Когда я впервые касаюсь большого пальца, он прыгает на небольшое количество.

Вот краткий пример, описывающий поведение.

Когда большой палец слайдера сначала расположен слева от центра (например, при минимальном значении), он переходит вправо. Если я запустил приложение в симуляторе iOS, большой палец прыгает при первом касании без перетаскивания. Большой палец всегда перескакивает к центру дорожки. Единственный раз, когда он не прыгает, это когда он находится в точном центре трека. Такое поведение появляется даже тогда, когда слайдер не подключен ни к чему.

Есть ли способ отключить его?

4b9b3361

Ответ 1

Сегодня настал этот вопрос. По какой-то причине вы должны установить пользовательский файл большого пальца, и он работает.

[self.yourSlider setThumbImage:[UIImage imageNamed:@"customThumb"] forState:UIControlStateNormal];

Ответ 2

Между тем в 2019 году и в iOS 12 появилась эта ошибка

Старый вопрос и все еще актуальный вопрос. Таким образом, хотя принятый ответ работает правильно, у него есть одна маленькая и важная проблема - зона касания большого пальца становится меньше, в то время как увеличение области касания в большинстве сценариев приводит к новым прыжкам (пробовал переопределять thumbRect (методы forBounds и beginTracking)

Давайте исправим это!

Таким образом, решение не так сложно, но немного неудобно (нужно немного ресурсов изображения), но все же проще, чем повторная реализация собственного Slider

Цель этого класса - устранить ошибку UIKit, которая прыжки большого пальца во время постукивания. Основной хак это замена оригинального большого пальца на какое-то изображение Другой код - это расширенная область постукивания, которая: 1) установить изображение с некоторым боковым альфа-смещением, то есть окружностью внутри большего прямоangularьника

setThumbImage (большой палец, для:.normal)

2) увеличенное изображение означает большой палец и, как результат, отслеживает минимальное и максимальное значение  виден под альфа-областью изображения. Таким образом, следующий шаг - установить мин и макс трек  изображение с левой и правой стороны соответственно,

setMinimumTrackImage (anImage, для:.normal)  setMaximumTrackImage (maxSliderImage, для:.normal)

но изображение также имеет некоторую альфа-зону, которая необходима, чтобы "скрыть" трек на  стороны большого пальца (с минимальными/максимальными значениями, где это чисто видно).

4) пока у нас большой палец и дорожка визуально уменьшилась (соответственно до ширины ползунка)  необходимо увеличить видимую часть дорожки путем переопределения trackRect (метод forBounds.  у нас не будет трека за пределами ползунка, так как часть мин/макс изображений прозрачна 5) поскольку одной из целей является увеличение зоны касания большого пальца, необходимо переопределить  точка (внутри точки :, с помощью метода :), чтобы сделать сенсорную зону по бокам

PS: не забудьте установить в xcassets min и max атрибуты треков слайдера:   1) Нарезка горизонтальных и левых/правых вставок   2) Техника растяжения

change slicing attributes

class Slider: UISlider {
    /// The value is distance between an image edge and thumb,
    /// Assume that an image scheme: [...o...] so 3 dots here is imageSideOffset, where 'o' is a thumb
    /// as we want to hide that zone
    private let imageSideOffset: CGFloat = 30

    override func awakeFromNib() {
        super.awakeFromNib()

        if let thumb = UIImage(named: "slider_thumb"),
            let minSliderImage = UIImage(named: "min_slider_track"),
            let maxSliderImage = UIImage(named: "max_slider_track") {
            setThumbImage(thumb, for: .normal)
            setMinimumTrackImage(minSliderImage, for: .normal)
            setMaximumTrackImage(maxSliderImage, for: .normal)
            clipsToBounds = true
        } else {
            assertionFailure("failed to load slider images")
        }
    }

    override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
        return bounds.insetBy(dx: -imageSideOffset, dy: 0).contains(point)
    }

    override func trackRect(forBounds bounds: CGRect) -> CGRect {
        let superRect = super.trackRect(forBounds: bounds)
        guard let _ = self.thumbImage(for: .normal) else {
            return superRect
        }
        return superRect.insetBy(dx: -imageSideOffset, dy: 0)
    }
}