Android线程等到可见

时间:2013-04-17 12:57:32

标签: android multithreading android-animation

我已经创建了一个自定义饼图视图,我想在饼图可见时启动动画。目前我所拥有的是饼图动画,但当你在屏幕上实际看到它时,动画已经结束了一半。这就是我所拥有的:

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

此外,如果您发现任何编程错误,内存泄漏,性能不佳的代码,请告诉我们。我是Android的新手。

以下是使用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>

2 个答案:

答案 0 :(得分:5)

好吧,我将使用我的饼图不会自动设置动画,它将有一个新功能,一旦它准备好,Activity将触发启动动画。我希望有一种更简单的方法......

答案 1 :(得分:1)

或者,您可以使用animation framework(或nine old androids,如果您想支持较旧的api)。这将允许您为视图中的属性设置动画,在您的情况下为开始和当前变量。

我认为这是在onAttachedToWindow期间发生的。

请注意,如果您在此饼图中没有做很多其他事情,那么表面视图可能会因您的需求而过度。