SeekBar
Android アプリでを使用しています。ユーザーが の任意の場所を 1 回タップするSeekBar
と、進行状況の値が変更されます。ユーザーがSeekBar
親指をスライドさせたときにのみ進行状況の値を変更したい( UISlider
iOSのように)。
clickable
のプロパティを false に設定しようとしSeekBar
ましたが、うまくいきませんでした。どうすれば望ましい動作を実現できますか?
SeekBar
Android アプリでを使用しています。ユーザーが の任意の場所を 1 回タップするSeekBar
と、進行状況の値が変更されます。ユーザーがSeekBar
親指をスライドさせたときにのみ進行状況の値を変更したい( UISlider
iOSのように)。
clickable
のプロパティを false に設定しようとしSeekBar
ましたが、うまくいきませんでした。どうすれば望ましい動作を実現できますか?
今週同じ問題に直面し、カスタム 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;
}}
お役に立てれば
この他のスレッドをチェックしてください:
以下を試してみましたが、うまくいきます。私のシークバーには、次のように 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();
}
});
}
}
私はこれに対する解決策を思いつきました、それはあまりきれいではありません、しかしそれはトリックをするべきです...
アイデアは次のとおりです。
サムボタンを除くすべてのスライダーを覆う非表示のオーバーレイを作成します
(オーバーレイとして機能するために、黒く塗りつぶされたシークバーを使用しました)
親指を押したら、スライダーの「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);
これは、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);
}
}
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;
}
}
}
追跡を停止したときの進行状況を比較できます。
@lordmegamax コードを見て、うまくいかないものを見つけました。
少し考えてみると、解決策が見つかりました。
//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: 初めての投稿です、間違っていたらごめんなさい。
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
}
}
私が直面していた状況は、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」式の内容を返すことはできますが、それではコードを読みやすくすることはできません。