[iOS]2つのサムのあるUISliderの作成(試作品)

サム(Thumb)というのは、UISliderのツマミ(取っ手)の部分を指します。
~から~までの値、と言うような指定をしたい場合のカスタムUIです。

・完成図
[iOS]2つのサムのあるUISliderの作成(試作品)_1
※赤枠が全体のフレームになります。

このサンプルはBuildMobile様の記事を参考に作成しています。

尚、初めに申しておきます。
このソースは未完成品で、サイズが固定になっています。
そのため、frameの設定がほぼ全く無意味になっています。
今後完成させますが、現在はプロジェクトがかなり詰まっているので時間がありません。
それでも良いと言う方のみご利用ください。
ソースを改良して可変にしていただくのはこちらとしては全く問題ありませんのでご自由にご利用ください。

・このサンプルに使用する画像はコチラです。

//  RangeSlider.h
#import <UIKit/UIKit.h>

@interface RangeSlider : UIControl {
float minimumValue;
float maximumValue;
float minimumRange;
float selectedMinimumValue;
float selectedMaximumValue;
BOOL _maxThumbOn;
BOOL _minThumbOn;
float _padding;
UIImageView * _minThumb;
UIImageView * _maxThumb;
UIImageView * _track;
UIImageView * _trackBackground;
}

@property (nonatomic) float minimumValue;
@property (nonatomic) float maximumValue;
@property (nonatomic) float minimumRange;
@property (nonatomic) float selectedMinimumValue;
@property (nonatomic) float selectedMaximumValue;

@end


//  RangeSlider.m
#import "RangeSlider.h"

@implementation RangeSlider
@synthesize minimumValue, maximumValue, minimumRange, selectedMinimumValue, selectedMaximumValue;

@interface RangeSlider (PrivateMethods)
- (float)xForValue:(float)value;
- (float)valueForX:(float)x;
- (void)updateTrackHighlight;
- (void)reloadThumb;
@end

- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {

// Initialization code
_maxThumbOn = false;
_minThumbOn = false;
_padding = 20; //20 is a good value

minimumValue = 0;
selectedMinimumValue = 0;
maximumValue = 1;
selectedMaximumValue = 1;
minimumRange = 0;


_trackBackground = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bar-background.png"]];
_trackBackground.frame = CGRectMake((frame.size.width - _trackBackground.frame.size.width) / 2,
(frame.size.height - _trackBackground.frame.size.height) / 2,
_trackBackground.frame.size.width,
_trackBackground.frame.size.height);
[self addSubview:_trackBackground];
_track = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"bar-highlight.png"]];
_track.frame = CGRectMake((frame.size.width - _track.frame.size.width) / 2,
(frame.size.height - _track.frame.size.height) / 2,
_track.frame.size.width,
_track.frame.size.height);
[self addSubview:_track];

_minThumb = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"handle.png"]
highlightedImage:[UIImage imageNamed:@"handle-hover.png"]];
_minThumb.frame = CGRectMake(0,0, self.frame.size.height,self.frame.size.height);
// Just place the image in the middle, don't scale
_minThumb.contentMode = UIViewContentModeCenter;
_minThumb.center = CGPointMake([self xForValue:selectedMinimumValue],
(self.frame.size.height / 2));
NSLog(@"_minThumb frame:%@",NSStringFromCGRect(_minThumb.frame));
[self addSubview:_minThumb];
_maxThumb = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"handle.png"]
highlightedImage:[UIImage imageNamed:@"handle-hover.png"]];
_maxThumb.frame = CGRectMake(0,0, self.frame.size.height,self.frame.size.height);
// Just place the image in the middle, don't scale
_maxThumb.contentMode = UIViewContentModeCenter;
_maxThumb.center = CGPointMake([self xForValue:selectedMaximumValue],
(self.frame.size.height / 2));
[self addSubview:_maxThumb];
}
return self;
}

/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/

- (float)xForValue:(float)value
{
float x,a,b,p;
//a:スライダーの全体サイズ
a = (self.frame.size.width - (_padding*2));
//b:スライダー上での割合
b = (value - minimumValue) / (maximumValue - minimumValue);
if(isnan(b))b = 0;
if(isinf(b))b = 0;
p = _padding;
x = a * b + p;
return x;
// return (self.frame.size.width-(_padding*2))*((value - minimumValue) / (maximumValue - minimumValue))+_padding;
}
- (float)valueForX:(float)x{
return minimumValue + (x-_padding) / (self.frame.size.width-(_padding*2)) * (maximumValue - minimumValue);
}

- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
CGPoint touchPoint = [touch locationInView:self];
if(CGRectContainsPoint(_minThumb.frame, touchPoint)){
_minThumbOn = true;
}else if(CGRectContainsPoint(_maxThumb.frame, touchPoint)){
_maxThumbOn = true;
}
return YES;
}

-(void)updateTrackHighlight{
float tmp_x,tmp_y,tmp_width,tmp_height;
tmp_x = _minThumb.center.x;
tmp_y = _track.center.y - (_track.frame.size.height/2);
tmp_width = _maxThumb.center.x - _minThumb.center.x;
tmp_height = _track.frame.size.height;
_track.frame = CGRectMake(tmp_x, tmp_y, tmp_width, tmp_height);
}

- (void)endTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
_minThumbOn = false;
_maxThumbOn = false;
}

- (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event{
if(!_minThumbOn && !_maxThumbOn){
return YES;
}
CGPoint touchPoint = [touch locationInView:self];
if(_minThumbOn){
_minThumb.center = CGPointMake(MAX([self xForValue:minimumValue],MIN(touchPoint.x, [self xForValue:selectedMaximumValue - minimumRange])), _minThumb.center.y);
}
if(_maxThumbOn){
_maxThumb.center = CGPointMake(MIN([self xForValue:maximumValue], MAX(touchPoint.x, [self xForValue:selectedMinimumValue + minimumRange])), _maxThumb.center.y);
}
[self setNeedsDisplay];

// For min
selectedMinimumValue = [self valueForX:_minThumb.center.x];
NSLog(@"Lower value is now %f", selectedMinimumValue);
// For max
selectedMaximumValue = [self valueForX:_maxThumb.center.x];
NSLog(@"Upper value is now %f", selectedMaximumValue);
// Below the if statements
[self sendActionsForControlEvents:UIControlEventValueChanged];

// Inside continueTrackingWithThumb, above [self setNeedsDisplay];
[self updateTrackHighlight];

return YES;
}

-(void)setSelectedMinimumValue:(float)_selectedMinimumValue{
selectedMinimumValue = _selectedMinimumValue;
[self reloadThumb];
}

-(void)setSelectedMaximumValue:(float)_selectedMaximumValue{
selectedMaximumValue = _selectedMaximumValue;
[self reloadThumb];
}

-(void)reloadThumb{
_minThumb.center = CGPointMake([self xForValue:selectedMinimumValue],
(self.frame.size.height / 2));
NSLog(@"_minThumb frame:%@",NSStringFromCGRect(_minThumb.frame));
_maxThumb.center = CGPointMake([self xForValue:selectedMaximumValue],
(self.frame.size.height / 2));
[self updateTrackHighlight];
}

- (void)setMinimumValue:(float)_minimumValue {
minimumValue = _minimumValue;
[self reloadThumb];
}

- (void)setMaximumValue:(float)_maximumValue {
maximumValue = _maximumValue;
[self reloadThumb];
}
@end


・利用例
//Frameはこのサイズで利用してください。
//これ以外だとはみ出たり、可動範囲が見えているものより小さかったりします。
RangeSlider *slider = [[RangeSlider alloc] initWithFrame:CGRectMake(0, 0, 300, 50)];
slider.minimumValue = 1;
slider.selectedMinimumValue = 2;
slider.maximumValue = 10;
slider.selectedMaximumValue = 8;
slider.minimumRange = 2;
[self.view addSubview:slider];



参考URL:Wicked iOS Range Slider: Part One
このエントリーをはてなブックマークに追加

tag : iOS UISlider custom カスタム サム Thumb 2つ double 範囲 指定

コメントの投稿

非公開コメント

Translation


プロフィール

チーズくん

Author:チーズくん
個人的メモをただ羅列しています。
twitter:@cheese1038

バロメーター
最新記事
最新コメント
最新トラックバック
月別アーカイブ
カテゴリ