简体   繁体   中英

SeekBar - Showing progress with TextView above

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);
}
}

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

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);
    }
   //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

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;

Use this , we are calculating the x position based on progress and setting it to textview

seekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
        override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {

               var xPosition=  (((seekBar1.right - seekBar1.left) / seekBar1.max) * seekBar1.progress ) + seekBar1.left
               textView1.translationX = xPosition.toFloat() - (textView1.width/2)
        }

        override fun onStartTrackingTouch(seekBar: SeekBar?) {
        }

        override fun onStopTrackingTouch(seekBar: SeekBar?) {
        }

    })

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM