Изменение андроид SeekBar виджета для работы по вертикали

голоса
17

Я пытаюсь получить вертикальную SeekBar происходит с эмулятором, но я вроде застряли. Я могу получить SeekBar, чтобы отобразить, как я хочу, чтобы он, и я могу получить прогресс делать то, что я хочу, и я могу модифицировать onTouchEvent, чтобы получить большой палец, чтобы идти вертикально, а не горизонтально. То, что я не могу сделать, это получить большой палец, чтобы выходить за пределы по умолчанию 29 пикселей по горизонтали на без использования setThumbOffset (). Это само по себе не является проблемой. Проблема исходит из того, что я не понимаю thumbOffset вообще - я думаю. Я думаю, что я мог бы (должным образом) изменить размер виджета, который я уверен, что я не делаю правильно. Или, может быть, я мог бы просто использовать thumbOffset, если бы я мог понять это. Так как я могу вычислить прогресс правильно, я думал, я бы просто использовать линейную функцию прогресса * (getTop () - getBottom ()) виджета, но это не похоже, чтобы сделать это. Но я не могу понять, что смещение вокруг.

Как-то в стороне, я действительно уверен, если то, что я делаю в onSizeChanged () нормально или если он собирается укусить меня в заднице позже.

Вот макет main.xml:

<?xml version=1.0 encoding=utf-8?>
<LinearLayout xmlns:android=http://schemas.android.com/apk/res/android
    android:orientation=vertical
    android:layout_width=fill_parent
    android:layout_height=fill_parent >

    <com.mobilsemantic.mobipoll.SlideBar
        android:id=@+id/slide
        android:layout_width=wrap_content
        android:layout_height=fill_parent
        android:max=100
        android:progress=0
        android:secondaryProgress=25 />

        <Button android:id=@+id/button
            android:layout_width=fill_parent
            android:layout_height=fill_parent
            android:text=Hello, I am a Button />

    <TextView android:id=@+id/tracking
        android:layout_width=fill_parent
        android:layout_height=wrap_content />

</LinearLayout>

А класс (игнорировать отладочный мусор):

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.SeekBar;

public class SlideBar extends SeekBar {

        private int oHeight = 320, oWidth = 29;
        private int oProgress = -1, oOffset = -1;;
        private float xPos = -1, yPos = -1;
        private int top = -1, bottom = -1, left = -1, right = -1;

        public SlideBar(Context context) {
                super(context);
        }
        public SlideBar(Context context, AttributeSet attrs)
        {
                super(context, attrs);
                oOffset = this.getThumbOffset();
                oProgress = this.getProgress();
        }
        public SlideBar(Context context, AttributeSet attrs, int defStyle)
        {
                super(context, attrs, defStyle);
        }

        protected synchronized void onMeasure(int widthMeasureSpec, intheightMeasureSpec)
        {
                int height = View.MeasureSpec.getSize(heightMeasureSpec);
                oHeight = height;
                this.setMeasuredDimension(oWidth, oHeight);

        }
        protected void onSizeChanged(int w, int h, int oldw, int oldh)
        {
                super.onSizeChanged(h, w, oldw, oldh);
        }
        protected void onLayout(boolean changed, int l, int t, int r, int b)
        {
                super.onLayout(changed, l, t, r, b);
                left = l;
                right = r;
                top = t;
                bottom = b;
        }
        protected void onDraw(Canvas c)
        {
                c.rotate(90);
                c.translate(0,-29);
                super.onDraw(c);
        }
        public boolean onTouchEvent(MotionEvent event)
        {
                xPos = event.getX();
                yPos = event.getY();
                float progress = (yPos-this.getTop())/(this.getBottom()-this.getTop());
                oOffset = this.getThumbOffset();
                oProgress = this.getProgress();
                Log.d(offset + System.nanoTime(), new Integer(oOffset).toString());
                Log.d(progress + System.nanoTime(), new Integer(oProgress).toString());

                float offset;

                offset = progress * (this.getBottom()-this.getTop());

                this.setThumbOffset((int)offset);

                Log.d(offset_postsetprogress + System.nanoTime(), new Integer(oOffset).toString());
                Log.d(progress_postsetprogress + System.nanoTime(), new Integer(oProgress).toString());

                this.setProgress((int)(100*event.getY()/this.getBottom()));
                return true;
        }

}
Задан 10/03/2009 в 17:54
источник пользователем
На других языках...                            


5 ответов

голоса
17

Я создал решение , которое работает (по крайней мере , для меня, во всяком случае) и создает вертикальную SeekBar. http://hackskrieg.wordpress.com/2012/04/20/working-vertical-seekbar-for-android/

Этот код будет правильно выбрать / отменить выбор пальца, перемещать, обновите слушатель правильно (только тогда, когда изменения прогресса!), Обновление / сделать ход правильно, и т.д. Я надеюсь, что это поможет вам.

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

Я просто поместил этот вертикальный SeekBar внутри LinearLayout с layout_height набора к FILL_PARENT и layout_width установлен в 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>

Примечание: Вы должны установить OnSeekBarChangeListener, иначе взаимодействуя с SeekBar будет производить NullPointerException.

Ответил 19/04/2012 в 11:45
источник пользователем

голоса
11

Вы можете скачать на http://560b.sakura.ne.jp/android/VerticalSlidebarExample.zip , я надеюсь , что это может может помочь вам

Ответил 28/07/2010 в 04:21
источник пользователем

голоса
9

Для API 11 and laterмогут использовать seekbar's XMLатрибуты (android:rotation="270")для вертикального эффекта.

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

Для старшего уровня API (бывший API10), используйте: https://github.com/AndroSelva/Vertical-SeekBar-Android или увидеть этот образец здесь

Вы также должны обновить его высота и ширина, как предполагают, по Ифтихар

В порядке

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

// не тестировал ..

где

public static int convertDpToPixels(float dp, Context context){
    Resources resources = context.getResources();
    return (int) TypedValue.applyDimension(
            TypedValue.COMPLEX_UNIT_DIP,
            dp, 
            resources.getDisplayMetrics()
    );
}
Ответил 08/02/2015 в 18:24
источник пользователем

голоса
2

Посмотрите на андроид источника . Я думаю , что нужно изменить , по крайней мере , trackTouchEvent и там , возможно, несколько других мест , где вы должны поменять местами х, у координаты , чтобы принять во внимание ваше вращение управления.

Ответил 10/03/2009 в 19:50
источник пользователем

голоса
0

Не могли бы вы оставить SeekBar как по горизонтали, положить его в макете кадра, а затем повернуть на 90 градусов макета в Java? звуки выполнимо ...

Ответил 06/11/2011 в 03:03
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more