一般的に指摘されているVerticalSeekBarの投稿 here を実装しました。現状では、SeekBarは少し風変わりです。以下は、その例からの私の少し適応したonTouchEvent()
です。
public boolean onTouchEvent(MotionEvent event)
{
xPos = event.getX();
yPos = event.getY();
oOffset = this.getThumbOffset();
oProgress = this.getProgress();
//Code from example - Not working
//this.setThumbOffset( progress * (this.getBottom()-this.getTop()) );
this.setProgress((int)(29*yPos/this.getBottom()));
return true;
}
私は1つのVerticalSeekBarを実装することができました。この場合、進行状況は予想どおりに更新され、完全に機能しますが、親指はそれに追従しません。これはグラフィカルなグリッチにすぎないため、今のところ見逃しています。しかし、動作するのは素晴らしいことです。このSeekBarにはmax = 20
があります。
ただし、max = 1000
を使用して別のVerticalSeekBarを実装してみました。明らかに、同じコードを使用するため、同じ動作を想定します。指がSeekBarを超えてスライドし、最終的に画面から外れても、0〜35の進捗しか達成できません。プログレスバーの終わり近くをタップすると(shouldprogress ~ 900
)、約35のプログレスが返され、黄色のプログレスバーはそのままでその値を反映します頂上近く。
私の質問は次のとおりです。誰かが動作している垂直のSeekBarへのリンクを持っていますか、またはこの特定の例を適応させる方法を知っていますか?
動作するVerticalSeekBarの実装は次のとおりです。
package Android.widget;
import Android.content.Context;
import Android.graphics.Canvas;
import Android.util.AttributeSet;
import Android.view.MotionEvent;
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);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}
実装するには、プロジェクトに新しいクラスを作成し、適切なパッケージを選択します。
そこで、コードを貼り付けて保存します。 XMLレイアウトで使用します。
<Android.widget.VerticalSeekBar
Android:id="@+id/seekBar1"
Android:layout_width="wrap_content"
Android:layout_height="200dp"
/>
受け入れられた回答で与えられたコードは、onStartTrackingTouchイベントとonStopTrackingTouchイベントをインターセプトしなかったため、この2つのイベントをより制御できるように修正しました。
ここに私のコードがあります:
public class VerticalSeekBar extends SeekBar {
private OnSeekBarChangeListener myListener;
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());
}
@Override
public void setOnSeekBarChangeListener(OnSeekBarChangeListener mListener){
this.myListener = mListener;
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if(myListener!=null)
myListener.onStartTrackingTouch(this);
break;
case MotionEvent.ACTION_MOVE:
setProgress(getMax() - (int) (getMax() * event.getY() / getHeight()));
onSizeChanged(getWidth(), getHeight(), 0, 0);
myListener.onProgressChanged(this, getMax() - (int) (getMax() * event.getY() / getHeight()), true);
break;
case MotionEvent.ACTION_UP:
myListener.onStopTrackingTouch(this);
break;
case MotionEvent.ACTION_CANCEL:
break;
}
return true;
}
}
SetProgressメソッドでこのコードを使用中に問題が発生しました。それらを解決するには、setProgressをオーバーライドし、onSizeChanged呼び出しを追加することをお勧めします。
SetProgressメソッドでこのコードを使用中に問題が発生しました。それらを解決するには、setProgressをオーバーライドしてonSizeChanged呼び出しを追加することをお勧めします。ここにコードを追加しました..
private int x,y,z,w;
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
this.x=w;
this.y=h;
this.z=oldw;
this.w=oldh;
}
@Override
public synchronized void setProgress(int progress) {
super.setProgress(progress);
onSizeChanged(x, y, z, w);
}
選択したホバーアクションは、次のコードを追加して実行されます。
1.setPressed(true); setSelected(true); // ACTION_DOWNに追加
2.setPressed(false); setSelected(false); // ACTION_UPにこれを追加
また、選択したホバーオプションのコードをur xmlで記述します。
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
<item Android:state_pressed="true"
Android:state_window_focused="true"
Android:drawable="@drawable/thumb_h" />
<item Android:state_selected="true"
Android:state_window_focused="true"
Android:drawable="@drawable/thumb_h" />
<item Android:drawable="@drawable/thumb" />
</selector>
これは私のために働いています...
このすばらしいコードを作成してくれたPaul Tsupikoff、Fatal1ty2787、Rameshに感謝します。
個人的には、与えられたコードと比較して上下が逆の垂直スライダーが必要でした。言い換えると、値は減少するのではなく増加するので、親指が低くなります。 4行を変更することでこれを処理できたようです。
最初に、元々Paulから与えられたonDraw()
メソッドを変更しました。 rotate()
およびtranslate()
呼び出しには、次の引数があります。
_c.rotate(90);
c.translate(0, -getWidth());
_
次に、Fatal1ty2787によって指定されたonTouchEvent()
の_ACTION_MOVE
_ケースに2つの変更を加えました。 setProgress()
の呼び出しは次のようになります。
_setProgress((int) (getMax() * event.getY() / getHeight()));
_
最後に、onProgressChanged()
の呼び出しは次のようになります。
_myListener.onProgressChanged(this, (int) (getMax() * event.getY() / getHeight()), true);
_
さて、もしGoogleだけがこの機能への関心を共有していたら...
にとって API 11 and later
、 使える seekbar's XML attributes
(Android:rotation="270"
)垂直効果用。
<SeekBar
Android:id="@+id/seekBar1"
Android:layout_width="match_parent"
Android:layout_height="wrap_content"
Android:rotation="270"/>
古いAPIレベル(ex API10)の場合: https://github.com/AndroSelva/Vertical-SeekBar-Android
別のアイデアは、MotionEventのXおよびY座標を変更し、それらをスーパー実装に渡すことです。
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);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if (!isEnabled()) {
return false;
}
float x = (getHeight() - event.getY()) * getWidth() / getHeight();
float y = event.getX();
MotionEvent verticalEvent = MotionEvent
.obtain(event.getDownTime(), event.getEventTime(), event.getAction(), x, y,
event.getPressure(), event.getSize(), event.getMetaState(),
event.getYPrecision(), event.getXPrecision(), event.getDeviceId(),
event.getEdgeFlags());
return super.onTouchEvent(verticalEvent);
}
protected void onDraw(Canvas c) {
c.rotate(-90);
c.translate(-getHeight(), 0);
super.onDraw(c);
}
@Override
protected synchronized void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(heightMeasureSpec, widthMeasureSpec);
setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
}
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(h, w, oldh, oldw);
}
}
この場合、setProgress(int)メソッドを呼び出す必要はないため、OnSeekBarChangeListener.onProgressChanged()のブールフラグ「fromUser」を使用して、ユーザーインタラクションによってシークが生成されたかどうかを判断できます。
対象プラットフォーム
from Android 2.3.x(Gingerbread)to Android 7.x(Nougat)
はじめに
このライブラリはjCenterで公開されています。これらの行をbuild.gradleに追加するだけです。
dependencies {
compile 'com.h6ah4i.Android.widget.verticalseekbar:verticalseekbar:0.7.2'
}
使用法
レイアウトXML
<!-- This library requires pair of the VerticalSeekBar and VerticalSeekBarWrapper classes -->
<com.h6ah4i.Android.widget.verticalseekbar.VerticalSeekBarWrapper
Android:layout_width="wrap_content"
Android:layout_height="150dp">
<com.h6ah4i.Android.widget.verticalseekbar.VerticalSeekBar
Android:id="@+id/mySeekBar"
Android:layout_width="0dp"
Android:layout_height="0dp"
Android:max="100"
Android:progress="0"
Android:splitTrack="false"
app:seekBarRotation="CW90" /> <!-- Rotation: CW90 or CW270 -->
</com.h6ah4i.Android.widget.verticalseekbar.VerticalSeekBarWrapper>
注意: Android:splitTrack="false"
は、Android N +。
Javaコード
public class TestVerticalSeekbar extends AppCompatActivity {
private SeekBar volumeControl = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test_vertical_seekbar);
volumeControl = (SeekBar) findViewById(R.id.mySeekBar);
volumeControl.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
int progressChanged = 0;
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
progressChanged = progress;
}
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
public void onStopTrackingTouch(SeekBar seekBar) {
Toast.makeText(getApplicationContext(), "seek bar progress:" + progressChanged,
Toast.LENGTH_SHORT).show();
}
});
}
}