수직으로 작동하도록 Android Seekbar 위젯을 수정합니다
문제
나는 에뮬레이터와 함께 수직 Seetbar를 얻으려고 노력하고 있지만, 나는 일종의 갇혀 있습니다. Seekbar가 원하는 방식을 표시하도록 할 수 있으며, 원하는 작업을 수행하기 위해 진행 상황을 얻을 수 있으며, Ontouchevent를 수정하여 엄지 손가락을 수평으로 수직으로 수직으로 만들 수 있습니다. 내가 할 수없는 것은 SetThumbOffset ()을 사용하지 않고 기본 29 가로 픽셀을 바깥으로 이동하는 것입니다. 이것은 그 자체로 문제가되지 않습니다. 문제는 제가 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;
}
}
해결책
을 위한 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)의 경우 사용하십시오. https://github.com/androselva/vertical-seekbar-enroid 또는 이것을 참조하십시오 여기 샘플
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()
);
}
다른 팁
나는 (적어도 나를 위해, 어쨌든) 작동하는 솔루션을 만들고 수직 탐사 바를 만듭니다.http://hackskrieg.wordpress.com/2012/04/20/working-vertical-seekbar-for-endroid/
이 코드는 엄지를 올바르게 선택/선택하고, 올바르게 이동하고, 청취자를 올바르게 업데이트하고 (진행 상황이 변경 될 때만) 진행 상황을 올바르게 업데이트/그리기 등으로 만듭니다. 도움이되기를 바랍니다.
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를 layout_height로 설정 한 LinearLayout 안에 배치했습니다.
<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이 생성됩니다.
다운로드 할 수 있습니다 http://560b.sakura.ne.jp/android/verticalslidebarexample.zip, 나는 이것이 당신을 도울 수 있기를 바랍니다
보세요 안드로이드 소스 . 나는 당신이 최소한 trackTouchevent를 변경해야한다고 생각하며 X, Y 좌표를 교환하여 컨트롤의 회전을 고려하여 몇 가지 다른 장소가있을 수 있습니다.
Seekbar를 수평으로 남겨두고 프레임 레이아웃에 넣은 다음 Java에서 레이아웃 90도 회전 할 수 있습니까? 할 수있는 소리 ...