如何在Android canvas中的onDraw()中添加延迟?

时间:2018-08-15 03:17:05

标签: java android canvas delay ondraw

我正在做一个项目。它在android画布中绘制同心圆。当用户拖动屏幕时,所有圆圈都会相应移动。到目前为止,这是我的代码。

activity_main.xml:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:background="@android:color/white">

        <RelativeLayout
        android:id="@+id/scrollableSpace"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true">

        <project.myProject.DrawOrbit
            android:id="@+id/orbitsRegion"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_alignParentRight="true"
            android:layout_alignParentBottom="true"
            android:layout_alignParentTop="true"
            android:layout_alignParentLeft="true" />


    </RelativeLayout>
</RelativeLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnTouchListener
{
    PointF center;
    center.x=500;center.y=500;
    float radius[]={100,200,300,400,500};
    DrawOrbit orbit;
    int startX=0,startY=0,currentX=0,currentY=0;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RelativeLayout layout=(RelativeLayout)findViewById(R.id.scrollableSpace);
        orbit.draw(center,radius);

        layout.setOnTouchListener(this);
    }   


    @Override
    public boolean onTouch(View v, MotionEvent motionEvent)
    {

        final int action= motionEvent.getAction();
        switch(action & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
            {              
                startX=(int)motionEvent.getRawX();
                startY=(int)motionEvent.getRawY();             

                break;
            }
            case MotionEvent.ACTION_MOVE:
            {
                currentX=(int)motionEvent.getRawX();
                currentY=(int)motionEvent.getRawY();               

                float diffX=currentX-startX;
                float diffY=currentY-startY;

                startX=currentX;
                startY=currentY;

                center.x+=diffX;
                center.y+=diffY;
                orbit.draw(center,radius);

                break;
            }          

        }
        return true;

    }
}

DrawOrbit.java

public class DrawOrbit extends View
{
    PointF center;
    float radius[];
    public DrawOrbit(Context context) {
        super(context);
    }

    public DrawOrbit(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawOrbit(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        paint.setColor(Color.BLACK);

        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.STROKE);
        int len=radius.length;
        for(int a=0;a<len;a++)
        {
            canvas.drawCircle(center.x,center.y,radius[a],paint);
        }
    }   

    public void draw(PointF center, float radius[])
    {
        this.center=center;
        this.radius=radius;
        invalidate();        
        requestLayout();
    }
}

我想做的是圆圈应该一个接一个地出现。首先是最里面的圆圈,然后是经过延迟的下一个圆圈,然后是下一个圆圈,依此类推。拖动屏幕时应看到相同的效果。我该如何实现?任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:0)

您要寻找的是超时。我建议创建一个新线程以绘制所有内容,并从绘制第一个圆开始,使方法如下所示:

public void drawCircle() {
    //Draw logic
    TimeUnit.SECONDS.sleep(3);
    drawNextCircle();
}
//Assuming on java 1.8+
Thread thread = new Thread() => {
    drawCircle();
}

这将使线程休眠3秒钟,然后在该时间段结束后继续正常运行。您也可以将其更改为其他时间度量方式,例如TimeUnit.MILLISECONDSTimeUnit.MINUTES

edit:您可能不希望在主线程中使用它,因为无论您将线程置于超时的时间如何,它都会使ENTIRE应用程序停止工作,因此,将其放在单独的线程。

edit 2:与上面的代码相比,向超时添加一个单独的util方法,然后通过反射调用另一个方法会更有意义,但是将需要相同的代码。

答案 1 :(得分:0)

找出我自己问题的答案。我必须使用一个处理程序,将延迟与for循环变量相乘,然后乘以1再乘以2,以此类推。这是代码。

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnTouchListener
{
    PointF center;
    center.x=500;center.y=500;
    float radius[]={100,200,300,400,500};
    DrawOrbit orbit;
    int startX=0,startY=0,currentX=0,currentY=0;
    Handler handler1 = new Handler();

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        RelativeLayout layout=(RelativeLayout)findViewById(R.id.scrollableSpace);
        for (int a = 0; a<radius.length ;a++)
        {
            final int index=a;
            handler1.postDelayed(new Runnable() {

                @Override
                public void run() {
                    orbit.draw(center,radius,index);
                }
            }, 300 * a);
        }

        layout.setOnTouchListener(this);
    }   


    @Override
    public boolean onTouch(View v, MotionEvent motionEvent)
    {

        final int action= motionEvent.getAction();
        switch(action & MotionEvent.ACTION_MASK)
        {
            case MotionEvent.ACTION_DOWN:
            {              
                startX=(int)motionEvent.getRawX();
                startY=(int)motionEvent.getRawY();             

                break;
            }
            case MotionEvent.ACTION_MOVE:
            {
                currentX=(int)motionEvent.getRawX();
                currentY=(int)motionEvent.getRawY();               

                float diffX=currentX-startX;
                float diffY=currentY-startY;

                startX=currentX;
                startY=currentY;

                center.x+=diffX;
                center.y+=diffY;

                break;
            } 
            case MotionEvent.ACTION_UP:
            {
                for (int a = 0; a<radius.length ;a++)
                {
                    final int index=a;
                    handler1.postDelayed(new Runnable() {

                        @Override
                        public void run() {
                            orbit.draw(center,radius,index);
                        }
                    }, 300 * a);
                }
                break;
            }

        }
        return true;

    }
}

DrawOrbit.java

public class DrawOrbit extends View
{
    PointF center;
    float radius[];
    int index;
    public DrawOrbit(Context context) {
        super(context);
    }

    public DrawOrbit(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public DrawOrbit(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);
        paint.setColor(Color.BLACK);

        paint.setStrokeWidth(2);
        paint.setStyle(Paint.Style.STROKE);
        int len=radius.length;
        for(int a=0;a<index;a++)
        {
            canvas.drawCircle(center.x,center.y,radius[a],paint);
        }
    }   

    public void draw(PointF center, float radius[],int index)
    {
        this.center=center;
        this.radius=radius;
        this.index=index;
        invalidate();        
        requestLayout();
    }
}