web-dev-qa-db-ja.com

Androidでスライダー(SeekBar)を実装する

私はスライダーを実装したいと思います。スライダーは基本的に、垂直と水平の2本の線で、画面がタッチされている場所を横切ります。私は1つを作ることができましたが、問題があります:

  1. スライダーは非常に滑らかではなく、指を動かしているときにわずかな遅延があります
  2. 2つのスライダーを配置する場合、マルチタッチではなく、両方を同時に使用したいです。

コードは次のとおりです。

public class Slider extends View {

    private Controller controller = new Controller();
    private boolean initialisedSlider;
    private int sliderWidth, sliderHeight;
    private Point pointStart;
    private Paint white;
    private int mode;

    final static int VERTICAL = 0, HORIZONTAL = 1, BOTH = 2;

    public Slider(Context context) {
        super(context);
        setFocusable(true);    
        // TODO Auto-generated constructor stub
    }
    public Slider(Context context, AttributeSet attrs) {
        super(context, attrs);     
        setFocusable(true);    
        pointStart = new Point();
        initialisedSlider = false;   
        mode = Slider.BOTH;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if(!initialisedSlider) {
            initialisedSlider = true;
            sliderWidth = getMeasuredWidth();
            sliderHeight = getMeasuredHeight();

            pointStart.x = (int)(sliderWidth/2.0);
            pointStart.y = (int)(sliderHeight/2.0);
            controller = new Controller(pointStart, 3);

            white = new Paint();
            white.setColor(0xFFFFFFFF);
        }

        canvas.drawLine(controller.getCoordX(),0,
                        controller.getCoordX(),sliderHeight, 
                        white);
        canvas.drawLine(0, controller.getCoordY(), 
                        sliderWidth, controller.getCoordY(), 
                        white);

    }

    public boolean onTouchEvent(MotionEvent event) {
        int eventaction = event.getAction();     
        int X = (int)event.getX(); 
        int Y = (int)event.getY(); 
        switch (eventaction) { 
        case MotionEvent.ACTION_DOWN:
            if(isInBounds(X,Y)) {
                updateController(X, Y);
            }
            break;
        case MotionEvent.ACTION_MOVE:
            if(isInBounds(X,Y)) {
                updateController(X, Y);
            }
            break;
        case MotionEvent.ACTION_UP:
            if(isInBounds(X,Y)) {
                updateController(X, Y);
            }
            break;
        }
        invalidate();  
        return true; 
    }

    private boolean isInBounds(int x, int y) {
        return ((x<=(sliderWidth)) && (x>=(0)) 
                 && (y<=(sliderHeight)) && (y>=(0)));
    }
    private void updateController(int x, int y) {
        switch(mode) {
        case Slider.HORIZONTAL:
            controller.setCoordX(x);
            break;
        case Slider.VERTICAL:
            controller.setCoordY(y);
            break;
        case Slider.BOTH:
            controller.setCoordX(x);
            controller.setCoordY(y);
            break;
        }
    }

    private class Controller {
        private int coordX, coordY;
        Controller() {

        }
        Controller(Point point, int width) {
            setCoordX(point.x);
            setCoordY(point.y);
        }
        public void setCoordX(int coordX) {
            this.coordX = coordX;
        }
        public int getCoordX() {
            return coordX;
        }
        public void setCoordY(int coordY) {
            this.coordY = coordY;
        }
        public int getCoordY() {
            return coordY;
        }
    }
}

そして、XMLファイル:

<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:layout_width="fill_parent"
    Android:layout_height="fill_parent"
    Android:orientation="vertical" >

    <TextView
        Android:layout_width="fill_parent"
        Android:layout_height="wrap_content"
        Android:text="@string/hello" />
    <com.Android.lasttest.Slider 
        Android:id="@+id/slider"
        Android:layout_width="100dp" 
        Android:layout_height="100dp" 
        Android:layout_gravity="center_horizontal" 
        Android:adjustViewBounds="true"/>
    <com.Android.lasttest.Slider 
        Android:id="@+id/slider"
        Android:layout_width="150dp" 
        Android:layout_height="150dp" 
        Android:layout_gravity="center_horizontal" 
        Android:adjustViewBounds="true"/>
    <com.Android.lasttest.Slider 
        Android:id="@+id/slider"
        Android:layout_width="200dp" 
        Android:layout_height="200dp" 
        Android:layout_gravity="center_horizontal" 
        Android:adjustViewBounds="true"/>

</LinearLayout>
20

Androidは水平のスライダーを提供します

onSeekBarChangeListenerを実装します

垂直シークバーが必要な場合は、このリンクに従ってください

20
Amit Hooda

SeekBarを実装する方法

enter image description here

SeekBarをレイアウトに追加します

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

    <TextView
        Android:id="@+id/textView"
        Android:layout_margin="20dp"
        Android:layout_width="wrap_content"
        Android:layout_height="wrap_content"/>

    <SeekBar
        Android:id="@+id/seekBar"
        Android:max="100"
        Android:progress="50"
        Android:layout_width="match_parent"
        Android:layout_height="wrap_content"/>

</LinearLayout>

ノート

  • maxは、シークバーが移動できる最高値です。デフォルトは100です。最小は0です。 xml min値はAPI 26からのみ利用できますが、プログラムで0-100範囲を以前のバージョンに必要なものに変換することができます。
  • progressは、スライダードットの初期位置です(「サム」と呼ばれます)。
  • 垂直SeekBarの場合は、Android:rotation="270"を使用します。

コードの変更をリッスンする

public class MainActivity extends AppCompatActivity {

    TextView tvProgressLabel;

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

        // set a change listener on the SeekBar
        SeekBar seekBar = findViewById(R.id.seekBar);
        seekBar.setOnSeekBarChangeListener(seekBarChangeListener);

        int progress = seekBar.getProgress();
        tvProgressLabel = findViewById(R.id.textView);
        tvProgressLabel.setText("Progress: " + progress);
    }

    SeekBar.OnSeekBarChangeListener seekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            // updated continuously as the user slides the thumb
            tvProgressLabel.setText("Progress: " + progress);
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            // called when the user first touches the SeekBar
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            // called after the user finishes moving the SeekBar
        }
    };
}

ノート

  • ユーザーがシークバーを移動している間に更新を行う必要がない場合は、onStopTrackingTouchのUIを更新するだけです。

こちらもご覧ください

16
Suragch