2013-09-04 11 views
12

Zasadniczo, muszę wykryć, kiedy zmiany postępu w SeekBar i narysuj widok tekstowy na szczycie kciuka wskazujący wartość postępu.Wykrywanie pozycji kciuka w SeekBar przed wersją interfejsu API 16

zrobić to poprzez wdrożenie OnSeekBarChangeListener i na metodzie public void onProgressChanged(SeekBar seekBar, int progress, boolean b) wzywam Rect thumbRect = seekBar.getThumb().getBounds(); aby określić, gdzie znajduje się kciuk.

Działa to doskonale, ale widocznie getThumb() jest dostępny tylko na poziomie API 16+ (Android 4.1), powodując NoSuchMethodError w starszych wersjach.

Każdy pomysł, jak obejść ten problem?

Odpowiedz

28

byłem w stanie wykorzystać moje własne klasy, aby uzyskać zasada:

MySeekBar.java

package mobi.sherif.seekbarthumbposition; 

import android.content.Context; 
import android.graphics.drawable.Drawable; 
import android.util.AttributeSet; 
import android.widget.SeekBar; 

public class MySeekBar extends SeekBar { 

    public MySeekBar(Context context) { 
     super(context); 
    } 
    public MySeekBar(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 
    public MySeekBar(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
    } 

    Drawable mThumb; 
    @Override 
    public void setThumb(Drawable thumb) { 
     super.setThumb(thumb); 
     mThumb = thumb; 
    } 
    public Drawable getSeekBarThumb() { 
     return mThumb; 
    } 

} 

w działalności tego działa perfekcyjnie:

package mobi.sherif.seekbarthumbposition; 

import android.app.Activity; 
import android.graphics.Rect; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.SeekBar; 
import android.widget.SeekBar.OnSeekBarChangeListener; 

public class MainActivity extends Activity implements OnSeekBarChangeListener { 
    MySeekBar mSeekBar; 
    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     mSeekBar = (MySeekBar) findViewById(R.id.seekbar); 
     mSeekBar.setOnSeekBarChangeListener(this); 
    } 
    @Override 
    public void onProgressChanged(SeekBar seekBar, int progress, boolean b) { 
     Rect thumbRect = mSeekBar.getSeekBarThumb().getBounds(); 
     Log.v("sherif", "(" + thumbRect.left + ", " + thumbRect.top + ", " + thumbRect.right + ", " + thumbRect.bottom + ")"); 
    } 
    @Override 
    public void onStartTrackingTouch(SeekBar seekBar) { 
     // TODO Auto-generated method stub 

    } 
    @Override 
    public void onStopTrackingTouch(SeekBar seekBar) { 
     // TODO Auto-generated method stub 

    } 
} 
+1

Działa idealnie, dzięki! (muszę poczekać 20 h, aby wysłać ci nagrodę) – Henrique

+1

Poczekaj 7 dni na wypadek, gdyby ktoś dał lepszą odpowiedź. Chociaż nienawidzę używać refleksji, ale można się było narysować za pomocą refleksji. Daj szansę na opublikowanie większej liczby odpowiedzi. –

0

wspaniałego rozwiązania ! Dzięki. To tylko nessesary dodać, że w użyciu niestandardowych SeekBar trzeba zmodyfikować xml

<com.example.MySeekBar 
     android:id="@+id/..." 
     android:layout_width="0dp" 
     android:layout_height="wrap_content" 
     android:layout_gravity="center_vertical" 
     android:layout_weight="1" 
     android:minHeight="3dp" 
     android:maxHeight="3dp" 
     android:progressDrawable="@drawable/seek_bar_2" 
     android:thumb="@drawable/thumbler_seekbart_circle" 
     android:thumbOffset="8dp" /> 

android: thumbOffset = „8dp” - to połowa kciuka Lepiej spesify, a tym samym nie będzie niedopasowanie z centrum tekst i kciuk

Pozycjonowanie może wyglądać następująco:

int possition = (int) (seekBar.getX() //the beginning of the seekbar 
+ seekBar.getThumbOffset()/2  //the half of our thumb - the text to be above it's centre 
+ ((MySeekBar) seekBar).getSeekBarThumb().getBounds().exactCenterX()); //position of a thumb inside the seek bar 
0

Mam nadzieję, że może to zaoszczędzić kilka godzin dla kogoś innego!

I stworzył tę metodę zamiast niestandardowego SeekBar: Odpowiedź

public int getSeekBarThumbPosX(SeekBar seekBar) { 
    int posX; 
    if (Build.VERSION.SDK_INT >= 16) { 
     posX = seekBar.getThumb().getBounds().centerX(); 
    } else { 
     int left = seekBar.getLeft() + seekBar.getPaddingLeft(); 
     int right = seekBar.getRight() - seekBar.getPaddingRight(); 
     float width = (float) (seekBar.getProgress() * (right - left))/seekBar.getMax(); 
     posX = Math.round(width) + seekBar.getThumbOffset(); 
    } 
    return posX; 
} 
0

@Sherif elKhatib jest wielki, ale ma tę wadę, buforowanie kopię kciuka nawet na API> = 16. Ulepszyłem go tak, aby buforował tylko kciuk Drawable na API < = 15 i nadpisał metodę w SeekBar.java, aby uniknąć stosowania dwóch metod w API> = 16. Jedyny minus: wymaga docelowego pakietu SDK>> 16, co powinno mieć miejsce w większości aplikacji w dzisiejszych czasach.

public class ThumbSeekBar extends AppCompatSeekBar { 

    private Drawable thumb; 

    public ThumbSeekBar(Context context) { 
     super(context); 
    } 

    public ThumbSeekBar(Context context, AttributeSet attrs) { 
     super(context, attrs); 
    } 

    public ThumbSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { 
     super(context, attrs, defStyleAttr); 
    } 

    @Override 
    public Drawable getThumb() { 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { 
      return super.getThumb(); 
     } 
     return thumb; 
    } 

    @Override 
    public void setThumb(Drawable thumb) { 
     super.setThumb(thumb); 
     if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
      this.thumb = thumb; 
     } 
    } 
}