2013-10-07 6 views
8

Итак, у меня есть приложение iOS7, в котором я использую MPVolumeView, чтобы пользователь мог контролировать уровень громкости. У меня есть кнопка маршрута, скрытая на этом MPVolumeView, и используйте другой MPVolumeView, а слайдер отключен как значок AirPlay.MPVolumeView неправильно перерисовывается в iOS 7

Мое приложение поддерживает как портретную, так и ландшафтную ориентации, а ползунок громкости - это разная ширина в этих двух разных режимах.

Если представление сначала инициализируется в ландшафтном режиме, то 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]; 

И в layoutSubviews я репозиционирование/масштабирования это рама:

self.volumeView.frame = CGRectIntegral(CGRectMake(controlsLeft + kEdgeToSliderSideWidth, 
                volumeTop, 
                controlsWidth - (2 * kEdgeToSliderSideWidth), 
                volumeSize.height)); 

Вот как это выглядит, когда представление начинается в Портретный режим: (общая ширина 640 пикселей)

Portrait Mode

И когда он получает поворачивается на альбомную он заканчивает тем, как это: (общая ширина 568 пикселей)

Landscape Mode

Кто-нибудь есть какие-нибудь идеи?

ответ

4

У меня такая же проблема. Мой текущий обходной путь, чтобы разрушить и заново добавить ползунок после поворота экрана:

- (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]; 
} 

Я знаю, что это не является реальным решением, но я думаю, что это лучше, чем ничего, и я надеюсь, что это помогает вам.

+0

Это хорошо, чтобы знать, что это не только у нас! Спасибо, что поделились своим обходом. – jrwagz

2

После много экспериментов кажется, что MPVolumeView очень плохо работает в iOS 7.0.x.

У меня возникла проблема, когда пользовательские изображения для слайдеров min/max, большого объема и маршрута большого объема иногда приводили к тому, что ползунок расширялся, чтобы закрыть кнопку маршрута.

Когда я изменил порядок, в котором они вызывается, он исправил проблему. Фокус в том, чтобы сначала вызвать setVolumeThumbImage и setRouteButtonImage, затем установитьMinimumVolumeSliderImage и setMaximumVolumeSliderImage.

Это касалось перекрывающейся дорожки над кнопкой маршрута.

ОДНАКО, это вызвало новый выпуск, в котором максимальное значениеSliderImage начало перекрывать volumeThumbImage!

Конечный раствор, чтобы довести слой большого пальца, чтобы перед следующим образом, в подклассе MPVolumeView:

- (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; 
     } 
    }]; 
} 
1

Я испытал другое решение, которое работает нормально. Я вставляю MPVolumeView в простой UIView (который может быть создан в раскадровке). Затем я выполняю наблюдение за ключевыми значениями на «границах» свойства UIView. Когда это свойство изменяется, я обновляю фрейм 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 
    } 
} 

} 
-2
@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) 

} 
+1

может добавить объяснение, а не просто кучу кода – Epicblood

 Смежные вопросы

  • Нет связанных вопросов^_^