Pregunta

I have a UIToolBar that is intended to contain sliders for controlling volume and brightness. I use a MPVolumeView slider for the volume, and an ordinary UISlider for the brightness. While the sliders themselves work fine, their vertical positions are mismatched:

Mismatched UISlider and MPVolumeView

How do I get them to be on the same height?

My code:

- (void) createToolbar{

toolBar = [[UIToolbar alloc] init];
toolBar.frame = CGRectMake(0, 0, self.view.frame.size.width, 44);

UISegmentedControl *modeSelector = [[UISegmentedControl alloc] initWithItems:[NSArray arrayWithObjects:@"Play", @"Rec", nil]];
[modeSelector setSegmentedControlStyle:UISegmentedControlStyleBar];
[modeSelector addTarget:self action:@selector(changePlayMode) forControlEvents:UIControlEventValueChanged];
modeSelector.selectedSegmentIndex = 0;
UIBarButtonItem *modeSelectorAsToolbarItem = [[UIBarButtonItem alloc] initWithCustomView:modeSelector];

brightnessSlider = [[UISlider alloc] initWithFrame:CGRectMake(0, 0, 150, 30)];
brightnessSlider.minimumValue = 0;
brightnessSlider.maximumValue = 1;
brightnessSlider.value = [[UIScreen mainScreen] brightness];
brightnessSlider.continuous = YES;
[brightnessSlider addTarget:self action:@selector(adjustBrightness:) forControlEvents:UIControlEventValueChanged];
UIBarButtonItem *brightSliderAsToolbarItem = [[UIBarButtonItem alloc] initWithCustomView:brightnessSlider];

MPVolumeView *volView = [[MPVolumeView alloc] initWithFrame:CGRectMake(0, 0, 150, 30)];
volView.showsRouteButton = NO;
UIBarButtonItem *volSliderAsToolbarItem = [[UIBarButtonItem alloc] initWithCustomView:volView];

UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];
UIBarButtonItem *toc = [[UIBarButtonItem alloc] initWithTitle:@"Contents" style:UIBarButtonItemStyleBordered target:self action:@selector(goToToC)];
[toolBar setItems:[NSArray arrayWithObjects:modeSelectorAsToolbarItem, flexibleSpace, brightSliderAsToolbarItem, volSliderAsToolbarItem, flexibleSpace, toc, nil] animated:NO];

toolBar.autoresizingMask |= UIViewAutoresizingFlexibleWidth;

[[self view] addSubview:toolBar];

}

(Changing the CGRectMake coordinates doesn't seem to do anything.)

A comment in the question "Custom MPVolumeView Thumb Image not vertically centered since iOS 5.1" seemed to suggest using the "Fixing thumb alignment" trick explained here, but implementing that code didn't seem to do anything as far as I could tell, and I'm not sure whether it was talking about the same problem.

¿Fue útil?

Solución

If you create a trivial subclass of MPVolumeView and override volumeSliderRectForBounds:, you can define your own alignment for the slider rect. I like to return the whole bounds, which centers the slider in the MPVolumeView's frame

@interface KMVolumeView : MPVolumeView

@end

@implementation KMVolumeView

- (CGRect)volumeSliderRectForBounds:(CGRect)bounds
{
    return bounds;
}

@end

Just use your subclass in code or in interface builder and you can then reliably position the volume view.

Otros consejos

I came up with something, that extends kmikael's answer:

@interface SystemVolumeView : MPVolumeView

@end

@implementation SystemVolumeView

- (CGRect)volumeSliderRectForBounds:(CGRect)bounds {
    CGRect newBounds=[super volumeSliderRectForBounds:bounds];

    newBounds.origin.y=bounds.origin.y;
    newBounds.size.height=bounds.size.height;

    return newBounds;
}

- (CGRect) routeButtonRectForBounds:(CGRect)bounds {
    CGRect newBounds=[super routeButtonRectForBounds:bounds];

    newBounds.origin.y=bounds.origin.y;
    newBounds.size.height=bounds.size.height;

    return newBounds;
}

@end

This implementation differs in that it still uses the default horizontal values but overrides the vertical ones in order to keep the MPVolumeView centered vertically in its container. It also overrides -routeButtonRectForBounds: so that the airplay/route button gets centered as well.

I have to wonder why the default implementation has a wonky vertical position.

SWIFT Version: come form hyperspasm's answer:

import Foundation

class SystemVolumeView: MPVolumeView {
    override func volumeSliderRect(forBounds bounds: CGRect) -> CGRect {
        var newBounds = super.volumeSliderRect(forBounds: bounds)
        newBounds.origin.y = bounds.origin.y
        newBounds.size.height = bounds.size.height
        return newBounds
    }
    override func routeButtonRect(forBounds bounds: CGRect) -> CGRect {
        var newBounds = super.routeButtonRect(forBounds: bounds)
        newBounds.origin.y = bounds.origin.y
        newBounds.size.height = bounds.size.height
        return newBounds
    }
}

I ended up just using UISlider for both, using the instructions provided in the "Get System Volume" and "Change System Volume" answers to make a volume slider instead of using MPVolumeView.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top