使用线程制作视图电影

时间:2014-03-06 18:14:17

标签: android multithreading

我想在单击按钮时启动一个Thread。该线程每秒都会向下移动一个视图,但它不起作用。这是代码:

public class MainActivity extends Activity {

private boolean juegoEmpezado = false;
private int clicks = 0;
private int margenTop = 20;
private int crecimientoMargen = 10;
private int velocidadDeCrecimiento = 1000;
private LayoutParams parametrosLayout;
private TextView item;


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    item = (TextView)findViewById(R.id.textView1);
    item.setText("asasas");
    parametrosLayout = (LayoutParams) item.getLayoutParams();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

public void empezarJuego(View v) {

    juegoEmpezado = true;
    empezar();
}

public void empezar() {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            while(juegoEmpezado) {
                try {
                    Thread.sleep(velocidadDeCrecimiento);
                    parametrosLayout.topMargin = margenTop;
                    margenTop += crecimientoMargen;
                    item.setLayoutParams(parametrosLayout);

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
       }
   }
});
}
}

empezar()方法是单击Button时触发的方法。

它不起作用。我看到了这个问题:Android "Only the original thread that created a view hierarchy can touch its views."

但它无法帮助我。你能告诉我问题出在哪里吗?

2 个答案:

答案 0 :(得分:2)

问题是你在这里停止主线程:

while(juegoEmpezado) {
     try {
        Thread.sleep(velocidadDeCrecimiento);

由于此调用在主线程上运行,实际上是在停止它,并且它不会刷新任何视图,你可以做的是这样的:

new Thread(new Runnable() {
            @Override
            public void run() {
                while(true){
                    empezar();
                    try{Thread.sleep(1000);}catch(InterruptedException ie){ie.toString();}
                }
            }
        }).start();

它将调用empezar(必须使用runOnUIThread来更新视图)。 这实际上是一种非常脏的方法,也许Handler可以更好地解决您的问题。

问候!

答案 1 :(得分:1)

只应在主线程上修改UI元素。没有必要为此创建一个新线程。相反,你要做的是创建一个扩展Runnable的内部类,并对其进行调整。然后使用View#postDelayed()方法每隔x毫秒运行一次。

public class CustomView extends View {

   private AnimRunnable animRunnable = new AnimRunnable();

   @Override
   protected void onAttachedToWindow() {
      animRunnable.start();
   }

   @Override
   protected void onDetachedFromWindow() {
      animRunnable.stop();
   }

   private class AnimRunnable implements Runnable {
      @Override
      public void run() {
          // Animation code
      }

      public void start() {
          postDelayed(this, 1000);
      }

      public void stop() {
          removeCallbacks(this);
      }
   }
}

编辑:

我刚注意到你没有制作自定义视图。 View#postDelayed()removeCallbacks()方法对View是公开的,因此可以轻松调整以在“视图”之外完成,因此您无需进行自定义View