switch stepper activity iphone cocoa-touch user-interface uislider

iphone - stepper - Cómo obtener el centro de la imagen del pulgar de UISlider



switch ios (11)

Estoy creando un UISlider personalizado para probar algunas ideas de interfaz. Se basa principalmente en agrandar la imagen del pulgar.

Descubrí cómo hacer eso, así:

UIImage *thumb = [UIImage imageNamed:@"newThumbImage_64px.png"]; [self.slider setThumbImage:thumb forState:UIControlStateNormal]; [self.slider setThumbImage:thumb forState:UIControlStateHighlighted]; [thumb release];

Para calcular un valor relacionado, necesito saber dónde cae el punto central de la imagen del pulgar cuando se está manipulando. Y el punto debería estar en las coordenadas de su supervista.

Al mirar los documentos de UISlider , no vi ninguna propiedad que rastreara esto.

¿Hay alguna manera fácil de calcular esto o se puede derivar de algún valor existente?


Aquí hay una solución Swift 2.2, creé una extensión para ella. Solo he intentado esto con la imagen predeterminada.

import UIKit extension UISlider { var thumbImageCenterX: CGFloat { let trackRect = trackRectForBounds(bounds) let thumbRect = thumbRectForBounds(bounds, trackRect: trackRect, value: value) return thumbRect.origin.x + thumbRect.width / 2 - frame.size.width / 2 } }


Después de jugar un poco con IB y una imagen de pulgar ancha de 1px, la posición del pulgar está exactamente donde lo esperarías:

UIImage *thumb = [UIImage imageNamed:@"newThumbImage_64px.png"]; CGRect sliderFrame = self.slider.frame; CGFloat x = sliderFrame.origin.x + slideFrame.size.width * slider.value + thumb.size.width / 2; CGFloat y = sliderFrame.origin.y + sliderFrame.size.height / 2; return CGPointMake(x, y);


Es mejor usar el -[UIView convertRect:fromView:] lugar. Es más limpio y fácil sin ningún cálculo complicado:

- (IBAction)scrub:(UISlider *)sender { CGRect _thumbRect = [sender thumbRectForBounds:sender.bounds trackRect:[sender trackRectForBounds:sender.bounds] value:sender.value]; CGRect thumbRect = [self.view convertRect:_thumbRect fromView:sender]; // Use the rect to display a popover (pre iOS 8 code) [self.popover dismissPopoverAnimated:NO]; self.popover = [[UIPopoverController alloc] initWithContentViewController:[UIViewController new]]; [self.popover presentPopoverFromRect:thumbRect inView:self.view permittedArrowDirections:UIPopoverArrowDirectionDown|UIPopoverArrowDirectionUp animated:YES]; }


Esto devolverá la posición X correcta de la imagen del centro del pulgar de UISlider en las coordenadas de vista:

- (float)xPositionFromSliderValue:(UISlider *)aSlider { float sliderRange = aSlider.frame.size.width - aSlider.currentThumbImage.size.width; float sliderOrigin = aSlider.frame.origin.x + (aSlider.currentThumbImage.size.width / 2.0); float sliderValueToPixels = (((aSlider.value - aSlider.minimumValue)/(aSlider.maximumValue - aSlider.minimumValue)) * sliderRange) + sliderOrigin; return sliderValueToPixels; }

Póngalo en su controlador de vista y úselo de esta manera: (se supone que la propiedad se llama control deslizante)

float x = [self xPositionFromSliderValue:self.slider];


Esto funcionará para que el UISlider se coloque en cualquier lugar de la pantalla. La mayoría de las otras soluciones solo funcionarán cuando el UISlider esté alineado con el borde izquierdo de la pantalla. Tenga en cuenta que usé frame lugar de bounds para el thumbRect, para lograr eso. Y muestro dos variaciones, basadas en el uso de frame o bounds para trackRect

extension UISlider { //this version will return the x coordinate in relation to the UISlider frame var thumbCenterX: CGFloat { return thumbRect(forBounds: frame, trackRect: trackRect(forBounds: bounds), value: value).midX } //this version will return the x coordinate in relation to the UISlider''s containing view var thumbCenterX: CGFloat { return thumbRect(forBounds: frame, trackRect: trackRect(forBounds: frame), value: value).midX } }


Intenté esto después de leer la sugerencia anterior:

yourLabel = [[UILabel alloc]initWithFrame:....]; //Call this method on Slider value change event -(void)sliderValueChanged{ CGRect trackRect = [self.slider trackRectForBounds:self.slider.bounds]; CGRect thumbRect = [self.slider thumbRectForBounds:self.slider.bounds trackRect:trackRect value:self.slider.value]; yourLabel.center = CGPointMake(thumbRect.origin.x + self.slider.frame.origin.x, self.slider.frame.origin.y - 20); }

Para la versión Swift

func sliderValueChanged() -> Void { let trackRect = self.slider.trackRect(forBounds: self.slider.bounds) let thumbRect = self.slider.thumbRect(forBounds: self.slider.bounds, trackRect: trackRect, value: self.slider.value) yourLabel.center = CGPoint(x: thumbRect.origin.x + self.slider.frame.origin.x + 30, y: self.slider.frame.origin.y - 60) }

Pude obtener el valor más preciso al usar este fragmento.


La solución anterior es útil cuando UISlider es horizontal. En un proyecto reciente, necesitamos usar UISlider con ángulo. Entonces necesito obtener la posición xey. Usando debajo para calcular el eje x, y:

- (CGPoint)xyPositionFromSliderValue:(UISlider *)aSlider WithAngle:(double)aangle{ //aangle means the dextrorotation angle compare to horizontal. float xOrigin = 0.0; float yOrigin = 0.0; float xValueToaXis=0.0; float yValueToaXis=0.0; float sliderRange = slider_width-aSlider.currentThumbImage.size.width; xOrigin = aSlider.frame.origin.x+slider_width*fabs(cos(aangle/180.0*M_PI)); yOrigin = aSlider.frame.origin.y; xValueToaXis = xOrigin + ((((((aSlider.value-aSlider.minimumValue)/(aSlider.maximumValue-aSlider.minimumValue)) * sliderRange))+(aSlider.currentThumbImage.size.width / 2.0))*cos(aangle/180.0*M_PI)) ; yValueToaXis = yOrigin + ((((((aSlider.value-aSlider.minimumValue)/(aSlider.maximumValue-aSlider.minimumValue)) * sliderRange))+(aSlider.currentThumbImage.size.width / 2.0))*sin(aangle/180.0*M_PI)); CGPoint xyPoint=CGPointMake(xValueToaXis, yValueToaXis); return xyPoint; }

Además, ¿puedo crear un control deslizante Ranger basado en UISlider? Gracias.


Me acerqué al primer mapeo del intervalo de valores del UISlider en porcentajes y luego tomé el mismo porcentaje del tamaño del control deslizante menos el porcentaje del tamaño del pulgar, un valor al que agregué la mitad del tamaño del pulgar para obtener su centro.

- (float)mapValueInIntervalInPercents: (float)value min: (float)minimum max: (float)maximum { return (100 / (maximum - minimum)) * value - (100 * minimum)/(maximum - minimum); } - (float)xPositionFromSliderValue:(UISlider *)aSlider { float percent = [self mapValueInIntervalInPercents: aSlider.value min: aSlider.minimumValue max: aSlider.maximumValue] / 100.0; return percent * aSlider.frame.size.width - percent * aSlider.currentThumbImage.size.width + aSlider.currentThumbImage.size.width / 2; }


Me gustaría saber por qué ninguno de ustedes proporciona la respuesta más simple que consiste en leer el manual. Puede calcular todos estos valores con precisión y también ASEGURARSE DE QUE SE QUEDEN DE ESA FORMA, simplemente usando los métodos:

- (CGRect)trackRectForBounds:(CGRect)bounds - (CGRect)thumbRectForBounds:(CGRect)bounds trackRect:(CGRect)rect value:(float)value

que puedes encontrar fácilmente en la documentación del desarrollador.

Si la imagen del pulgar cambia y desea cambiar la forma en que está posicionada, subclase y anule estos métodos. El primero le da el rectángulo en el que el pulgar puede mover el segundo la posición del pulgar.


Swift 3

extension UISlider { var thumbCenterX: CGFloat { let trackRect = self.trackRect(forBounds: frame) let thumbRect = self.thumbRect(forBounds: bounds, trackRect: trackRect, value: value) return thumbRect.midX } }


Swift 3.0
Por favor, consulte si lo desea.

import UIKit extension UISlider { var trackBounds: CGRect { return trackRect(forBounds: bounds) } var trackFrame: CGRect { guard let superView = superview else { return CGRect.zero } return self.convert(trackBounds, to: superView) } var thumbBounds: CGRect { return thumbRect(forBounds: frame, trackRect: trackBounds, value: value) } var thumbFrame: CGRect { return thumbRect(forBounds: bounds, trackRect: trackFrame, value: value) } }