SeekBar - Showing progress with TextView above

2019-07-07 01:48发布

问题:

I'm trying the (surely simple?) task of having a TextView follow the thumb on a progress bar and show the progress in the TextView.

The problem is that for progress values of less than half max, the TextView drifts to the left of the thumb, getting more and more left of the correct place and vice versa with progress values more than half max the TextView drifts more and more to the right.

Below is a version of code that reproduces the problem...

Layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical" 
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".Seekbar_test" >

<SeekBar
    android:id="@+id/seekBar1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:max="59"
    android:layout_marginTop="24dp" />

<TextView
    android:id="@+id/textView1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:textAppearance="?android:attr/textAppearanceLarge" />

And .java

package com.example.seekbar_test;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;

public class Seekbar_test extends Activity {
SeekBar fade_seek;
TextView fade_text;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_seekbar_test);

    fade_seek = (SeekBar) findViewById(R.id.seekBar1);
    fade_text = (TextView) findViewById(R.id.textView1);

    fade_seek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {       
        @Override       
        public void onStopTrackingTouch(SeekBar seekBar) {            
        }       
        @Override       
        public void onStartTrackingTouch(SeekBar seekBar) {     
        }       
        @Override       
        public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {
            say_minutes_left(progress);
        }
    });
}

private void say_minutes_left(int how_many)
{
    String what_to_say = String.valueOf(how_many);
    fade_text.setText(what_to_say);

    int seek_label_pos = (int)((float)(fade_seek.getMeasuredWidth()) * ((float)how_many / 60f));
    fade_text.setX(seek_label_pos);
}
}

回答1:

This works for me:

private void say_minutes_left(int how_many)
{
    String what_to_say = String.valueOf(how_many);
    fade_text.setText(what_to_say);
    int seek_label_pos = (((fade_seek.getRight() - fade_seek.getLeft()) * fade_seek.getProgress()) / fade_seek.getMax()) + fade_seek.getLeft();
    if (how_many <=9)
        {
            fade_text.setX(seek_label_pos - 6);
        }
    else
        {
            fade_text.setX(seek_label_pos - 11);
        }
}

Thanks to Pushpendra Kuntal & flightplanner @ unable to get right position of texBox in Thumb of seekbar



回答2:

   //Get the thumb bound and get its left value
    int x = seekBar.getThumb().getBounds().left;
    //set the left value to textview x value
    textView.setX(x);

use this to move text view according to progress



回答3:

The following solution works for API >= 15:

  1. Override SeekBar to create the getThumb() method that is not available on api 15:

    public class CustomSeekBar extends SeekBar {
        private Drawable thumb;
        public CustomSeekBar(Context context) {
            super(context);
        }
    
        public CustomSeekBar(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
    
        public CustomSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        @Override
        public void setThumb(Drawable thumb) {
            super.setThumb(thumb);
            this.thumb = thumb;
        }
    
        @Override
        public Drawable getThumb() {
            return thumb;
        }
    }
    
  2. And use it Like this:

    correctX = customSeekBar.getThumb().getBounds().left;
    


回答4:

Works good with Ken Nichols code, but here is a better decision, for example, to center you TextView to current position in ProgressBar(SeekBar):

 private void say_minutes_left(int how_many)
{
    String what_to_say = String.valueOf(how_many);
    fade_text.setText(what_to_say);
    int seek_label_pos = (((fade_seek.getRight() - fade_seek.getLeft()) * fade_seek.getProgress()) / fade_seek.getMax()) + fade_seek.getLeft();
  fade_text.setX(seek_label_pos - fade_text.getWidth() / 2);
}

If you have padding in your ProgressBar(SeekBar), you can use more general version of this code:

 private void say_minutes_left(int how_many)
    {
        String what_to_say = String.valueOf(how_many);
        fade_text.setText(what_to_say);
        int left = fade_seek.getLeft() + fade_seek.getPaddingLeft();
        int right = fade_seek.getRight() - fade_seek.getPaddingRight();
        int seek_label_pos = (((right - left * fade_seek.getProgress()) / fade_seek.getMax()) + left;
      fade_text.setX(seek_label_pos - fade_text.getWidth() / 2);
    }


回答5:

TextView must be

 <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textAppearance="?android:attr/textAppearanceLarge"
        />

and remove it:

  int seek_label_pos = (int)((float)(fade_seek.getMeasuredWidth()) * ((float)how_many / 60f));
  fade_text.setX(seek_label_pos);

Hope it's help.