How to display divider value below seekbar in Andr

2019-06-06 17:14发布

问题:

I have added a seekbar to one of my activities. Its max value is 5. Now, I want to display the divider values (with increment 1, like 0, 1, 2, 3, 4 and 5) below my seekbar. How can I do that?

Is there any system method to achieve this which I am not able to put my hands on? Any inputs are welcomed.

NOTE : I want to apply any changes programatically, not from xml. The numbers should be separated at equal intervals. I could not edit it that precisely though.

回答1:

I am supposing you want to display view like below in picture.

if that is the case you have to create your own customSeekbar like give code.

CustomSeekBar.java

public class CustomSeekBar extends SeekBar {

private Paint textPaint;

private Rect textBounds = new Rect();

private String text = "";

public CustomSeekBar(Context context) {
    super(context);
    textPaint = new Paint();
    textPaint.setColor(Color.WHITE);

}

public CustomSeekBar(Context context, AttributeSet attrs) {
    super(context, attrs);
    textPaint = new Paint();
    textPaint.setTypeface(Typeface.SANS_SERIF);
    textPaint.setColor(Color.BLACK);

}

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


    textPaint = new Paint();
    textPaint.setColor(Color.BLACK);
}

@Override
protected synchronized void onDraw(Canvas canvas) {
    // First draw the regular progress bar, then custom draw our text
    super.onDraw(canvas);


    int progress = getProgress();
    text = progress + "";

    // Now get size of seek bar.
    float width = getWidth();
    float height = getHeight();

    // Set text size.
    textPaint.setTypeface(Typeface.create(Typeface.DEFAULT, Typeface.BOLD));
    textPaint.setTextSize(40);
    // Get size of text.
    textPaint.getTextBounds(text, 0, text.length(), textBounds);

    // Calculate where to start printing text.
    float position = (width / getMax()) * getProgress();

    // Get start and end points of where text will be printed.
    float textXStart = position - textBounds.centerX();
    float textXEnd = position + textBounds.centerX();

    // Check does not start drawing outside seek bar.
    if (textXStart <= 1) textXStart = 20;

    if (textXEnd > width) {
        textXStart -= (textXEnd - width + 30);
    }
    // Calculate y text print position.
    float yPosition = height;

    canvas.drawText(text, textXStart, yPosition, textPaint);
}

public synchronized void setTextColor(int color) {
    super.drawableStateChanged();
    textPaint.setColor(color);
    drawableStateChanged();
}


}

In your Xml file use your custom file like below

 <com.waleedsarwar.customseekbar.CustomSeekBar
    android:id="@+id/seekbar"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:max="5"
    android:paddingBottom="16dp" />


回答2:

This is another approach. I am extending a linearlayout. I put seekbar and another linearlayout(layout_5) which contains 6 textviews with 0-1-2-3-4-5. Better option would be creating a dynamic image(get width from seekBar) which has these numbers according to segment count.

I force seekbar's indicator to stop at specific points(6 points in your case). Instead of doing this, it is possible to set seekBar's maximum progress value to 5. It will work, but it will not give a good user experience.

public class SegmentedSeekBar extends LinearLayout {

    private int[] preDefinedValues;
    private int currentProgressIndex;
    private SeekBar seekBar;
    private int segmentCount = 5:

    public SegmentedSeekBar(Context context) {
        this(context, null, 0);
    }

    public SegmentedSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, android.R.attr.seekBarStyle);
    }

    public SegmentedSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        TypedArray a = context.getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.SegmentedSeekBar,
                0, 0);
        try {
           segmentCount =
           a.getInt(R.styleable.SegmentedSeekBar_segmentCount, -1);
        } finally {
           a.recycle();
        }
           init();
    }

    public void init() {
        //this values will be used when you need to set progress
        preDefinedValues = new int[segmentCount];
        for(int i = 0; i < preDefinedValues.length; i++) {
            preDefinedValues[i] = (100/(segmentCount-1)) * i;
        }
        //Get layout_5
        //which is linearlayout with 6 textviews  
        LayoutInflater inflater = (LayoutInflater) getContext()
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        View sliderView = inflater.inflate(
                getSliderId(segmentCount), null);
        //seekbar already inside the linearlayout
        seekBar = (SeekBar)sliderView.findViewById(R.id.seek_bar);
        //linear layout is vertically align 
        //so add your 6 textview linearlayout
        addView(sliderView);
        seekBar.setOnTouchListener(seekBarTouchListener);
    }

    private int getSliderId(int size) {
        return R.layout.layout_5;
    }

    //this method sets progress which is seen in UI not actual progress
    //It uses the conversion that we did in beginning
    public synchronized void setProgress(int progress) {
        if(preDefinedValues != null && progress < preDefinedValues.length && progress >= 0) {
            seekBar.setProgress(preDefinedValues[progress]);
            currentProgressIndex = progress;
        }
    }

    //this listener make sure the right progress is seen in ui
    //take action when user finish with changing progress
    SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            int index = 0;
            for(int i = 0; i < preDefinedValues.length; i++) {
                //try to find closest preDefinedvalues by comparing with latest value
                if(Math.abs(seekBar.getProgress() - preDefinedValues[i]) < Math.abs(seekBar.getProgress() - preDefinedValues[index])) {
                    index = i;
                }
            }
            setProgress(index);
        }
    };
}