Reputation: 183
I want to start a Thread when I click a Button. That Thread moves a View down every second, but it doesn't work. Here's the code:
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();
}
}
}
});
}
}
The empezar()
method is the method that fires when I click the Button.
It doesn't work. I saw this question: Android "Only the original thread that created a view hierarchy can touch its views."
But it can't help me. Can you tell me where is the problem?
Upvotes: 0
Views: 56
Reputation: 36035
UI elements should only be modified on the main thread. There's no point to create a new thread for this. Instead, what you would do is create an inner class that extends Runnable
and do your adjustments in that. Then use View#postDelayed()
method to run every x
milliseconds.
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);
}
}
}
EDIT:
I just noticed you weren't making a custom View. The View#postDelayed()
and removeCallbacks()
methods are public to the View
, so this can easily be adapted to be done outside of Views so you don't have to make a custom View
.
Upvotes: 1
Reputation: 13705
The problem is you are stopping the main thread here:
while(juegoEmpezado) {
try {
Thread.sleep(velocidadDeCrecimiento);
Since this call is running on the main thread you are actually stopping it, and it will not refresh any of your Views, what you can do is something like this:
new Thread(new Runnable() {
@Override
public void run() {
while(true){
empezar();
try{Thread.sleep(1000);}catch(InterruptedException ie){ie.toString();}
}
}
}).start();
It will call empezar (which must use runOnUIThread to update views). This is actually a very dirty way to do it, maybe a Handler would be a better approach to your problem.
Regards!
Upvotes: 2