Modifying the Android seekbar widget to operate vertically

前端 未结 5 829
温柔的废话
温柔的废话 2020-11-28 07:43

I\'m trying to get a vertical seekbar going with the emulator, but I\'m sort of stuck. I can get the seekbar to display the way I want it to, and I can get the progress to

相关标签:
5条回答
  • 2020-11-28 08:04

    Could you leave the seekbar as horizontal, put it in a frame layout, then rotate the layout 90 degrees in the java? sounds doable...

    0 讨论(0)
  • 2020-11-28 08:11

    Take a look at android source . I think you need to change at least trackTouchEvent and there maybe a few other places where you also need to swap the x,y coordinates to take into account your rotation of the control.

    0 讨论(0)
  • 2020-11-28 08:14

    I've created a solution which works (at least for me, anyway) and creates a vertical SeekBar. http://hackskrieg.wordpress.com/2012/04/20/working-vertical-seekbar-for-android/

    This code will correctly select/deselect the thumb, move correctly, update the listener correctly (only when the progress changes!), update/draw the progress correctly, etc. I hope it helps you.

    public class VerticalSeekBar extends SeekBar {
    
    public VerticalSeekBar(Context context) {
        super(context);
    }
    
    public VerticalSeekBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    public VerticalSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
    }
    
    @Override
    protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }
    
    protected void onDraw(Canvas c) {
        c.rotate(-90);
        c.translate(-getHeight(), 0);
    
        super.onDraw(c);
    }
    
    private OnSeekBarChangeListener onChangeListener;
    @Override
    public void setOnSeekBarChangeListener(OnSeekBarChangeListener onChangeListener){
        this.onChangeListener = onChangeListener;
    }
    
    private int lastProgress = 0;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }
    
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            onChangeListener.onStartTrackingTouch(this);
            setPressed(true);
            setSelected(true);
            break;
        case MotionEvent.ACTION_MOVE:
            // Calling the super seems to help fix drawing problems
            super.onTouchEvent(event);
            int progress = getMax() - (int) (getMax() * event.getY() / getHeight());
    
            // Ensure progress stays within boundaries of the seekbar
            if(progress < 0) {progress = 0;}
            if(progress > getMax()) {progress = getMax();}
    
            // Draw progress
            setProgress(progress);
    
            // Only enact listener if the progress has actually changed
            // Otherwise the listener gets called ~5 times per change
            if(progress != lastProgress) {
                lastProgress = progress;
                onChangeListener.onProgressChanged(this, progress, true);
            }
    
            onSizeChanged(getWidth(), getHeight() , 0, 0);
            onChangeListener.onProgressChanged(this, getMax() - (int) (getMax() * event.getY() / getHeight()), true);
            setPressed(true);
            setSelected(true);
            break;
        case MotionEvent.ACTION_UP:
            onChangeListener.onStopTrackingTouch(this);
            setPressed(false);
            setSelected(false);
            break;
        case MotionEvent.ACTION_CANCEL:
            super.onTouchEvent(event);
            setPressed(false);
            setSelected(false);
            break;
        }
        return true;
    }
    
    public synchronized void setProgressAndThumb(int progress) {
        setProgress(getMax() - (getMax()- progress));
        onSizeChanged(getWidth(), getHeight() , 0, 0);
    }
    
    public synchronized void setMaximum(int maximum) {
        setMax(maximum);
    }
    
    public synchronized int getMaximum() {
        return getMax();
    }
    }
    

    I just placed this vertical SeekBar inside a LinearLayout with layout_height set to FILL_PARENT and layout_width set to WRAP_CONTENT.

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="fill_parent"
        android:orientation="vertical" >
    
        <com.safetyculture.jsadroidtablet.VerticalSeekBar
            android:id="@+id/calculatorVerticalSeekBar"
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:layout_gravity="bottom"
            android:max="4"
            android:progress="2" />
    
    </LinearLayout>
    

    NOTE: You must set an OnSeekBarChangeListener, otherwise interacting with the SeekBar will produce NullPointerException.

    0 讨论(0)
  • 2020-11-28 08:20

    you can download at http://560b.sakura.ne.jp/android/VerticalSlidebarExample.zip, i hope this may can help you

    0 讨论(0)
  • 2020-11-28 08:29

    For API 11 and later, can use seekbar's XML attributes(android:rotation="270") for vertical effect.

    <SeekBar
    android:id="@+id/seekBar1"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:rotation="270"/>
    

    For older API level (ex API10),use: https://github.com/AndroSelva/Vertical-SeekBar-Android or see this sample here

    You also have to update it's height & width as suggest by Iftikhar

    In order

    seekBar.setLayoutParams(
                    new ViewGroup.LayoutParams(convertDpToPixels(1.0f,mContext), ViewGroup.LayoutParams.WRAP_CONTENT));
    

    //haven't tested..

    where

    public static int convertDpToPixels(float dp, Context context){
        Resources resources = context.getResources();
        return (int) TypedValue.applyDimension(
                TypedValue.COMPLEX_UNIT_DIP,
                dp, 
                resources.getDisplayMetrics()
        );
    }
    
    0 讨论(0)
提交回复
热议问题