UISlider вместе с ProgressView

Есть ли способ сделать яблочный дом, чтобы получить UISlider с ProgressView. Это используется многими streamовыми приложениями, например, native quicktimeplayer или youtube. (Чтобы быть уверенным: я заинтересован в визуализации)

Ползунок с загрузчиком

приветствие Саймона

Вот простая версия того, что вы описываете.

alt text

Это «просто» в том смысле, что я не стал пытаться добавить оттенки и другие тонкости. Но это легко построить, и вы можете настроить его, чтобы сделать более тонким способом, если хотите. Например, вы можете создать свой собственный образ и использовать его как большой палец слайдера.

Это на самом деле подclass UISlider, лежащий поверх подclassа UIView (MyTherm), который рисует термометр плюс два UILabels, которые рисуют числа.

Подclass UISlider устраняет встроенную дорожку, так что через нее проходит термометр. Но большой палец (ручка) UISlider по-прежнему перетаскивается обычным способом, и вы можете установить его на пользовательский образ, получить событие Value Changed, когда пользователь его перетащит, и так далее. Вот код для подclassа UISlider, который устраняет собственный трек:

- (CGRect)trackRectForBounds:(CGRect)bounds { CGRect result = [super trackRectForBounds:bounds]; result.size.height = 0; return result; } 

Термометр представляет собой экземпляр пользовательского подclassа UIView, MyTherm. Я создал его в банке и снял флажок с Opaque и дал ему цвет фона Clear Color. Он обладает свойством value поэтому он знает, сколько нужно заполнить термометром. Вот его drawRect: code:

 - (void)drawRect:(CGRect)rect { CGContextRef c = UIGraphicsGetCurrentContext(); [[UIColor whiteColor] set]; CGFloat ins = 2.0; CGRect r = CGRectInset(self.bounds, ins, ins); CGFloat radius = r.size.height / 2.0; CGMutablePathRef path = CGPathCreateMutable(); CGPathMoveToPoint(path, NULL, CGRectGetMaxX(r) - radius, ins); CGPathAddArc(path, NULL, radius+ins, radius+ins, radius, -M_PI/2.0, M_PI/2.0, true); CGPathAddArc(path, NULL, CGRectGetMaxX(r) - radius, radius+ins, radius, M_PI/2.0, -M_PI/2.0, true); CGPathCloseSubpath(path); CGContextAddPath(c, path); CGContextSetLineWidth(c, 2); CGContextStrokePath(c); CGContextAddPath(c, path); CGContextClip(c); CGContextFillRect(c, CGRectMake(r.origin.x, r.origin.y, r.size.width * self.value, r.size.height)); } 

Чтобы изменить значение термометра, измените значение экземпляра MyTherm на число от 0 до 1 и скажите ему перерисовать его с помощью setNeedsDisplay .

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

В интерфейсе Builder поместите ваш UISlider сразу поверх вашего UIProgressView и сделайте их одинакового размера.

На UISlider фоновая горизонтальная линия называется дорожкой, трюк – сделать ее невидимой. Мы делаем это с помощью прозрачного PNG и методов setMinimumTrackImage:forState: и setMaximumTrackImage:forState:

В методе viewDidLoad вашего controllerа просмотров добавьте:

 [self.slider setMinimumTrackImage:[UIImage imageNamed:@"transparent.png"] forState:UIControlStateNormal]; [self.slider setMaximumTrackImage:[UIImage imageNamed:@"transparent.png"] forState:UIControlStateNormal]; 

где self.slider ссылается на ваш UISlider .

Я протестировал код в Xcode, и это даст вам слайдер с независимым индикатором выполнения.

Создайте UISlider:

 // 1 // Make the slider as a public propriety so you can access it playerSlider = [[UISlider alloc] init]; [playerSlider setContinuous:YES]; [playerSlider setHighlighted:YES]; // remove the slider filling default blue color [playerSlider setMaximumTrackTintColor:[UIColor clearColor]]; [playerSlider setMinimumTrackTintColor:[UIColor clearColor]]; // Chose your frame playerSlider.frame = CGRectMake(--- , -- , yourSliderWith , ----); // 2 // create a UIView that u can access and make it the shadow of your slider shadowSlider = [[UIView alloc] init]; shadowSlider.backgroundColor = [UIColor lightTextColor]; shadowSlider.frame = CGRectMake(playerSlider.frame.origin.x , playerSlider.frame.origin.y , playerSlider.frame.size.width , playerSlider.frame.origin.size.height); shadowSlider.layer.cornerRadius = 4; shadowSlider.layer.masksToBounds = YES; [playerSlider addSubview:shadowSlider]; [playerSlider sendSubviewToBack:shadowSlider]; // 3 // Add a timer Update your slider and shadow slider programatically [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(updateSlider) userInfo:nil repeats:YES]; -(void)updateSlider { // Update the slider about the music time playerSlider.value = audioPlayer.currentTime; // based on ur case playerSlider.maximumValue = audioPlayer.duration; float smartWidth = 0.0; smartWidth = (yourSliderFullWidth * audioPlayer.duration ) / 100; shadowSlider.frame = CGRectMake( shadowSlider.frame.origin.x , shadowSlider.frame.origin.y , smartWidth , shadowSlider.frame.size.height); } 

Наслаждайтесь! PS У меня могут быть опечатки.

Решение, соответствующее моему дизайну:

 class SliderBuffering:UISlider { let bufferProgress = UIProgressView(progressViewStyle: .Default) override init (frame : CGRect) { super.init(frame : frame) } convenience init () { self.init(frame:CGRect.zero) setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setup() } func setup() { self.minimumTrackTintColor = UIColor.clearColor() self.maximumTrackTintColor = UIColor.clearColor() bufferProgress.backgroundColor = UIColor.clearColor() bufferProgress.userInteractionEnabled = false bufferProgress.progress = 0.0 bufferProgress.progressTintColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.5) bufferProgress.trackTintColor = UIColor.blackColor().colorWithAlphaComponent(0.5) self.addSubview(bufferProgress) } } 

Идея 1: вы легко можете использовать UISlider в качестве представления прогресса, подclassифицируя его. Он отвечает на такие методы, как «setValue: анимированные:», с помощью которых вы можете установить значение (т. Е. Прогресс) представления.

Ваше единственное «ограничение», создающее то, что вы видите в вашем примере, представляет собой буферную панель, которую вы можете создать с помощью «творчески» скинирования UISlider (потому что вы можете добавить к ней пользовательские скины) и, возможно, программным образом настроить этот скин.

Идея 2: Другой (более простой) вариант заключается в подclassе UIProgressView и создании UISlider внутри этого подclassа. Вы можете обрезать UISlider, чтобы иметь прозрачный скин (нет полосы, только ручка видимая) и класть ее поверх UIProgressView.

Вы можете использовать UIProgressView для предварительной загрузки (буферизация) и UISlider для индикации управления движением / выполнения.

Кажется довольно легко 🙂

Изменить: чтобы на самом деле ответить на ваш вопрос, нет внутреннего способа, но с этими инструментами было бы легко выполнить.

Вы можете сделать какой-то трюк, как это, это проще и понятнее. Просто вставьте приведенный ниже код в свой подclass UISlider.

 - (void)layoutSubviews { [super layoutSubviews]; if (_availableDurationImageView == nil) { // step 1 // get max length that our "availableDurationImageView" will show UIView *maxTrackView = [self.subviews objectAtIndex:self.subviews.count - 3]; UIImageView *maxTrackImageView = [maxTrackView.subviews objectAtIndex:0]; _maxLength = maxTrackImageView.width; // step 2 // get the right frame where our "availableDurationImageView" will place in superView UIView *minTrackView = [self.subviews objectAtIndex:self.subviews.count - 2]; _availableDurationImageView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"MediaSlider.bundle/4_jindu_huancun.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 2, 0, 2)]]; _availableDurationImageView.opaque = NO; _availableDurationImageView.frame = minTrackView.frame; [self insertSubview:_availableDurationImageView belowSubview:minTrackView]; } } - (void)setAvailableValue:(NSTimeInterval)availableValue { if (availableValue >=0 && availableValue <= 1) { // use "maxLength" and percentage to set our "availableDurationImageView" 's length _availableDurationImageView.width = _maxLength * availableValue; } } 

Добавляя решение мата, обратите внимание, что с iOS 7.0 реализация trackRectForBounds: оказывается невозможной. Вот мое решение этой проблемы:

В подclassе UISlider выполните следующее:

 -(void)awakeFromNib { [super awakeFromNib]; UIImage* clearColorImage = [UIImage imageWithColor:[UIColor clearColor]]; [self setMinimumTrackImage:clearColorImage forState:UIControlStateNormal]; [self setMaximumTrackImage:clearColorImage forState:UIControlStateNormal]; } 

с функцией imageWithColor в качестве этой функции:

 + (UIImage*) imageWithColor:(UIColor*)color { return [UIImage imageWithColor:color andSize:CGSizeMake(1.0f, 1.0f)]; } 

Это правильно позаботится об этом раздражающем треке Rectangle.

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

Вот решение в Objective C. https://github.com/abhimuralidharan/BufferSlider

Идея состоит в том, чтобы создать UIProgressview как свойство в подclassе UISlider и программно добавить необходимые ограничения.

 #import  //.h file @interface BufferSlider : UISlider @property(strong,nonatomic) UIProgressView *bufferProgress; @end #import "BufferSlider.h" //.m file @implementation BufferSlider - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setup]; } return self; } -(void)setup { self.bufferProgress = [[UIProgressView alloc] initWithFrame:self.bounds]; self.minimumTrackTintColor = [UIColor redColor]; self.maximumTrackTintColor = [UIColor clearColor]; self.value = 0.2; self.bufferProgress.backgroundColor = [UIColor clearColor]; self.bufferProgress.userInteractionEnabled = NO; self.bufferProgress.progress = 0.7; self.bufferProgress.progressTintColor = [[UIColor blueColor] colorWithAlphaComponent:0.5]; self.bufferProgress.trackTintColor = [[UIColor lightGrayColor] colorWithAlphaComponent:2]; [self addSubview:self.bufferProgress]; [self setThumbImage:[UIImage imageNamed:@"redThumb"] forState:UIControlStateNormal]; self.bufferProgress.translatesAutoresizingMaskIntoConstraints = NO; NSLayoutConstraint *left = [NSLayoutConstraint constraintWithItem:self.bufferProgress attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeft multiplier:1 constant:0]; NSLayoutConstraint *centerY = [NSLayoutConstraint constraintWithItem:self.bufferProgress attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeCenterY multiplier:1 constant:0.75]; // edit the constant value based on the thumb image NSLayoutConstraint *right = [NSLayoutConstraint constraintWithItem:self.bufferProgress attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0]; [self addConstraints:@[left,right,centerY]]; [self sendSubviewToBack:self.bufferProgress]; } - (instancetype)initWithCoder:(NSCoder *)coder { self = [super initWithCoder:coder]; if (self) { [self setup]; } return self; } @end 
  • drawRect не вызывается в моем подclassе UIImageView
  • Предварительная буферизация для AVQueuePlayer
  • Что такое NSCFDictionary?
  • Сохранить фотографии в пользовательский альбом в iPhones Photo Library
  • Objective-c iPhone-процент кодирует строку?
  • Как добавить 1 день к NSDate?
  • Пользовательские цвета в UITabBar
  • Правильный способ выхода из приложения iPhone?
  • Получите данные Exif от UIImage - UIImagePickerController
  • Выясните, кадр UIBarButtonItem в окне?
  • Как получить размер NSString
  • Interesting Posts

    Отобразить jquery ui автозаполненный список событий фокуса

    Аутентификация и запрос временной шкалы пользователя с помощью API Twitter 1.1 oAuth

    Как контролировать папку для изменений и выполнять команду, если она есть, в Windows?

    Присоединение к домашней группе Windows 7 прерывает подключения к общим ресурсам

    Excel: как удалить поисковые запросы из ячейки (ссылающийся URL)

    Как печатать значения регистров в GDB?

    Общие точки останова для запросов СМИ на быстродействующем сайте

    Как поддерживать HTTP OPTIONS-глагол в приложении ASP.NET MVC / WebAPI

    Удобное объявление строк времени компиляции в C ++

    Может ли поток потока беспроводного маршрутизатора без подключения к Интернету?

    Поддерживает ли AutoMapper Linq?

    Отменить команду «rm -rf ~»?

    Как настроить профиль пользователя при использовании django-allauth

    Как получить PID фонового процесса?

    Ребенок с максимальной высотой: 100% переполняет родительский

    Давайте будем гением компьютера.