Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to set ToolTip Text in android custom seekbar?

I have a custom seekbar with drawable and it is working fine, i am trying to make tooltip text on user action over the seekbar, is there any way without using third party library, i have posted the code below which i am using for custom seekbar

i have also attached a sample progress tooltip that i would like to achieve below

any reference or solution would be appreciated

This is how i need my seekbar to look like

implementation "com.android.support:appcompat-v7:${android_support_version}"

seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progressValue, boolean fromUser) {
                seekBar.setThumb(getThumb(progressValue));
                TooltipCompat.setTooltipText(seekBar, String.valueOf(progressValue));
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                //Do nothing
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //Do nothing
            }
        });

 private Drawable getThumb(int progress) {
        View thumbView = LayoutInflater.from(getActivity()).inflate(R.layout.seekbar_tv, null, false);
        ((TextView) thumbView.findViewById(R.id.tvProgress)).setText(progress + "");
        thumbView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        Bitmap bitmap = Bitmap.createBitmap(thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        thumbView.layout(0, 0, thumbView.getMeasuredWidth(), thumbView.getMeasuredHeight());
        thumbView.draw(canvas);
        return new BitmapDrawable(getResources(), bitmap);
    }

<!--mySeekBarInLayout-->

<SeekBar
android:id="@+id/seekBar_Experience"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="10"
android:progressDrawable="@drawable/survey_seekbar_style"
android:splitTrack="false"
android:thumb="@drawable/survey_seekbar_thum" />

<!--survey_seekbar_thum-->

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="oval">
            <solid android:color="@color/circle_yellow"/>
            <size
                android:width="30dp"
                android:height="30dp"/>
        </shape>
    </item>
</layer-list>

<!--survey_seekbar_style-->

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@android:id/background"
        android:drawable="@drawable/survey_border_shadow"
        android:height="1dp"
        android:gravity="center">
    </item>

    <item
        android:id="@android:id/progress"
        android:height="4dp"
        android:gravity="center">
        <clip android:drawable="@drawable/survey_seekbar_progress" />
    </item>
</layer-list>

<!--survey_border_shadow-->

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <gradient
                android:endColor="@color/thr_dark_blue"
                android:startColor="@color/thr_dark_blue" />
        </shape>
    </item>
</layer-list>


<!--survey_seekbar_progress-->

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:id="@+id/progressshape" >
        <clip>
            <shape
                android:shape="rectangle" >
                <size android:height="3dp"/>
                <corners
                    android:radius="5dp" />
                <solid android:color="@color/thr_dark_blue"/>
            </shape>
        </clip>
    </item>
</layer-list>
like image 318
Gopi.cs Avatar asked Jul 17 '19 06:07

Gopi.cs


2 Answers

You should have your customized textview and change the text inside onProgressChanged.

Is that enough? ==> No

You need to change the x coordinate of the textview to change it's place to be compatible with seekbar place.

Code demonstrate that:

@Override
public void onProgressChanged(SeekBar seekBar, int progress,
        boolean fromUser) {

    yourTextView.setText(progress + " miles");
    // Get the thumb bound and get its left value
    int x = seekBar.getThumb().getBounds().left;
    // set the left value to textview x value
    yourTextView.setX(x);
}
like image 118
Ibrahim Ali Avatar answered Oct 27 '22 00:10

Ibrahim Ali


You can do the following:

1) MainActivity.class:

public class MainActivity extends AppCompatActivity {

private static final String TAG = MainActivity.class.getSimpleName();
private SeekBar sb;
private RelativeLayout rlMarker;

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

    sb = (SeekBar) findViewById(R.id.sb);
    rlMarker = (RelativeLayout) findViewById(R.id.rlMarker);

    sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            updateMarker(sb, rlMarker, (i + " miles"));
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            rlMarker.setVisibility(View.VISIBLE);
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            rlMarker.setVisibility(View.GONE);
        }
    });


    //initialize
    updateMarker(sb, rlMarker, "0 miles");

}



private void updateMarker(final SeekBar sb,
                           View rlMarker,
                           String message) {

    final TextView tvProgress = (TextView) rlMarker.findViewById(R.id.tvProgress);
    final View vArrow = (View) rlMarker.findViewById(R.id.vArrow);
    /**
     * According to this question:
     * https://stackoverflow.com/questions/20493577/android-seekbar-thumb-position-in-pixel
     * one can find the SeekBar thumb location in pixels using:
     */
    int width = sb.getWidth()
            - sb.getPaddingLeft()
            - sb.getPaddingRight();
    final int thumbPos = sb.getPaddingLeft()
            + width
            * sb.getProgress()
            / sb.getMax() +
            //take into consideration the margin added (in this case it is 10dp)
            Math.round(convertDpToPixel(10, MainActivity.this));

    tvProgress.setText(message);

    tvProgress.post(new Runnable() {
        @Override
        public void run() {

            final Display display = ((WindowManager) MainActivity.this.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
            final Point deviceDisplay = new Point();
            display.getSize(deviceDisplay);

            //vArrow always follow seekBar thumb location
            vArrow.setX(thumbPos - sb.getThumbOffset());

            //unlike vArrow, tvProgress will not always follow seekBar thumb location
            if ((thumbPos - tvProgress.getWidth() / 2 - sb.getPaddingLeft()) < 0) {
                //part of the tvProgress is to the left of 0 bound
                tvProgress.setX(vArrow.getX() - 20);
            } else if ((thumbPos + tvProgress.getWidth() / 2 + sb.getPaddingRight()) > deviceDisplay.x) {
                //part of the tvProgress is to the right of screen width bound
                tvProgress.setX(vArrow.getX() - tvProgress.getWidth() + 20 + vArrow.getWidth());
            } else {
                //tvProgress is between 0 and screen width bounds
                tvProgress.setX(thumbPos - tvProgress.getWidth() / 2f);
            }
        }
    });
}

/**
 * According to this question:
 * https://stackoverflow.com/questions/4605527/converting-pixels-to-dp
 * one can convert dp to pixels using the following method:
 */
public static float convertDpToPixel(float dp, Context context) {
    Resources resources = context.getResources();
    DisplayMetrics metrics = resources.getDisplayMetrics();
    float px = dp * ((float) metrics.densityDpi / DisplayMetrics.DENSITY_DEFAULT);
    return px;
}
}

2) activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimaryDark"
    android:textSize="40sp"
    android:layout_alignParentTop="true"
    android:gravity="center"
    android:text="Top"
    android:layout_above="@id/v"
    android:textColor="@android:color/white"/>

<include
    layout="@layout/marker"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:visibility="gone"
    android:layout_above="@id/v">
</include>

<View
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_above="@id/sb"
    android:id="@+id/v">
</View>

<SeekBar
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/sb"
    android:layout_centerInParent="true"
    android:layout_marginRight="10dp"
    android:layout_marginEnd="10dp"
    android:layout_marginStart="10dp"
    android:layout_marginLeft="10dp"
    android:max="100"/>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/colorPrimary"
    android:textSize="40sp"
    android:gravity="center"
    android:text="Bottom"
    android:layout_below="@id/sb"
    android:layout_alignParentBottom="true"
    android:textColor="@android:color/white"/>

</RelativeLayout>

3) marker.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/transparent"
android:id="@+id/rlMarker">

<TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/tvProgress"
    android:gravity="center"
    android:padding="10dp"
    android:textColor="@android:color/white"
    android:background="@drawable/marker_shape"
    android:text="0 miles"/>

<View
    android:layout_width="20dp"
    android:layout_height="20dp"
    android:id="@+id/vArrow"
    android:gravity="center"
    android:rotation="180"
    android:layout_below="@id/tvProgress"
    android:background="@drawable/marker_arrow_shape"/>

</RelativeLayout>

4) marker_shape.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item>
    <rotate
        android:fromDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%">
        <shape>
            <solid
                android:shape="rectangle"
                android:color="@color/colorAccent" />
            <corners
                android:bottomLeftRadius="5dp"
                android:bottomRightRadius="5dp"
                android:topLeftRadius="5dp"
                android:topRightRadius="5dp"/>
        </shape>
    </rotate>
</item>

</layer-list>

5) marker_arrow_shape.xml:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

<item>
    <rotate
        android:fromDegrees="45"
        android:toDegrees="45"
        android:pivotX="-40%"
        android:pivotY="87%">
        <shape>
            <solid
                android:shape="rectangle"
                android:color="@color/colorAccent" />
        </shape>
    </rotate>
</item>

</layer-list>

6) Result:

enter image description here

like image 32
Brainnovo Avatar answered Oct 26 '22 23:10

Brainnovo