2012-11-21 15 views
9

मैंने एंड्रॉइड के लिए एक एप्लीकेशन बनाया है, जिसमें एक संख्या पिकर है। और मुझे इस नंबरपिकर के मान को बदलने की जरूरत है, लेकिन एक चिकनी एनीमेशन के साथ जब आप इसे स्पर्श करते हैं और इसके मूल्य को बदलते हैं।एनीमेशन के साथ नंबरपिकर के मूल्य को कैसे बदला जाए?

उदाहरण के लिए, मान लें कि वर्तमान मान 1 है और यह 5 होने जा रहा है, मैं चाहता हूं कि नंबरपिकर 1 से 2 तक 3 तक चलने के लिए और इसी तरह से चल रहा हो। लेकिन मैं चाहता हूं कि यह सिर्फ मूल्यों को तुरंत बदल न सके!

अगर मैं निम्नलिखित कोड का उपयोग करें:

numberPicker.setValue(5); 

अपने मूल्य तुरन्त 5 के लिए बदल जाएगा, लेकिन मैं इसे जब आप मैन्युअल रूप से उसे स्पर्श करें और यह स्पिन बनाने की तरह 1 से 5 तक रोल करना चाहते हैं।

उत्तर

15

मैं इसे refelction

 /** 
     * using reflection to change the value because 
     * changeValueByOne is a private function and setValue 
     * doesn't call the onValueChange listener. 
     * 
     * @param higherPicker 
     *   the higher picker 
     * @param increment 
     *   the increment 
     */ 
     private void changeValueByOne(final NumberPicker higherPicker, final boolean increment) { 

      Method method; 
      try { 
       // refelction call for 
       // higherPicker.changeValueByOne(true); 
       method = higherPicker.getClass().getDeclaredMethod("changeValueByOne", boolean.class); 
       method.setAccessible(true); 
       method.invoke(higherPicker, increment); 

      } catch (final NoSuchMethodException e) { 
       e.printStackTrace(); 
      } catch (final IllegalArgumentException e) { 
       e.printStackTrace(); 
      } catch (final IllegalAccessException e) { 
       e.printStackTrace(); 
      } catch (final InvocationTargetException e) { 
       e.printStackTrace(); 
      } 
     } 

सही काम करता है के माध्यम से हल किया। मुझे नहीं पता कि यह विधि निजी क्यों है

+0

[इस समस्या] को ठीक करने के लिए अपनी तकनीक का उपयोग किया गया (http://stackoverflow.com/q/17708325/473232)। धन्यवाद। – dgel

+0

पुराने धागे को पुनर्जीवित करने के लिए खेद है, लेकिन क्या यह तेजी से बढ़ने के बजाय संख्यापिकर को कम करने के लिए एक आसान तरीका होगा? संपादित करें: समझ गया! सिर्फ तर्क के बदले तर्क को गलत में बदलना होगा। – intA

+0

मुझे इस पुराने धागे को पुनर्जीवित करने पर गर्व है। दो साल बाद, यह मेरे लिए काम करता है! मुझे आश्चर्य है कि कई घटकों के अंदर बहुत सी विशेषताएं निजी क्यों हैं। यह लगभग निराशाजनक है। –

3

मुझे विश्वास नहीं है कि यह मूल रूप से समर्थित है। मैं इसे स्वयं करने का एक 'गंदा' जिस तरह के बारे में सोचा:

आप NumberPicker के scrollBy (int x, int y) समारोह iteratively कहा जाता है एनीमेशन के प्रभाव बनाने के लिए उपयोग कर सकते हैं।

कुछ बातें ध्यान में रखना:

  • scrollBy (एक्स, वाई) पिक्सल के साथ काम करता है। चूंकि एंड्रॉइड को उन सभी अलग-अलग स्क्रीन घनत्व मिल गए हैं, आपको पहले क्या करना चाहिए (मैं इसे परीक्षण और त्रुटि से करता हूं) 'डीपी' दूरी जो लगातार मूल्य पर स्क्रॉल करने के अनुरूप होती है, और इसे पिक्सल में परिवर्तित करने के लिए इसका इस्तेमाल करें।
  • scrollBy (एक्स, वाई) के पहले पैरामीटर 0 के एक मूल्य लेना चाहिए, के मामले में यह स्पष्ट नहीं है

मैं एनिमेशन अपने आप एंड्रॉयड में नहीं किया है, लेकिन एक बहुत अच्छा एपीआई के बाद से वहाँ है हनीकॉम्ब जो शायद इसे पूरा करना आसान बनाता है।

मुझे खेद है, लेकिन यह सबसे आसान है जो मैं सोच सकता हूं!

संपादित करें: 'डी पी' से पिक्सल को बदलने के लिए:

private float pxFromDp(float dp) 
{ 
    return dp * this.getContext().getResources().getDisplayMetrics().density; 
} 

आप करना होगा क्या परीक्षण scrollBy बुला (0, pxFromDp (डीपी)) अलग 'डी पी' मूल्यों के साथ, आप जब तक सटीक एक प्राप्त करें जो नंबरपिकर को एक नंबर पर ले जाता है। एक बार जब आप वह मान प्राप्त कर लेंगे, तो आप अपनी एनीमेशन विधि बना सकते हैं कि एक्स संख्याओं को ऊपर ले जाने पर इस डीपी दूरी को X बार स्क्रॉल किया जाएगा। यदि आप इसे पूरी तरह से समझ में नहीं आता :)

+0

ओह ;-) अपने काफी स्मार्ट जवाब के लिए धन्यवाद आप कृपया अपना पहला बिंदु की व्याख्या करेंगे आप का उल्लेख किया? 'डीपी' और' पिक्सेल 'के बारे में। मैं इसे आज़माउंगा और आपको बता दूंगा (निश्चित रूप से स्वीकृत उत्तर के रूप में अपना उत्तर चिह्नित करके: डी) फिर से धन्यवाद! – Mehran

+0

मैंने इसे विवरण में जोड़ा :) – alfongj

+0

मेरे लिए काम नहीं करता है। बस * scrollBy (x, y) * का उपयोग करके मैन्युअल रूप से स्क्रॉलिंग के समान प्रभाव नहीं देता है। जैसे वर्तमान में चयनित नंबर बिल्कुल स्क्रॉल नहीं करता है, यह सिर्फ केंद्र में रहता है और फिर नए नंबर के साथ बदल जाता है। और * यूपी *, * नीचे * स्क्रॉल करते समय तीर गायब नहीं होते हैं। –

1

वहाँ NumberPicker, जो है

changeCurrentByOne(boolean increment) 

अंदर निजी विधि आप इसे सार्वजनिक करने और इसका इस्तेमाल कर सकते हैं

फिर कहें। यूपी या नंबरपिकर के तीर को दबाते समय आप इस विधि को क्रिया में देख सकते हैं। शायद यह वह नहीं है जिसे आप ढूंढ रहे हैं क्योंकि यह विधि एनीमेशन का अधिक नियंत्रण नहीं देती है, लेकिन यह निश्चित रूप से सेट वैल्यू से बेहतर है। किसी भी एनीमेशन के बिना setValue उपयोगकर्ता के लिए भयानक लग रहा है।

2

धन्यवाद @passsy। अपने जवाब को प्रेरित किया: यह समाधान एकाधिक वृद्धि/कमी चरण का समर्थन करता है। इसके अलावा, के साथ और एकाधिक संख्या पिकर्स (अतिरिक्त कोडिंग के बिना) के साथ निष्पादित किया जा सकता है।

class IncreaseValue { 
    private int counter = 0; 
    private final NumberPicker picker; 
    private final int incrementValue; 
    private final boolean increment; 

    private final Handler handler = new Handler(); 
    private final Runnable fire = new Runnable() { @Override public void run() { fire(); } }; 

    /*public*/ IncreaseValue(final NumberPicker picker, final int incrementValue) { 
     this.picker = picker; 
     if (incrementValue > 0) { 
      increment = true; 
      this.incrementValue = incrementValue; 
     } else { 
      increment = false; 
      this.incrementValue = -incrementValue; 
     } 
    } 

    /*public*/ void run(final int startDelay) { 
     handler.postDelayed(fire, startDelay); // This will execute the runnable passed to it (fire) 
     // after [startDelay in milliseconds], ASYNCHRONOUSLY. 
    } 

    private void fire() { 
     ++counter; 
     if (counter > incrementValue) return; 

     try { 
      // refelction call for 
      // picker.changeValueByOne(true); 
      final Method method = picker.getClass().getDeclaredMethod("changeValueByOne", boolean.class); 
      method.setAccessible(true); 
      method.invoke(picker, increment); 

     } catch (final NoSuchMethodException | InvocationTargetException | 
       IllegalAccessException | IllegalArgumentException e) { 
      Log.d(TAG, "...", e); 
     } 

     handler.postDelayed(fire, 120); // This will execute the runnable passed to it (fire) 
     // after 120 milliseconds, ASYNCHRONOUSLY. Customize this value if necessary. 
    } 
} 

उपयोग:

// Suppose picker1 as a NumberPicker 
IncreaseValue increasePicker1 = new IncreaseValue(picker1, 10); // So picker1 will be increased 10 steps. 
increasePicker1.run(0); // Increase immediately. If you want to run it from onCreate(), onStart() or ... of your activity, you will probably need to pass a positive value to it (e.g. 100 milliseconds). 
संबंधित मुद्दे