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:
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.
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.
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With