MPVolumeView没有';t在iOS 7中正确重画

MPVolumeView没有';t在iOS 7中正确重画,ios,uiview,ios7,mpvolumeview,Ios,Uiview,Ios7,Mpvolumeview,因此,我有一个iOS7应用程序,我在其中使用了MPVolumeView,这样用户就可以控制音量了。我在这个特定的MPVolumeView上隐藏了route按钮,并使用另一个MPVolumeView将滑块禁用作为我的AirPlay图标 我的应用程序支持纵向和横向,并且音量滑块在这两种不同模式下的宽度不同 如果视图首先以横向模式初始化,则MPVolumeView将正确调整自身大小 但是,当视图在纵向模式下初始化,然后我旋转到横向模式时,应用程序中的所有其他内容都会被调整/移动,除了MPVolumeV

因此,我有一个iOS7应用程序,我在其中使用了
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)

}