Set Handler Postdelayed on Imageview dynamically - java

I am creating like a Whack a Molee type of game, and I am creating imageviews at random positions on the screen.
The thing is, I am adding a postdelayed to a var I am creating every two seconds ( the var is the imageview) but it only acts to the last imageview created. It happens because every two seconds that var is replaced with a new instance of imageview.
How can I add an independent postdelayed or something that detects when 2 seconds has passed and removing that specific imageview.
Thanks!
mv = new ImageView(this);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
mv.setVisibility(View.GONE);
}
}, 2000);
I tried this, but only removes the very last imageview.

public void createImage() {
final ImageView mv = new ImageView(this);
// Do all your positioning and sizing (layout params) setting stuff here
new Handler(getMainLooper()).postDelayed(new Runnable() {
#Override
public void run() {
mv.setVisibility(View.GONE);
}
}, 2000);
}
Simply don't override the value every time, by using a local varaible inside a method.
This way the mv instance will be the same in the runnable which is executed by the handler.
(And also don't create a handler every time)
(You could also draw the entire thing on a canvas)

Related

LinearLayout.getwidth is zero when outside Runnable

I tried to get the width of a LinearLayout.
Here is the code of the MainActivity.java:
public class MainActivity extends AppCompatActivity {
BoardClass board;
private int widthareagame;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final LinearLayout gamearea;
ImageView im1 ;
Button abutton;
abutton = (Button) findViewById(R.id.buttonnew);
gamearea = ( LinearLayout) findViewById(R.id.boardarea);
gamearea.post(new Runnable(){
public void run(){
widthareagame = gamearea.getWidth();
}
});
board = new BoardClass(this,widthareagame);
gamearea.addView(board);
}
The value of widthareagame at new BoardClass(this,widthareagame); is still Zero.
Thanks
Here is what documentation says about View#post():
Causes the Runnable to be added to the message queue. The runnable
will be run on the user interface thread.
Your task, of modifying the value of widthareagame variable, has been pushed to the message queue of the view. It doesn't guarantee that it will get executed at the very same instance. The control then proceeds to the next line, where you still get the unmodified value.
You can try something like this, to ensure that you are able to use the modified value:
gamearea.post(new Runnable(){
public void run(){
widthareagame = gamearea.getWidth();
board = new BoardClass(this,widthareagame);
gamearea.addView(board);
}
});
This is because post method call queued the setting of widthareagame where as your view is rendering.You didn't guarantee the order of execution.
You have to make sure the statements inside the run method execute first and then new Board(.. is invoked.For that you can do something like this
final AtomicBoolean done = new AtomicBoolean(false);
run(){
//inside run method
done.set(true);
notify();
}
then do something like this
synchronized(task) {
while(!done.get()) {
task.wait();
}
new Board(..
}
where task is your runnable task defined something like this
final Runnable task = new Runnable() {
#Override
public void run() {
The reason is zero is because within the onCreate the LinearLayout has not been measured yet.
And the reason it only works when within the Runnable is because since this one has been posted then it will run on the next execution cycle, which is after the onCreate and the rest of the Activity lifecycle methods (onStart, onResume, etc.) and even onAttachedToWindow have been called, at which point will be already measured and give the correct size.
Said all that, a safer way to get your layout metrics with certainty would be to listen when the layout state changes.
gamearea.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Remove the listener here unless you want to get this callback for
// "every" layout pass, which can get you into an infinite loop if you
// modify the layout from within this method
gamearea.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// A this point you can get the width and height
widthareagame = gamearea.getWidth();
}
});

Move code into my RecyclerAdapter to prevent NPE

I have this piece of code inside my MainActivity , what I'm trying to do is to tint a background for an element, it works nice, but the handler is not supposed to do the job of waiting when the views are all inflated, so, I want to move this code inside my onBindViewHolder but Im kinda lost, any hint ?
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
for (int i = 0; i < mArrayListSelectedTAGS.size(); i++) {
View view = mRecyclerView.getLayoutManager().findViewByPosition(mArrayListaTAGs.indexOf(mArrayListSelectedTAGS.get(i)));
view.setBackgroundColor(getApplicationContext().getResources().getColor(R.color.colorVincular));
}
}
}, 500);
Te question is, how do I get the exact view on my onBindView holder in order to tint it, and how to call it from MainActivity
thanks
For those having the same issue , I just solved this with a simple Interface, in my onBindViewHolder, after I bind all my views, I call an interface named onBindFinished(boolean isFinished);
after that in my adapter I just set that value to true if the onBind have finished
and in my class the only thing I do is checking if onBindFinished is true I just paint the views.

Configure Back Button to Skip First View

I have an app with a title screen. When the app first starts, I have an onCreate method that contains the following code:
setContentView(R.layout.title_screen);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main_screen);
}
}, 2000);
When I run my app and press the back button while on the main_screen layout, it closes the app (as it should). However, when I reopen the app, it displays the title_screen layout for two seconds again even though the app is already running. How can I prevent this?
This will prevent the delay appearing again when resumed:
private static boolean flag = false;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(!flag){
setContentView(R.layout.title_screen);
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
setContentView(R.layout.main_screen);
}
}, 2000);
flag = true;
} else {
setContentView(R.layout.main_screen);
}
}
Btw, if your app was on background and it is calling onCreate again while being resumed, it means that it is killed by the OS. Therefore it is normal to have the initial delay again.
What I would do is to implement two different activities first one showing title_screen and the second which is started after 2s should show your main screen.
After looking at your code I can see that you ALWAYS start with title_screen then after 2s, you change to main_screen. Therefore, when you press back, that means you finish your activity. When you re-open your app, onCreated is called again, and it run every line of code as the previous opening.Of course, there's no difference in 2 times you open your app. To overcome it, I recommend to use SharedPreference to store the flag to check main_screen or title_screen.

How to perform an action after button click

I need to perform an action after onClick method of OnClickListener has run.
Here is my code for onClickListener:
View.OnClickListener imgButton0Handler0 = new View.OnClickListener() {
int identifier=0;
public void onClick(View v) {
//check if tile is found and return if it is
if(isFound[identifier]==true) return;
//set tile as open
checkField[identifier]=1;
//set background on predetermined
button0.setBackgroundResource(tiles[identifier]);
}
};
After this has run, and the background is set I would like to call a method checker(int identifier) which will check for other open tiles and change backgrounds accordingly.
This method needs to be run separately because the background is only displayed after onClick finishes, and I need predetermined background shown for a short time before checker method changes it to something else.
How can I accomplish this?
Have You Tried Post Delayed see this,
View.OnClickListener imgButton0Handler0 = new View.OnClickListener() {
int identifier=0;
public void onClick(View v) {
//check if tile is found and return if it is
if(isFound[identifier]==true) return;
//set tile as open
checkField[identifier]=1;
//set background on predetermined
button0.setBackgroundResource(tiles[identifier]);
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
// This method will be executed once the timer is over
// Start your app main activity
checker(identifier) // your method call
}
}, 3000); // 3 second
}
};

Make ImageView visible for set amount of time

I have an onClick method set in the xml layout file that triggers the vibration of the phone for 100ms at this point I have the ImageView Visibility set to visible so it can be seen. I want the ImageView to be set back to gone again when the vibration has stopped. How do I go about this?
You can start this method at the same time:
public void timerDelayRemoveView(float time, final ImageView v) {
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
v.setVisibility(View.GONE);
}
}, time);
}

Categories