2013-02-16 2 views
0

Я хочу сделать представление, показывающее, что точка/круг движутся горизонтально по экрану. Я хочу достичь этого только через пользовательский вид. Итак, я написал фрагмент кода, в котором я хочу вызвать onDraw(), который будет рисовать круг, тогда он вызовет обработчик, который будет ждать 500 мс и вызывать onDraw(). Поэтому каждый раз, когда onDraw() называется кругом, будет сдвинут на несколько шагов вправо. , но здесь я не могу синхронизировать вызов между run() и onDraw(). код:Нужно синхронизировать между обработчиком и onDraw()

package com.example.layoutpractice; 

import javax.net.ssl.HandshakeCompletedListener; 

import android.annotation.TargetApi; 
import android.content.Context; 
import android.graphics.Canvas; 
import android.graphics.Color; 
import android.graphics.Paint; 
import android.graphics.Point; 
import android.graphics.PorterDuff.Mode; 
import android.os.Build; 
import android.os.Handler; 
import android.util.Log; 
import android.view.Display; 
import android.view.View; 
import android.view.WindowManager; 

public class DrawView extends View { 
    private static final String TAG = "DrawView"; 
    Context ctx = null; 
    int MAX_WIDTH = 0; 
    int MAX_HEIGHT = 0; 
    int current_x = 0; 
    int current_y = 0; 
    Paint paint = null; 

    public DrawView(Context context) { 

    @TargetApi(13) 
    private void initialize() { 
     // get the screen size 
     WindowManager wm = (WindowManager) ctx 
       .getSystemService(Context.WINDOW_SERVICE); 
     Display display = wm.getDefaultDisplay(); 
     Point size = new Point(); 
     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) { 
      display.getSize(size); 
      MAX_WIDTH = size.x; 
      MAX_HEIGHT = size.y; 
     } else { 
      MAX_WIDTH = display.getWidth(); 
      MAX_HEIGHT = display.getHeight(); 
     } 

     // initialize paint 
     paint = new Paint(); 
     paint.setColor(Color.BLUE); 
     this.setFocusable(true); 
     this.setFocusableInTouchMode(true); 
    } 

    @Override 
    protected void onDraw(Canvas canvas) { 
     Log.d(TAG, "onDraw()"); 
     current_y = MAX_HEIGHT/2; 
     while (current_x < MAX_WIDTH) { 
      canvas.drawColor(Color.WHITE, Mode.CLEAR); 
      canvas.drawCircle(current_x, current_y, 2, paint); 
      current_x = current_x + 10; 
      // new Thread(new TimeHandler()).start(); 
      new TimeHandler().execute(); 
     } 
     super.onDraw(canvas); 
    } 

    class TimeHandler extends Handler { 
     Runnable myRun = new Runnable() { 
      public void run() { 
       Log.d(TAG, "run"); 
       invalidate(); 
      } 
     }; 

     public void execute() { 
      this.postDelayed(myRun, 500); 
     } 

    } 
} 

журналы

02-17 01:40:28.355: D/DrawView(1162): onDraw() 
02-17 01:40:28.875: D/DrawView(1162): run 
02-17 01:40:28.875: D/DrawView(1162): run 
02-17 01:40:28.875: D/DrawView(1162): run 
02-17 01:40:28.875: D/DrawView(1162): run 
02-17 01:40:28.966: D/DrawView(1162): onDraw() 
02-17 01:40:28.966: D/DrawView(1162): run 
02-17 01:40:28.966: D/DrawView(1162): run 
02-17 01:40:28.966: D/DrawView(1162): run 
02-17 01:40:28.966: D/DrawView(1162): run 
02-17 01:40:29.005: D/DrawView(1162): run 
02-17 01:40:29.005: D/DrawView(1162): run 
02-17 01:40:29.005: D/DrawView(1162): run 
02-17 01:40:29.005: D/DrawView(1162): run 
02-17 01:40:29.005: D/DrawView(1162): run 
02-17 01:40:29.005: D/DrawView(1162): run 
02-17 01:40:29.036: D/DrawView(1162): run 
02-17 01:40:29.036: D/DrawView(1162): run 
02-17 01:40:29.036: D/DrawView(1162): run 
02-17 01:40:29.036: D/DrawView(1162): run 
02-17 01:40:29.036: D/DrawView(1162): run 
02-17 01:40:29.036: D/DrawView(1162): run 
02-17 01:40:29.065: D/DrawView(1162): run 
02-17 01:40:29.065: D/DrawView(1162): run 
02-17 01:40:29.075: D/DrawView(1162): run 
02-17 01:40:29.075: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.101: D/DrawView(1162): run 
02-17 01:40:29.105: D/DrawView(1162): onDraw() 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.125: D/DrawView(1162): run 
02-17 01:40:29.175: D/DrawView(1162): onDraw() 
+0

Разве это не потому, что вы выполняете итерацию (в цикле while), и вы вызываете Handler.execute() несколько раз? я не уверен, что это лучший способ сделать это, взгляните на APIDemos, некоторые анимации делают именно это. –

+0

Я хочу добиться этого поведения с помощью пользовательского представления, но я тоже буду смотреть на анимацию, и здесь я думаю, что я вызов выполняется один раз на каждой итерации и требует, чтобы каждая итерация сохранялась в течение 500 мс. – 2013-02-16 20:50:00

+0

. Вы также можете взглянуть на SurfaceView, который использует обратные вызовы для рисования и недействительности (не испытывал с ним) –

ответ

0

Изменить

while (current_x < MAX_WIDTH) 

в

if (current_x < MAX_WIDTH) 

P.S. вы проектируете неправильно. onDraw - это специальный метод, который может вызывать android, а не только вы. Каждый раз, когда onDraw вызывается с помощью invalidate или самого фрейма, вы планируете запустить runyable за 500 мс. И вы думаете, что onDraw будет выполняться каждые 500 мс (current_x = current_x + 10;) ... у вас есть проблема)

Чтобы исправить вашу проблему, не ставьте никакой логики в ondraw. OnDraw должен отображать только текущее состояние. Оставьте только это:

current_y = MAX_HEIGHT/2; 
    canvas.drawColor(Color.WHITE, Mode.CLEAR); 
    canvas.drawCircle(current_x, current_y, 2, paint); 

    super.onDraw(canvas); 

Создать дополнительный метод в вас пользовательский вид, который должен сделать следующее:

public void startBallMovement() { 
     animationRunnable.run(); 
} 

private Handler handler = new Handler(); 
private final Rubbanle animationRunnable = new Runnable() { 
    public void run() { 
     current_x = current_x + 10; 
     if (current_x < MAX_WIDTH) { 
      handler.postDelayed(animationRunnable, 500); 
     } 
     invalidate(); 
    } 
} 

Я уверен, что вы можете использовать мой код, как есть, но логика ясна.

+0

Это имеет смысл. Не могли бы вы предоставить то, что должно быть лучше. Есть ли какой-либо шаблон, связанный с этим типом проблемы. – 2013-02-16 22:18:03

+1

обновил мой ответ – Leonidos

+0

Я сделал то же самое. Спасибо, что ответили. – 2013-02-19 10:14:01

Смежные вопросы