12

SeekBarAndroid アプリでを使用しています。ユーザーが の任意の場所を 1 回タップするSeekBarと、進行状況の値が変更されます。ユーザーがSeekBar親指をスライドさせたときにのみ進行状況の値を変更したい( UISlideriOSのように)。

clickableのプロパティを false に設定しようとしSeekBarましたが、うまくいきませんでした。どうすれば望ましい動作を実現できますか?

4

13 に答える 13

10

今週同じ問題に直面し、カスタム SeekBar を使用して解決しました: 次のコード:

public class Slider extends SeekBar {

private Drawable mThumb;

public Slider(Context context) {
    super(context);

}

public Slider(Context context, AttributeSet attrs) {
    super(context, attrs);

}

@Override
public void setThumb(Drawable thumb) {
    super.setThumb(thumb);
    mThumb = thumb;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    if (event.getAction() == MotionEvent.ACTION_DOWN) {

        if (event.getX() >= mThumb.getBounds().left
                && event.getX() <= mThumb.getBounds().right
                && event.getY() <= mThumb.getBounds().bottom
                && event.getY() >= mThumb.getBounds().top) {

            super.onTouchEvent(event);
        } else {
            return false;
        }
    } else if (event.getAction() == MotionEvent.ACTION_UP) {
        return false;
    } else {
        super.onTouchEvent(event);
    }

    return true;
}}

お役に立てれば

于 2013-06-07T21:07:48.100 に答える
8

この他のスレッドをチェックしてください:

ユーザーはシークバーと対話できません

以下を試してみましたが、うまくいきます。私のシークバーには、次のように android:max プロパティが 100 に設定されていることに注意してください。


<SeekBar
android:id="@+id/EnableBar"
android:layout_span="2"
android:max="100"
/>

package com.androidbook.hiworld;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.SeekBar;


public class HiWorldActivity extends Activity {
    int originalProgress;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        SeekBar seek = (SeekBar)findViewById(R.id.EnableBar);

        seek.setOnSeekBarChangeListener(
        new SeekBar.OnSeekBarChangeListener() {
           public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
               ((TextView)findViewById(R.id.SeekTxt)).setText("Value: "+progress);
               if(fromTouch == true){
                  // only allow changes by 1 up or down
                  if ((progress > (originalProgress+24))
                       || (progress < (originalProgress-24))) {
                     seekBar.setProgress( originalProgress);
                  } else {
                      originalProgress = progress;
                  }
               } 
           }

           @Override
           public void onStopTrackingTouch(SeekBar seekBar) {
               //Nothing here..                
           }

           @Override
           public void onStartTrackingTouch(SeekBar seekBar) {
               originalProgress = seekBar.getProgress();
           }
        });
    }
}
于 2011-08-01T22:01:38.197 に答える
1

私はこれに対する解決策を思いつきました、それはあまりきれいではありません、しかしそれはトリックをするべきです...

アイデアは次のとおりです。

  1. サムボタンを除くすべてのスライダーを覆う非表示のオーバーレイを作成します

    (オーバーレイとして機能するために、黒く塗りつぶされたシークバーを使用しました)

  2. 親指を押したら、スライダーの「bringToFront」メソッドを呼び出します

  3. 親指を離したら、非表示のオーバーレイで「bringToFront」メソッドを呼び出します

これが機能するためには、親指ボタン以外のすべてをカバーするようにオーバーレイのサイズを変更する必要があることに注意してください(2つのオーバーレイ[親指ボタンの両側に1つずつ]を使用することをお勧めします)

サムボタンを離すと、オーバーレイのサイズを変更する必要があります

...私が言ったように、それはきれいではありません。それを行うにはもっと良い方法があると確信していますが、もしあなたがそれをしなければならないのなら、私はこれを試してみます。

   yourBarChangeListener yourBarChangeListener = new SeekBar.OnSeekBarChangeListener() { 

    @Override 
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
     } 

    @Override 
    public void onStartTrackingTouch(SeekBar seekBar) {
     // YOUR CODE HERE 
    } 
    @Override 
    public void onStopTrackingTouch(SeekBar seekBar) { 
    } 
}; 
yourBar.setOnSeekBarChangeListener(yourBarChangeListener);
于 2011-04-22T19:08:15.920 に答える
1

これは、SeekBar 内のイベント リスナーと完全に連携します。

PS。このコードを Slim から改良して、より一般化しました。

/**
 * ProtectedSeekBar
 * 01/27/15
 */
public class ProtectedSeekBar extends SeekBar {

    private Drawable mThumb;

    public ProtectedSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ProtectedSeekBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ProtectedSeekBar(Context context) {
        super(context);
    }

    @Override
    public void setThumb(Drawable thumb) {
        super.setThumb(thumb);
        mThumb = thumb;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            if( event.getX() < mThumb.getBounds().left ||
                event.getX() > mThumb.getBounds().right ||
                event.getY() > mThumb.getBounds().bottom ||
                event.getY() < mThumb.getBounds().top) {
                return false;
            }
        }
        return super.onTouchEvent(event);
    }
}
于 2015-01-27T15:31:01.543 に答える
0
    int oldProgress;
    boolean isOn = true;
    vSeek.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            oldProgress = seekBar.getProgress();
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (oldProgress == seekBar.getProgress()) {
                if (isOn) {
                    seekBar.setThumb(getResources().getDrawable(R.drawable.blck_btn));
                    isOn = false;
                } else {
                    seekBar.setThumb(getResources().getDrawable(R.drawable.blck_btn_selected));
                    isOn = true;
                }
            }
        }

追跡を停止したときの進行状況を比較できます。

于 2013-02-26T18:24:32.203 に答える
0

@lordmegamax コードを見て、うまくいかないものを見つけました。

  1. int oldProgress は onCreate 内にとどまることはできません。外部で宣言する必要があります。
  2. seekBar を常に最初から開始すると、onStartTrackingTouch は常に 0 を返すため、onStopTrackingTouch は機能しません。

少し考えてみると、解決策が見つかりました。

//SeekBar Slide
    skbLogin.setOnSeekBarChangeListener(new OnSeekBarChangeListener() {
        //Force Slide From Beginning
        public void onStartTrackingTouch(SeekBar seekBar) { continuosProgress = false; }
        //Execute when reach the max
        public void onStopTrackingTouch(SeekBar seekBar) {
            if(continuosProgress)
                if(seekBar.getProgress() == 100) btnLogin();
                else skbRollBack();
            else
                seekBar.setProgress(0);
        }
        //Check Slide from Beginning
        public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
            if(progress < 10) continuosProgress = true;
        }
    });

それが役に立てば幸い。よろしくお願いします

PS: 初めての投稿です、間違っていたらごめんなさい。

于 2013-04-26T17:52:31.270 に答える
0
private class UpdateListener implements OnSeekBarChangeListener {

    // max step user can change at once
    private static final int THUMB_MAX_MOVE = 5;

    // current seekbar value (50 is initial seekbar value as defined in xml)
    private int currentProgress = 50;

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {

        // save current value before user jumps around
        currentProgress = seekBar.getProgress();
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {}

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

        // check if we've jumped too far
        if (Math.abs(currentProgress - progress) > THUMB_MAX_MOVE) {

            // if so, revert to last progress and return
            seekBar.setProgress(currentProgress);
            return;
        }

        // if not, move was valid and update current progress
        currentProgress = progress;

        // do anything more here
    }
}
于 2016-05-17T05:19:50.570 に答える
0

私が直面していた状況は、SeekBar が別のコードによって作成されたため、onTouchEvent() ハンドラーを使用してサブクラスを作成できなかったことです。代わりに、いじりたいインスタンスの OnTouchListener をオーバーライドしました...

SeekBar sb = (SeekBar) findViewById(R.id.seekbar);

sb.setOnTouchListener(new OnTouchListener()
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        Drawable thumb = ((SeekBar) v).getThumb();

        if (   event.getX() < thumb.getBounds().left
            || event.getX() > thumb.getBounds().right
            || event.getY() < thumb.getBounds().top
            || event.getY() > thumb.getBounds().bottom) {
            // event occurred outside the thumb slider so ignore it
            return true;
        } else {
            // event occurred inside the thumb slider so pass it on
            return false;
        }
    }
});

はい、単純に「if」式の内容を返すことはできますが、それではコードを読みやすくすることはできません。

于 2018-11-21T15:10:31.720 に答える