【问题标题】:How to make the android canvas re-draw every 5 seconds如何使android画布每5秒重新绘制一次
【发布时间】:2015-02-07 21:55:10
【问题描述】:

我正在制作一个需要动态动画的应用。 (玩家动作)我正在使用Canvas 对象来执行此操作。我的第一个问题是“Canvas 真的是处理这些动画的最佳方式吗?”, 我的第二个问题是“如何将玩家重新绘制到Canvas?”这是我的代码:

theGame.java:

package birdprograms.freezetag;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;

public class theGame extends Activity {
    players[] arr = {
            new player(),
            new player(),
            new player(),
            new player()
    };
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new myView(this));
    }
    public class myView extends View {
        Paint paint = new Paint();
        public myView(Context context) {
            super(context);
            paint.setColor(Color.YELLOW);
        }
        @Override
        public void onDraw(final Canvas canvas) {
            arr[0].update(true, true);
            arr[0].draw(canvas, paint);
        }
    }
}

player.java

package birdprograms.freezetag;

import android.graphics.*;

public class player {
    int y = 0;
    int x = 0;
    int vy = 5;
    int vx = 5;
    int height = y + 15;
    int width = x + 15;
    public void draw(Canvas canvas, Paint paint){
        canvas.drawRect(x,y,width,height,paint);
    }
    public void update(boolean left, boolean top){
        if(left){x += vx; width = x + 15;}
        else{x -= vx; width = x + 15;}
        if(top){y += vy; height = y + 15;}
        else{y -= vy; height = y + 15;}
    }
}

【问题讨论】:

    标签: java android android-canvas


    【解决方案1】:

    您可以通过制作计时器并设置时间表固定费率来做到这一点。在视图构造函数中调用 init。

    private void init(){
        Timer timer = new Timer();
        timer.scheduleAtFixedRate(new TimerTask(){
            public void run() {
                 postInvalidate();
            }
        }, 0, 5 * 1000L);//5 seconds
    }
    

    【讨论】:

      【解决方案2】:

      您无法真正控制何时调用 onDraw:当视图无效时,将在将来的某个时间调用 onDraw

      您的代码中有一个根本性的设计缺陷:在执行onDraw 期间玩家的位置被修改:您将无法控制它。

      每 5 秒移动一次玩家:您可以使用 Handler.postDelayed 每 5 秒重新发布相同的 RunnableRunnable 将更新玩家位置,然后使 View 无效。

      这里有一些代码来说明这个想法

      (免责声明:这是伪代码,它只关心索引为 0 的玩家,还有更多工作要做才能移动所有玩家,...)

      public class myView extends View {
          Paint paint = new Paint();
          public myView(Context context) {
              super(context);
              paint.setColor(Color.YELLOW);
              movePlayer0Runnable.run(); //this is the initial call to draw player at index 0
          }
      
          @Override
          public void onDraw(final Canvas canvas) {
              super.onDraw(canvas);  //IMPORTANT to draw the background
              arr[0].draw(canvas, paint);
          }
      
          Handler handler = new Handler(Looper.getMainLooper());
          Runnable movePlayer0Runnable = new Runnable(){
              public void run(){
                  arr[0].update(true, true);
                  invalidate(); //will trigger the onDraw
                  handler.postDelayed(this,5000); //in 5 sec player0 will move again
              }
          }   
          ... 
      }
      

      【讨论】:

      • 你能举个例子吗?
      • 非常感谢!现在我明白了很多。
      • 如何移除这些回调?
      • @vinshaba handler.removeCallbacksAndMessages(null)
      • @ben75 是的,但你怎么称呼它?在View类的哪个方法中
      【解决方案3】:

      How to animate a path on canvas - android 中所示的onDraw 方法内部调用postInvalidateDelayed(5000) 比生成计时器或可运行对象的现有答案要简单一些。和他们一样,它不是高分辨率计时器。

      这是一个最小的完整示例:

      布局:

      <?xml version="1.0" encoding="utf-8"?>
      <LinearLayout
          xmlns:android="http://schemas.android.com/apk/res/android"
          android:keepScreenOn="true"
          android:layout_width="match_parent"
          android:layout_height="match_parent"
          android:gravity="center"
          android:orientation="vertical"
      >
          <view
              class="com.example.foo.FooActivity$Drawer"
              android:layout_width="fill_parent"
              android:layout_height="0dp"
              android:layout_weight="1"
          />
      </LinearLayout>
      

      活动:

      package com.example.foo;
      
      import android.app.Activity;
      import android.content.Context;
      import android.graphics.Canvas;
      import android.graphics.Paint;
      import android.os.Bundle;
      import android.util.AttributeSet;
      import android.view.View;
      
      import java.util.Random;
      
      public class FooActivity extends Activity {
          @Override
          protected void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.activity_foo);
          }
      
          public static class Drawer extends View {
              private static final int delayMS = 5000;
              private static Random rnd;
              private static Paint paint;
              private static int viewWidth;
              private static int viewHeight;
      
              public Drawer(Context con, AttributeSet attr) {
                  super(con, attr);
                  rnd = new Random();
                  paint = new Paint(Paint.ANTI_ALIAS_FLAG);
                  paint.setStyle(Paint.Style.FILL);
              }
      
              // https://stackoverflow.com/a/9718512/6243352
              @Override
              protected void onSizeChanged(int xNew, int yNew, int xOld, int yOld) {
                  super.onSizeChanged(xNew, yNew, xOld, yOld);
                  viewWidth = xNew;
                  viewHeight = yNew;
              }
      
              @Override
              protected void onDraw(final Canvas c) {
                  super.onDraw(c);
      
                  // https://stackoverflow.com/a/18617993/6243352
                  postInvalidateDelayed(delayMS);
      
                  int color = rnd.nextInt(256);
                  paint.setARGB(255, color, color, color);
                  c.drawCircle(
                      viewWidth / 2,
                      viewHeight / 2,
                      viewWidth / 4,
                      paint
                  );
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-10-24
        • 1970-01-01
        • 2012-01-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-25
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多