MPVolumeView没有';t在iOS 7中正确重画
因此,我有一个iOS7应用程序,我在其中使用了MPVolumeView没有';t在iOS 7中正确重画,ios,uiview,ios7,mpvolumeview,Ios,Uiview,Ios7,Mpvolumeview,因此,我有一个iOS7应用程序,我在其中使用了MPVolumeView,这样用户就可以控制音量了。我在这个特定的MPVolumeView上隐藏了route按钮,并使用另一个MPVolumeView将滑块禁用作为我的AirPlay图标 我的应用程序支持纵向和横向,并且音量滑块在这两种不同模式下的宽度不同 如果视图首先以横向模式初始化,则MPVolumeView将正确调整自身大小 但是,当视图在纵向模式下初始化,然后我旋转到横向模式时,应用程序中的所有其他内容都会被调整/移动,除了MPVolumeV
MPVolumeView
,这样用户就可以控制音量了。我在这个特定的MPVolumeView
上隐藏了route按钮,并使用另一个MPVolumeView
将滑块禁用作为我的AirPlay图标
我的应用程序支持纵向和横向,并且音量滑块在这两种不同模式下的宽度不同
如果视图首先以横向模式初始化,则MPVolumeView
将正确调整自身大小
但是,当视图在纵向模式下初始化,然后我旋转到横向模式时,应用程序中的所有其他内容都会被调整/移动,除了MPVolumeView
之外,其他内容只会被移动,并且不会像应该的那样变短
我在MPVolumeView
上使用自定义图像,如果我删除了曲目的自定义图像,这个问题就会消失
以下是用于初始化MPVolumeView的代码
self.volumeView = [[MPVolumeView alloc] initWithFrame:CGRectZero];
self.volumeView.showsRouteButton = NO;
self.volumeView.layer.borderColor = [[UIColor redColor] CGColor];
self.volumeView.layer.borderWidth = 1.0f;
if (AT_LEAST_IOS7) {
// TODO: BUGBUG iOS7 doesn't redraw this MPVolumeView correctly when it's frame changes (i.e. we rotate to the portrait view).
// These images simply make the bar a little thicker than the standard thickness (to match the iOS7 music app) but it's not redrawing
// correctly so we are going to have to live with a slightly thinner bar.
[self.volumeView setMaximumVolumeSliderImage:[UIImage imageNamed:@"volume_bar_max"] forState:UIControlStateNormal];
[self.volumeView setMinimumVolumeSliderImage:[UIImage imageNamed:@"volume_bar_min"] forState:UIControlStateNormal];
[self.volumeView setVolumeThumbImage:[UIImage imageNamed:@"volume_scrubber"] forState:UIControlStateNormal];
}
[self addSubview:self.volumeView];
在LayoutSubView中,我正在重新定位/缩放其框架:
self.volumeView.frame = CGRectIntegral(CGRectMake(controlsLeft + kEdgeToSliderSideWidth,
volumeTop,
controlsWidth - (2 * kEdgeToSliderSideWidth),
volumeSize.height));
以下是以纵向模式启动视图时的外观:(总宽640像素)
当它旋转到横向时,它最终看起来是这样的:(总宽568像素)
有人有什么想法吗?我也遇到了同样的问题。我当前的解决方法是在屏幕旋转后销毁并重新添加滑块:
- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
//remove the old view
for (UIView *subview in self.volumeViewContainer.subviews)
[subview removeFromSuperview];
//recreate it
UIImage *slider = [[UIImage imageNamed:@"slider"] resizableImageWithCapInsets:UIEdgeInsetsMake(0.0, 15.0, 0.0, 15.0)];
UIImage *knobImage = [UIImage imageNamed:@"slider_knob"];
MPVolumeView *volumeView = [[[MPVolumeView alloc] initWithFrame:self.volumeViewContainer.bounds] autorelease];
[volumeView setMinimumVolumeSliderImage:slider forState:UIControlStateNormal];
[volumeView setMaximumVolumeSliderImage:slider forState:UIControlStateNormal];
[volumeView setVolumeThumbImage:knobImage forState:UIControlStateNormal];
[self.volumeViewContainer addSubview:volumeView];
}
这样做仍然存在一个问题,即滑块在旋转过程中仍然显示有小故障。这就是为什么我将滑块渲染为图像,并在旋转发生之前将滑块与所述图像交换:
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
//render to UIImage
UIGraphicsBeginImageContextWithOptions(self.volumeViewContainer.frame.size, NO, 0.0);
[self.volumeViewContainer.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//remove old slider
for (UIView *subview in self.volumeViewContainer.subviews)
[subview removeFromSuperview];
//add UIImageView which resizes nicely with the container view
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:self.volumeViewContainer.bounds] autorelease];
imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
imageView.image = img;
[self.volumeViewContainer addSubview:imageView];
}
我知道这不是一个真正的解决方案,但我认为这总比什么都没有好,我希望它能帮助你 在做了大量的实验之后,似乎MPVolumeView在iOS 7.0.x中有很多缺陷 我遇到了一个问题,即为最小/最大滑块、音量拇指和路线自定义图像有时会导致滑块展开以覆盖路线按钮 当我改变调用顺序时,它解决了这个问题。诀窍是首先调用setVolumeThumbImage和setRouteButtonImage,然后调用setMinimumVolumeSliderImage和setMaximumVolumeSliderImage 这解决了路线按钮上的重叠轨道 然而,这导致了一个新问题,maximumSliderImage开始与volumeThumbImage重叠 最终的解决方案是在MPVolumeView的子类中将thumb层放在前面,如下所示:
- (void)_initialize {
UIImage *scrubber = [UIImage imageNamed:@"volume_scrubber_grip"];
scrubberSize = scrubber.size;
[self setVolumeThumbImage:scrubber forState:UIControlStateNormal];
[self setRouteButtonImage:[UIImage imageNamed:@"airplay_button"] forState:UIControlStateNormal];
[self setMinimumVolumeSliderImage:[UIImage imageNamed:@"min_slider"] forState:UIControlStateNormal];
[self setMaximumVolumeSliderImage:[UIImage imageNamed:@"max_slider"] forState:UIControlStateNormal];
}
- (void)layoutSubviews {
[super layoutSubviews];
[self.subviews enumerateObjectsUsingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
if([obj isKindOfClass:[UISlider class]]) {
UISlider *slider = (UISlider *)obj;
[slider.subviews enumerateObjectsUsingBlock:^(UIView *obj2, NSUInteger idx, BOOL *stop2) {
if(CGSizeEqualToSize(obj2.frame.size, scrubberSize)) {
[obj bringSubviewToFront:obj2];
*stop2 = YES;
}
}];
*stop = YES;
}
}];
}
我测试了另一种效果很好的解决方案。我将
MPVolumeView
嵌入一个简单的UIView
(可以在情节提要中创建)。然后我对UIView
的属性“bounds”进行键值观察。当此属性更改时,我将MPVolumeView
的框架更新为UIView
的新边界
此解决方案同时处理自动旋转和自动布局
import UIKit
import MediaPlayerclass ViewController: UIViewController {
@IBOutlet weak var volumeViewContainer: UIView!
override func viewDidLoad() {
super.viewDidLoad()
volumeViewContainer.backgroundColor = UIColor.grayColor()
var volumeView = MPVolumeView(frame: volumeViewContainer.bounds)
volumeViewContainer.addSubview(volumeView)
volumeViewContainer.addObserver(self, forKeyPath: "bounds", options: nil, context: nil)
}
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if let subview = volumeViewContainer.subviews.first as? UIView {
subview.frame = volumeViewContainer.bounds
}
}
}
导入UIKit
导入MediaPlayerclass ViewController:UIViewController{
@IBOutlet弱var VolumeView容器:UIView!
重写func viewDidLoad(){
super.viewDidLoad()
volumeViewContainer.backgroundColor=UIColor.grayColor()
var volumeView=MPVolumeView(框架:volumeViewContainer.bounds)
volumeViewContainer.addSubview(volumeView)
addObserver(self,forKeyPath:“bounds”,选项:nil,上下文:nil)
}
重写func observeValueForKeyPath(键路径:字符串,对象对象:AnyObject,更改:[NSObject:AnyObject],上下文:UnsafeMutablePointer){
如果let subview=volumeViewContainer.subviews.first as?UIView{
subview.frame=volumeViewContainer.bounds
}
}
}
很高兴知道这不仅仅是我们!谢谢分享你的解决方法。也许可以添加一个解释,而不仅仅是一堆代码
@IBOutlet var volumeViewHolder: UIView!
override func viewDidLoad() {
super.viewDidLoad()
volumeViewHolder.backgroundColor = UIColor.clearColor()
var volumeView : MPVolumeView = MPVolumeView()
volumeView.frame = volumeViewHolder.frame
volumeView.center = volumeViewHolder.center
volumeView.sizeToFit()
volumeView.showsRouteButton = false
volumeView.showsVolumeSlider = true
volumeView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
volumeViewHolder.addSubview(volumeView)
}