2010-05-11 31 views
7

我正在實現一個用戶可以操縱的UISlider來設置距離。 我從來沒有使用CocoaTouch UISlider,但已經使用其他框架滑塊,通常有一個變量設置「步」和其他「幫手」屬性。如何讓UISlider輸出精美的四捨五入數字?

UISlider的文檔僅處理最大值和最小值,輸出始終是一個6位十進制浮點數,與「滑動塊」的位置呈線性關係。我想我將不得不逐步實現所需的功能。

對用戶來說,最小/最大值的範圍從10米到999公里,我試圖以指數方式實現這一點,這對用戶來說會感覺很自然。即用戶體驗到對大小數值的控制感。此外,「輸出」具有合理的價值。值如10m 200m 2.5km 150km等,而不是1.2342356m或108.93837756km。

我希望前面200米的步長增加10米,然後可能是50米到500米,然後當通過1000米的值時,它開始處理公里,那麼它的步長= 1公里直到50公里,然後可能是25公里步驟等

任何方式,我去做這個我最終做了很多四捨五入和大量的計算在 forrest if語句和NSString/Number轉換,每次用戶移動滑塊一點點。

我希望有人可以借我一點靈感/數學幫助,或讓我知道 更精益的方法來解決這個問題。

我最後的想法是用100個字符串值填充和數組,然後讓滑塊的int值對應一個字符串,這不是很靈活,但可行。

感謝您提前給任何幫助:)

+1

現在我用蘋果數字,使我想要的實際數字(通過輸入一些數字,選擇並拖動。這使得Numbers在相同的時間間隔內產生數字)我做了大約75個數字。然後我導出爲CSV,通過Textmate運行並做了一些正則表達式來獲得數字作爲字符串@「number」, 將數字粘貼到數組中,並將滑塊拉出來: \t NSInteger numberLookup = lroundf([slider值]); \t NSString * distanceString = [sliderNumber objectAtIndex:numberLookup]; 我將滑塊分鐘設置爲0,最大爲[slideNumbers count]。 我仍然有興趣聽到想法:) – RickiG 2010-05-11 18:24:18

回答

0

最簡單的答案是使用分段控制與不同的「步長」。取決於用戶選擇的選項,滑塊將具有的步長大小。我甚至建議這可能是一種更友好的方法來處理它:)。

隨意使用Dapp來玩你的應用程序的外觀,看看分段控件如何適合設計。

但是......你想要一個更精簡的方法;)。

我開始編寫所需的10個左右的步驟,但當我意識到自己可能已經找到類似的解決方案時,我停下了腳步。你的字符串數組的想法是好的,我假設你將簡單地將滑塊值轉換爲整數並從數組中獲取相關索引?

有時候作爲程序員,我們在解決問題的方法上做得太過分了。是的,一個字符串數組並不是最「靈活」的解決方案,但速度很快!而且,我認爲,即使是天才的數學解決方案也不如您想像的那麼靈活。此外,如果您不打算在短時間內更改這些值,並且不需要不同的滑塊範圍,則只需創建一個靜態數組就可以了。

祝你好運!:)

+0

嗨Raal和謝謝。 「有時候,作爲程序員,我們對問題的解決方法太過分了」完美地總結了最後幾個小時:) 我花了25分鐘將我在之前對陣列評論中描述的解決方案放在一起。它完美的工作,我只處理75個值,所以查找時間/開銷幾乎不存在。 我讓我的滑塊從0-74變成了圓形/將數字轉換爲整數,然後查找相應的值。當它從米變爲千米時,我選擇了索引值21。 如果有人可以從中受益,我只會在代碼中發佈代碼。 – RickiG 2010-05-14 12:25:13

5

快速縮放解決方案包括三個特殊方法:

- (CGFloat)scaleValue:(CGFloat)value { 
    return pow(value, 10); 
} 

- (CGFloat)unscaleValue:(CGFloat)value { 
    return pow(value, 1.0/10.0); 
} 

- (CGFloat)roundValue:(CGFloat)value { 
    if(value <= 200) return floor(value/ 10) * 10; 
    if(value <= 500) return floor(value/ 50) * 50; 
    if(value <= 1000) return floor(value/100) * 100; 
    if(value <= 50000) return floor(value/1000) * 1000; 
    return floor(value/25000) * 25000; 
} 

反應到滑塊的變化會是這樣的:

- (void)sliderChange:(id)sender { 
    CGFloat value = mySlider.value; 
    value = [self scaleValue:value]; 
    value = [self roundValue:value]; 
    valueLabel.text = [NSString stringWithFormat:@"%f", value]; 
} 

您可以用下面的代碼初始化:

mySlider.maximumValue = [self unscaleValue:999000]; 
mySlider.minimumValue = [self unscaleValue:10]; 

我得到了上述所有工作沒有任何問題,但它可以使用一些防彈。 scaleValue:unscaleValue:方法應檢查不支持的值,我相信sliderChange:方法可能更有效。

就速度而言,我相信這比將數組拉出陣列要快。實際的滑塊行爲可能會感覺有點不可靠,並且沒有太多控制滑塊可用的值,所以它可能不會完全按照您的要求進行操作。使用真正的高功率似乎使它更有用。

+0

謝謝MrHen! 對於真正的指數值,這是一種相當精益的方法。 當我進行優化時,我會嘗試一下如何再次比較數組查找。 再次感謝。 – RickiG 2010-05-14 12:19:19

0
+ (NSArray*) getSliderNumbers { 

    NSArray *sliderNumbers = [NSArray arrayWithObjects:@"10", 
          @"20", 
          @"30", 
          @"40", 
          @"50", 
          @"60", 
          @"70", 
          @"80", 
          @"90", 
          @"100", 
          @"150", 
          @"200", 
          @"250", 
          @"300", 
          @"350", 
          @"400", 
          @"450", 
          @"500", 
          @"600", 
          @"700", 
          @"800", 
          @"900", 
          @"1", 
          @"1.5", 
          @"2.0", 
          @"2.5", 
          @"3.0", 
          @"3.5", 
          @"4", 
          @"4.5", 
          @"5", 
          @"5.5", 
          @"6", 
          @"6.5", 
          @"7", 
          @"7.5", 
          @"8", 
          @"8.5", 
          @"9", 
          @"9.5", 
          @"10", 
          @"15", 
          @"20", 
          @"25", 
          @"30", 
          @"35", 
          @"40", 
          @"45", 
          @"50", 
          @"55", 
          @"60", 
          @"65", 
          @"70", 
          @"75", 
          @"80", 
          @"85", 
          @"90", 
          @"95", 
          @"100", 
          @"200", 
          @"300", 
          @"400", 
          @"500", 
          @"600", 
          @"700", 
          @"800", 
          @"900", 
          nil]; 
    return sliderNumbers; 

} 

以上在實例化時被加載到一個數組:

設置滑塊:

customSlider.minimumValue = 0.0f; 
    customSlider.maximumValue = (CGFloat)[sliderNumbers count] - 1; 
    customSlider.continuous = YES; 
    customSlider.value = customSlider.maximumValue; 

呼籲UIControlEventValueChanged

- (void) sliderMove:(UISlider*) theSlider { 

    NSInteger numberLookup = lroundf([theSlider value]); 

    NSString *distanceString = [sliderNumbers objectAtIndex:numberLookup]; 
    CGFloat distanceInMeters; 

    if (numberLookup > 21) { 

     [self.indicator.indicatorLabel setText:[NSString stringWithFormat:@"%@ km", distanceString]];  
     distanceInMeters = [distanceString floatValue] * 1000; 
    } else { 

     [self.indicator.indicatorLabel setText:[NSString stringWithFormat:@"%@ m", distanceString]]; 
     distanceInMeters = [distanceString floatValue]; 
    } 

    if (oldDistanceInMeters != distanceInMeters) { 

     [self.delegate distanceSliderChanged:distanceInMeters]; 
     oldDistanceInMeters = distanceInMeters; 
    } 
} 

此方法甚至負責格式化的用戶界面的字符串,例如「200米」或「1.5公里」,然後使用以米爲單位的距離編號更新委託,以便在使用謂詞對結果進行排序時使用。

0

爲了做到這一點,你希望你的滑塊代表指數。例如,如果你想要一個10-100000的縮放比例,你希望你的滑塊的範圍是1(10 = 10^1)到5(100,000 = 10^5)。您可以將滑塊上的步進設置爲幾分之一,以便爲您提供所需的精度。就我的例子而言,我將使用20,000分鐘和最多20,000,000次的輸出(因爲這是我坐下來弄清楚的時候需要的)。由於我基本上將從最小值增加到最大值1000倍,所以我想要10^3,所以我的滑塊將會是0-3(10^0評估爲1)。我將使用.001步進,因此總共有3000個可能的位置。下面是你需要做到這一點的代碼:

$("#amount-slider").slider({ 
    value:20000, 
    min: 0, 
    max: 3, 
    step:.001, 
    slide: function(event, ui) { 
    $("#amount").val(Math.pow(10, ui.value)*20000); 
    } 
    }); 

假設你想要這個函數的反函數,所以你可以設置滑塊位置給予一定的外部輸入。然後你想使用對數:

var amtVal = parseFloat($("#amount").val()); 

    $('#amount-slider').slider('value', ((Math.log(amtVal/20000)/Math.log(10)))); 

你需要在兩個函數中調整20000以匹配你的基數。如果您的最大值必須由除10以外的其他指數導出,請更改10以​​及最大值(指數)。如果你以十的權力上升,生活將會變得更容易。這個解決方案

- (void) sliderChanged:(UISlider *)slider 
{ 
    int value = (int)[slider value]; 
    int stepSize = 500.0f; 

    value = value - value%stepSize; 

    [km setText:[NSString stringWithFormat:@"%d Km",value]]; 
} 

在一起,你可以將兩個按鈕(+和 - )調整滑塊值:

+2

這不是一個JavaScript問題... – 2011-01-04 22:02:24

+0

感謝,對jQuery有用,但不是Cocoa Touch! – 2011-02-05 03:01:18

2

您還可以設置一個「步長」,以建立您的滑塊這樣

- (void) incrementKm:(UIButton *)button 
{ 
    [kmSlider setValue:[kmSlider value] + 500.0f animated:YES]; 
    [self sliderChanged:kmSlider]; 
} 

- (void) decrementKm:(UIButton *)button 
{ 
    [kmSlider setValue:[kmSlider value] - 500.0f animated:YES]; 
    [self sliderChanged:kmSlider]; 
} 
1

下面是一個選項,如果你有選擇的變長數組你想要的滑塊來選擇:

-(void)setupSlider { 

    //this has to be (scale - 1) from sliderChanged selector to avoid index out of bounds error 
    _sldOptionPicker.maximumValue = 99; 

    //should be zero 
    _sldOptionPicker.minimumValue = 0; 

    //can be any value 0 to 99 
    _sldOptionPicker.value = 0;   

} 

-(IBAction)sliderChanged:(id)sender { 

    float scale = 100/[optionsArray count]; 

    int index = (int)(_sldOptionPicker.value/scale); 

    Option *mySelectedOption = (Option*)[optionsArray objectForIndex:index]; 

}