2009-03-10 9 views
17

Próbuję uzyskać pionowy pasek wyszukiwania zgodny z emulatorem, ale jestem w pewnym stopniu zablokowany. Mogę uzyskać pasek wyszukiwania, który będzie wyświetlany w żądany sposób, i mogę uzyskać postępy, aby zrobić to, co chcę, i mogę zmodyfikować poziomo onTouchEvent, aby kciuk przesunął się w pionie zamiast o . Nie mogę tego zrobić, aby kciuk przesunął się poza domyślne 29 poziomych pikseli bez użycia setThumbOffset(). To samo w sobie, w , nie stanowi problemu. Problem wynika z faktu, że I w ogóle nie rozumiem thumbOffset - tak myślę. Myślę, że mógłbym (odpowiednio) zmienić rozmiar widżetu , co do którego jestem pewien, że nie robię dobrze. A może mógłbym po prostu użyć ThumbOffset, gdybym mógł to rozgryźć. Ponieważ mogę obliczyć postęp poprawnie pomyślałem, że po prostu użyłbym funkcji liniowej postępu * (getTop() - getBottom()) widżetu, ale wydaje się, że to nie robi. Ale nie mogę się zorientować, na czym polega przesunięcie względem siebie.Modyfikowanie widgetu apletu Android do działania w pionie

W pewnym sensie nie jestem pewien, czy to, co robię w onSizeChanged(), jest przy zdrowych zmysłach lub jeśli chce mnie ugryźć w dupę później: .

Oto układ 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> 

I klasa (ignorować śmieci debugowania):

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; 
     } 

} 
+0

musi zobaczyć http://stackoverflow.com/a/28397583/3496570 i http://stackoverflow.com/a/28397530/ 3496570 – Nepster

Odpowiedz

9

Dla API 11 and later można użyć atrybutówdla uzyskania efektu pionowego (android:rotation="270").

<SeekBar 
android:id="@+id/seekBar1" 
android:layout_width="match_parent" 
android:layout_height="wrap_content" 
android:rotation="270"/> 

Dla starszej poziomie API (ex API10), użyj: https://github.com/AndroSelva/Vertical-SeekBar-Android lub zobaczyć ten sample here

Trzeba też go zaktualizować to wysokość & szerokość jak sugerują przez Iftikhar

Aby uzyskać

seekBar.setLayoutParams(
       new ViewGroup.LayoutParams(convertDpToPixels(1.0f,mContext), ViewGroup.LayoutParams.WRAP_CONTENT)); 

// nie testowałem ..

gdzie

public static int convertDpToPixels(float dp, Context context){ 
    Resources resources = context.getResources(); 
    return (int) TypedValue.applyDimension(
      TypedValue.COMPLEX_UNIT_DIP, 
      dp, 
      resources.getDisplayMetrics() 
    ); 
} 
+0

w ten sposób nie możesz zmienić wysokości i szerokości paska wyszukiwania, po obrocie są one wciąż takie same. –

2

Spójrz na android source. Myślę, że musisz zmienić przynajmniej trackTouchEvent i być może kilka innych miejsc, w których musisz również zamienić współrzędne x, y, aby uwzględnić rotację kontrolki.

0

mógłbyś zostawić SeekBar poziomo, umieścić go w układzie ramki, a następnie obrócić układ o 90 stopni w Java? brzmi wykonalne ...

17

Stworzyłem rozwiązanie, które działa (przynajmniej dla mnie, tak) i tworzy pionowy SeekBar. http://hackskrieg.wordpress.com/2012/04/20/working-vertical-seekbar-for-android/

Ten kod będzie poprawnie wybierać/odznaczyć kciuk, poruszać się poprawnie, poprawnie aktualizować słuchacza (tylko, gdy postęp się zmienia!), Zaktualizować/narysować postęp poprawnie, itp. Mam nadzieję, że ci to pomoże.

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(); 
} 
} 

Właśnie umieszczony ten pionowa SeekBar wewnątrz LinearLayout z layout_height zestaw do FILL_PARENT i layout_width ustawiony WRAP_CONTENT.

<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> 

UWAGA: Należy ustawić OnSeekBarChangeListener, inaczej interakcji z SeekBar będzie produkować NullPointerException.

+0

@ Technlx, ​​używasz tego rozwiązania do widżetu na ekranie głównym? – rxlky

+0

Da ci to błąd, dopóki nie użyjesz "setOnSeekBarChangeListener" w odpowiedniej aktywności Java lub klasie –

Powiązane problemy