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

17

Я пытаюсь получить вертикальную стрелку, идущую с эмулятором, но я вроде застрял. Я могу заставить поисковую панель отображать то, как я ее хочу, и я могу добиться прогресса, чтобы сделать то, что хочу, и я могу изменить 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;
        }

}
    
задан Neil D 10.03.2009 в 17:54
источник
  • должен видеть stackoverflow.com/a/28397583/3496570 и stackoverflow.com/a/28397530/3496570 –  Nepster 08.02.2015 в 19:21

5 ответов

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 (ex API10) используйте: Ссылка или посмотрите это здесь

  

Вам также нужно обновить его высоту и amp; ширина, как предполагает Iftikhar

В порядке

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()
    );
}
    
ответ дан Nepster 08.02.2015 в 19:24
источник
  • таким образом, вы не можете изменить высоту и ширину прокрутки, после вращения они все те же. –  Iftikar Urrhman Khan 08.02.2017 в 21:03
17

Я создал решение, которое работает (по крайней мере, для меня, в любом случае) и создает вертикальный SeekBar. Ссылка

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

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.

    
ответ дан TechnIx 19.04.2012 в 12:45
источник
  • @Technlx, ​​вы используете это решение для виджета на главном экране? –  rxlky 04.08.2012 в 15:49
  • Это даст вам ошибку до тех пор, пока вы не будете использовать «setOnSeekBarChangeListener» в вашей соответствующей активности или классе java –  Umair Khalid 27.04.2017 в 09:28
11

вы можете скачать Ссылка , я надеюсь, что это может помочь вам

    
ответ дан pengwang 28.07.2010 в 05:21
источник
2

Взгляните на источник Android . Я думаю, вам нужно изменить хотя бы trackTouchEvent и, возможно, несколько других мест, где вам также нужно поменять координаты x, y, чтобы принять во внимание ваш поворот элемента управления.

    
ответ дан hacken 10.03.2009 в 19:50
источник
0

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

    
ответ дан Kyle Clegg 06.11.2011 в 03:03
источник