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

How to add delay in onDraw() in android canvas?

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

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

我想要做的是圆圈应该一个接一个地出现。首先是最内圈,然后是下一个,经过一些延迟,然后是下一个,依此类推。拖动屏幕时应该会看到相同的效果。我怎样才能做到这一点?任何帮助将不胜感激。

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

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

这样做的目的是让线程休眠 3 秒,然后在时间段结束后继续正常运行。您也可以将其更改为其他时间测量值,例如 TimeUnit.MILLISECONDSTimeUnit.MINUTES

编辑:您可能不希望在您的主线程中使用它,因为无论您将线程置于超时状态多长时间,它都会停止整个应用程序的工作,因此您放置它几乎是必不可少的在一个单独的线程中。

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

找出我自己问题的答案。我不得不使用一个处理程序,将延迟与 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();
    }
}