2013-04-17 12 views
11

Zrobiłem niestandardowy widok wykresu kołowego, który chcę animować, rozpoczynając, gdy wykres kołowy jest widoczny. Obecnie mam animację na wykresie kołowym, ale do czasu, kiedy można go zobaczyć na ekranie, animacja jest już w połowie. Oto, co mam:Wątek z Androida czeka aż będzie widoczny

public class SinglePieChart extends SurfaceView implements SurfaceHolder.Callback { 
    // Chart setting variables 
    private int emptyCircleCol, strokeColor, number, total; 

    // Paint for drawing custom view 
    private Paint circlePaint; 

    private RectF rect; 

    private Context context; 
    private AnimThread animThread; 
    private SurfaceHolder holder; 

    // animation variables 
    private float speed; 
    private float current = 0.0f; 
    private boolean percentsCalculated = false; 
    private float degree; 
    private int viewWidth, viewHeight; 

    public SinglePieChart(Context ctx, AttributeSet attrs) { 
     super(ctx, attrs); 

     context = ctx; 

     // Paint object for drawing in doDraw 
     circlePaint = new Paint(); 
     circlePaint.setStyle(Style.STROKE); 
     circlePaint.setStrokeWidth(3); 
     circlePaint.setAntiAlias(true); 
     circlePaint.setDither(true); 


     rect = new RectF(); 

     //get the attributes specified in attrs.xml using the name we included 
     TypedArray a = context.getTheme().obtainStyledAttributes(attrs, 
      R.styleable.DashboardChartSmall, 0, 0); 

     try { 
      //get the colors specified using the names in attrs.xml 
      emptyCircleCol = a.getColor(R.styleable.DashboardChartSmall_smCircleColor, 0xFF65676E); // light gray is default 
      strokeColor = a.getColor(R.styleable.DashboardChartSmall_smColor, 0xFF39B54A); // green is default 

      // Default number values 
      total = a.getInteger(R.styleable.DashboardChartSmall_smTotal, 1); 
      number = a.getInteger(R.styleable.DashboardChartSmall_smNumber, 0); 
     } finally { 
      a.recycle(); 
     } 

     this.setZOrderOnTop(true); 

     holder = getHolder(); 
     holder.setFormat(PixelFormat.TRANSPARENT); 

     holder.addCallback(this); 
    } 

    protected void calculateValues() { 
     degree = 360 * number/total; 
     percentsCalculated = true; 
     speed = 10 * number/total; 
     viewWidth = this.getMeasuredWidth(); 
     viewHeight = this.getMeasuredHeight(); 

     float top, left, bottom, right; 

     if (viewWidth < viewHeight) { 
      left = 4; 
      right = viewWidth - 4; 
      top = ((viewHeight - viewWidth)/2) + 4; 
      bottom = viewHeight - top; 
     } else { 
      top = 4; 
      bottom = viewHeight - 4; 
      left = ((viewWidth - viewHeight)/2) + 4; 
      right = viewWidth - left; 
     } 

     rect.set(left, top, right, bottom); 
    } 

    protected void doDraw(Canvas canvas) { 
     if (total == 0) { 
      // Number values are not ready 
      animThread.setRunning(false); 
      return; 
     } 

     if (!percentsCalculated) { 
      calculateValues(); 
     } 

     // set the paint color using the circle color specified 
     float last = current; 
     float start = -90; 

     circlePaint.setColor(strokeColor); 
     canvas.drawArc(rect, start, (last > degree) ? degree : last, false, circlePaint); 
     start += (last > number) ? number : last; 
     last = (last < number) ? 0 : last - number; 

     circlePaint.setColor(emptyCircleCol); 

     if (current > 360) { 
      current = 360; 
     } 

     canvas.drawArc(rect, start, 360 - current, false, circlePaint);  

     current += speed; 

     if (last > 0 || number == 0) { 
      // we're done 
      animThread.setRunning(false); 
     } 
    } 

    public void setNumbers(int num, int tot) { 
     number = num; 
     total = tot; 

     invalidate(); 
     requestLayout(); 
    } 


    public void setColor(int col) { 
     strokeColor = col; 
    } 

    public void redraw() { 
     calculateValues(); 
     animThread.setRunning(true); 

     invalidate(); 
     requestLayout(); 
    } 

    @Override 
    public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 
    } 

    @Override 
    public void surfaceCreated(SurfaceHolder arg0) { 
     animThread = new AnimThread(holder, context, this); 
     animThread.setRunning(true); 
     animThread.start(); 
    } 

    @Override 
    public void surfaceDestroyed(SurfaceHolder arg0) { 
     animThread.setRunning(false); 

     boolean retry = true; 

     while(retry) { 
      try { 
       animThread.join(); 
       retry = false; 
      } catch(Exception e) { 
       Log.v("Exception Occured", e.getMessage()); 
      } 
     } 
    } 

    public class AnimThread extends Thread { 
     boolean mRun; 
     Canvas mcanvas; 
     SurfaceHolder surfaceHolder; 
     Context context; 
     SinglePieChart msurfacePanel; 

     public AnimThread(SurfaceHolder sholder, Context ctx, SinglePieChart spanel) { 
      surfaceHolder = sholder; 
      context = ctx; 
      mRun = false; 
      msurfacePanel = spanel; 
     } 

     void setRunning(boolean bRun) { 
      mRun = bRun; 
     } 

     @Override 
     public void run() { 
      super.run(); 
      while (mRun) { 
       mcanvas = surfaceHolder.lockCanvas(); 
       if (mcanvas != null) { 
        msurfacePanel.doDraw(mcanvas); 
        surfaceHolder.unlockCanvasAndPost(mcanvas); 
       } 
      } 
     } 
    } 
} 

Jeśli widzisz błędy programistyczne, wycieki pamięci, słabe działanie kodu, daj mi znać. Jestem nowy na Androida.

Oto układ, który wykorzystuje klasę SinglePieChart:

<?xml version="1.0" encoding="utf-8"?> 
<merge xmlns:android="http://schemas.android.com/apk/res/android"> 
    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="0dp" 
     android:layout_weight="1"> 
     <com.davidscoville.vokab.views.elements.SinglePieChart 
      android:id="@+id/smallPieChart" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" /> 

     <TextView 
      android:id="@+id/dashSmNumber" 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:layout_centerHorizontal="true" 
      android:layout_centerVertical="true" 
      android:textSize="25sp" 
      android:textColor="#FFFFFF" /> 

    </RelativeLayout> 

    <TextView 
     android:id="@+id/dashSmLabel" 
     android:layout_width="match_parent" 
     android:layout_height="20dp" 
     android:textSize="14sp" 
     android:gravity="center" 
     android:textColor="#FFFFFF" /> 
</merge> 
+0

jaki jest twój problem? – Blackbelt

+0

"Utworzyłem niestandardowy widok wykresu kołowego, który chcę animować, rozpoczynając od wyświetlenia wykresu kołowego. Obecnie mam animację wykresu kołowego, ale do czasu, kiedy można go zobaczyć na ekranie, animacja jest o połowę . " – chrislondon

+0

używasz niestandardowego SurfaceView w układzie? – Blackbelt

Odpowiedz

5

Dobra idę z moim wykresie kołowym nie będzie automatycznie animować i będzie mieć nową funkcję, że aktywność będzie powodować, aby rozpocząć animowanie, gdy będzie gotowe. Szkoda, że ​​nie było łatwiejszego sposobu ...

1

Alternatywnie możesz użyć animation framework (lub nine old androids, jeśli chcesz wspierać starsze apisy). Umożliwi to animowanie właściwości w widoku, w twoim przypadku zmiennych początkowych i bieżących.

Ustawiłbym, że stanie się to podczas onAttachedToWindow.

Uwaga: jeśli nie robisz wielu innych rzeczy na tej wykresie kołowym, widok powierzchni może być przesadny dla twoich potrzeb.

Powiązane problemy