UISlider выделяет состояние с большой шириной большого пальца, чем обычно - программирование
Подтвердить что ты не робот

UISlider выделяет состояние с большой шириной большого пальца, чем обычно

Я пытаюсь реализовать пользовательский UISlider (подкласс UISlider), который ведет себя аналогично встроенному слайдеру, у которого есть свечение вокруг большого пальца, когда оно выделено. У меня проблемы с этим, однако.

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

Если я использую thumbRectForBounds: для смещения большого пальца, чтобы правильно выравниваться с началом дорожки, это только делает проблему хуже на другом конце.

Если я сохраняю оба изображения только так широко, как они должны быть (т.е. никаких отступов в нормальном состоянии, а два не одинаковой ширины), я стал ближе. Я могу установить смещение независимо в thumbRectForBounds: на основе UIControl.state, но кажется, что там какая-то математическая магия происходит за кулисами. Единственное место, где UISlider считает, что изображения для обоих состояний идеально подходят, - это точный центр.

Кажется, мне может понадобиться реализовать некоторую математику, которая определяет смещение состояния подсветки на основе его относительного положения вдоль дорожки. Это потребует у-смещения нуля в центре (UISlider будет центрировать оба изображения, что означает, что они выравниваются). В крайних случаях для этого потребуется у-смещение, которое полностью компенсирует свечение. И между ними потребуется интерполировать смещение y.

Кажется, что много работы, чтобы воссоздать что-то, что делает собственный слайдер, поэтому, возможно, мне не хватает чего-то очевидного.

Обновление Текущее решение:

Он не полностью переносимый, поскольку он делает некоторые предположения о размере добавляемого свечения. Я добавляю свечение с изображением, а не рисую его непосредственно на CALayer. Я еще не тестировал, насколько это возможно.

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

- (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value {
  CGRect r = [super thumbRectForBounds:bounds trackRect:rect value:value];

  [thumbHighlightOverlayLayer removeFromSuperlayer];
  thumbHighlightOverlayLayer = [CALayer layer]; 

  int x = r.origin.x + (r.size.width / 2) - (r.size.height / 2);
  thumbHighlightOverlayLayer.frame = CGRectMake(x, r.origin.y, r.size.height, r.size.height);

  UIImage* thumbHighlightOverlayImage = [UIImage imageNamed:@"thumb-highlight"];
  thumbHighlightOverlayLayer.contents = (id)thumbHighlightOverlayImage.CGImage;

  switch (self.state) {
    case UIControlStateHighlighted:
      [[self layer] addSublayer:thumbHighlightOverlayLayer];
      break;
    default:
      break;
  }

  return r;
}
4b9b3361

Ответ 1

вместо добавления эффекта свечения на изображении, возможно, лучше добавить его динамически. вы можете использовать CALayer, чтобы добавить эффект свечения.

CALayer

Ответ 2

Вы можете прокручивать свой собственный слайдер, который не так сложный, как может показаться, но все равно потребуется несколько часов кодирования.

Однако самым простым решением было бы просто установить пользовательские изображения дорожек:

  • Создание пользовательских "минимальных" / "максимальных" образов дорожек с заполнением (прозрачные пиксели) на левой/правой стороне. Прокладка должна быть такой же большой, как ваш радиус свечения минус радиус большого пальца (11pt).
  • Применить изображения к вашему UISlider с помощью setMinimumTrackImage:forState: и setMaximumTrackImage:forState:
  • Увеличьте ширину слайдера на размер добавленного дополнения.

Ответ 3

Я столкнулся с аналогичной проблемой с пользовательским слайдером для одного из моих приложений. В отличие от обычного слайдера, дорожка представляет собой статическую цифровую строку, поэтому мне не нужны отдельные минимальные и максимальные изображения треков. Тем не менее, мне понадобилось дополнительное большое горячее пятно для большого пальца. Поэтому я сделал изображение большого пальца с дополнительным дополнением прозрачных пикселей, и я назначил прозрачные изображения на дорожку. Видимая дорожка - это всего лишь UIImageView за слайдером (фактически один UIImageView за группой слайдеров). Края ползунка выходят далеко за края изображения дорожки.

Мое предложение состоит в том, чтобы сделать визуальную конструкцию вашего намеченного слайдера, объединив несколько представлений вместо того, чтобы стучать против ограничений настройки UISlider. Если вы можете обойтись без изменения дорожки, вы можете дублировать мою технику. Или вы можете манипулировать рамкой UIView или двумя, чтобы настраивать настраиваемые дорожки, когда ползунок меняет значение. Если вам нужно использовать один и тот же слайдер более одного раза в своем приложении, вы можете упаковать группу представлений в подкласс UIView. В зависимости от того, насколько сложным будет ваше действие слайдера, может возникнуть точка, в которой создание настраиваемого элемента управления будет более разумным выбором.