Estado de resaltado de UISlider con un ancho de pulgar diferente al normal

Estoy tratando de implementar un UISlider personalizado (subclase de UISlider), que se comporta de manera similar al control deslizante nativo que tiene un brillo alrededor del pulgar cuando está resaltado. Sin embargo, estoy teniendo problemas con esto.

El ancho (efectivo) del pulgar resaltado es obviamente mayor que el pulgar normal (debido al brillo). Si agrego un relleno de píxeles transparente a la imagen de estado normal, de modo que ambas imágenes tengan el mismo ancho, el problema es que el pulgar de estado normal nunca parece llegar al final de la pista (sí llega al final, pero el relleno hace parece lo contrario).

Si uso thumbRectForBounds: para desplazar el pulgar para que se alinee correctamente con el comienzo de la pista, solo empeora el problema en el otro extremo.

Si mantengo ambas imágenes con el ancho necesario (es decir, sin relleno en el estado normal y las dos no tienen el mismo ancho), me he acercado. Puedo configurar el desplazamiento de forma independiente en thumbRectForBounds: basado en UIControl.state, pero parece que hay algo de magia matemática detrás de escena. El único lugar donde UISlider cree que las imágenes de ambos estados se alinean perfectamente es el centro exacto.

Parece que es posible que deba implementar algunas matemáticas que determinen el desplazamiento del estado de resaltado en función de su posición relativa a lo largo de la pista. Necesitaría un desplazamiento y de cero en el centro (el UISlider centraría ambas imágenes, lo que significa que se alinearían). En los extremos, necesitaría un desplazamiento en y que compense por completo el brillo. Y en el medio necesitaría interpolar el desplazamiento y.

Sin embargo, esto parece mucho trabajo para recrear algo que hace el control deslizante nativo, así que tal vez me esté perdiendo algo obvio.

Noticias Solución actual:

No es completamente portátil, ya que hace algunas suposiciones sobre el tamaño del brillo que se agrega. Estoy agregando el brillo con una imagen en lugar de dibujarlo directamente en CALayer. Todavía no he probado el rendimiento de esto.

Esencialmente, creo una capa que es un cuadrado cuyas dimensiones son la altura de la imagen del pulgar de estado predeterminada, la centro sobre el pulgar y luego dibujo el resplandor (solo el resplandor, no una imagen separada de un pulgar con un resplandor, como sería hecho con una imagen de estado resaltado) en la capa.

- (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;
}

preguntado el 03 de mayo de 12 a las 17:05

La pregunta es principalmente con respecto a la imagen de la pista, no a la imagen del pulgar. Escribir mi propio control deslizante aún puede ser la única respuesta aquí, pero dado que estoy tratando de recrear el comportamiento nativo, todavía me pregunto si hay una manera de evitar tener que hacerlo. -

3 Respuestas

en lugar de agregar un efecto de brillo en la imagen, puede ser mejor agregarlo dinámicamente. puede usar CALayer para agregar un efecto de brillo.

Capa CAL

contestado el 09 de mayo de 12 a las 08:05

Eso será bastante difícil, ya que UISlider no parece tener subvistas o subcapas a las que pueda agregar una sombra. - Andreas Ley

Como dice Andreas, esto no es completamente sencillo ya que no hay acceso directo a la vista de la imagen en miniatura, pero se me ocurrió una solución que parece estar funcionando. Gracias por la idea, Tejesh. - Farski

@farski Gracias. Sería bueno si pudiera compartir la solución de trabajo. - Tejesh Alimilli

Lo agregué a mi publicación original la semana pasada. - Farski

Puede hacer rodar su propio control deslizante, que no es tan complicado como puede parecer, pero aún requeriría algunas horas de codificación.

Sin embargo, la solución más simple sería configurar también imágenes de seguimiento personalizadas:

  1. Cree imágenes de pista "mínimas"/"máximas" personalizadas con relleno (píxeles transparentes) en el lado izquierdo/derecho. El relleno debe ser tan grande como el radio de tu brillo menos el radio del pulgar (11 puntos).
  2. Aplique imágenes a su UISlider con setMinimumTrackImage:forState: y setMaximumTrackImage:forState:
  3. Aumente el ancho de su control deslizante por el tamaño del relleno agregado

contestado el 10 de mayo de 12 a las 13:05

Encontré un problema similar con un control deslizante personalizado para una de mis aplicaciones. A diferencia del control deslizante normal, la pista es una recta numérica estática, por lo que no necesito imágenes de pista mínimas y máximas separadas. Sin embargo, necesitaba un punto caliente extra grande para el pulgar. Así que hice la imagen de mi pulgar con relleno adicional de píxeles transparentes y asigné imágenes transparentes a la pista. La pista visible es solo un UIImageView detrás del control deslizante (en realidad, un UIImageView detrás de un grupo de controles deslizantes). Los bordes del control deslizante se extienden mucho más allá de los bordes de la imagen de la pista.

Mi sugerencia es hacer la construcción visual de su control deslizante deseado combinando múltiples vistas en lugar de chocar con las limitaciones de personalizar un control deslizante UIS. Si puede prescindir de una pista cambiante, podría duplicar mi técnica. O puede manipular el marco de una o dos UIView para hacer que las pistas personalizadas se ajusten cada vez que el control deslizante cambia de valor. Si necesita usar este mismo control deslizante más de una vez en su aplicación, puede empaquetar el grupo de vistas en una subclase UIView. Dependiendo de cuán compleja sea la acción de su control deslizante, puede llegar un punto en el que hacer un control personalizado sea la opción más prudente.

contestado el 10 de mayo de 12 a las 15:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.