I guess this is pretty simple question but somehow I cannot figure it out.
I am animating couple of .png file from drawable folder, it is working fine as they are animated and stopped as required. What I am trying from previous three hours is that I want to hide the imageview once the animation is stopped. This is the simple code i am using
animImageView = (ImageView) findViewById(R.id.iv_animation);
animImageView.setBackgroundResource(R.drawable.anim);
animImageView.post(new Runnable() {
#Override
public void run() {
visiblity = false;
frameAnimation =
(AnimationDrawable) animImageView.getBackground();
frameAnimation.start();
frameAnimation.setOneShot(true);
//animImageView.setVisibility(View.INVISIBLE);
}
});
Even tried the removeCallBack() methods on imageview but its not working. Can somebody please guide me what I am doing wrong or what I need to do to overcome this.
Thanks.
There is no finish listener for AnimationDrawable. Try this approach, https://stackoverflow.com/a/15856260/1972597
What you can do is after your animation is over, just call
iv.setVisibility(View.GONE);
there is an animation listener availale. So you can use it for Animation Utils
Related
I am new to Android development. I am currently building an application that must flash different colors when a button is clicked. When the button is clicked I call a function. This function loops through a list of items and basically at the moment attempts to show blue and green after each other a couple of times. Problem is that it only shows the last color. And this only happens when the thread has exited the method. In the example below it is blue. I have noticed with some of the work I have done that screen changes reflects once the program have left the current method where the loop occurs and sometimes even longer after that. Below is the code :
//Method that sets the color
public void SetVisualLayoutColor(int Color)
{
linearLayout.setBackgroundColor(Color);
linearLayout.invalidate();
linearLayout.refreshDrawableState();
}
//Method that loops and calls above method to set color
public boolean ShowRepititive()
{
boolean successfull = false;
try
{
boolean isGreen = true;
//for (TimingItem timingItem : items) {
for (int i=0;i<=10;i++) {
if (isGreen) {
SetVisualLayoutColor(Color.BLUE);
isGreen = false;
} else
{
SetVisualLayoutColor(Color.BLUE);
isGreen = true;
}
}
successfull = true;
} catch (Exception e)
{
Log.e("Repeating Flash", "showFlashRepititive: ", e);
successfull = false;
}
return successfull;
}
Is there some way to get past this or to force the changes to occur timeously ?
Thank you in advance.
Unless you explicitly run your code on a different thread, the code you write in an Activity, Fragment, or View will run on the UI thread.
When you are performing work on the UI thread, the UI cannot update. The UI only updates after your code has finished executing. Thus your for loop blocks any UI updates until it completes, showing the last color you set.
A more appropriate pattern to use would be to use an animation to change the color
Here is an example of a very basic animation that does a cross-fade between two background colors:
ObjectAnimator.ofObject(view, "backgroundColor", new ArgbEvaluator(), 0xFF0000, 0x00FF00)
.start();
Obviously this won't achieve the flashing effect you are looking for, but you can define your own animations in a similar manner to achieve the desired effect.
As Tanis.7x said, you can't create the desired animation while your code is executed in the main thread. All potential solutions have to have a background Thread and a way for it to communicate with your UI thread. (see AsyncTasks,Threads,Handlers)
An alternative to ObjectAnimator that can work in your specific case is TransitionDrawable. It's not that powerful but if it suits your needs, it's preferable since it's API 1 compatible:
You need to store a transitioncolors.xml in your drawables folder with your transition definition:
<?xml version="1.0" encoding="UTF-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#color/green"/>
<item android:drawable="#color/blue"/>
</transition>
and then call:
ImageView view = (ImageView) findViewById(R.id.transitionId);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
TransitionDrawable transition = (TransitionDrawable) v.getBackground();
transition.startTransition(3000);
});
where R.id.transitionId is:
<ImageView
android:id="#+id/transitionId"
android:background="#drawable/transitioncolors"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
I did some more research after I read Tanis.7x and Sevle's post, which put me in the right direction. For some reason the Object animator did not worked when I ran it and the Transition does not give me the flexibility I wanted. So I came across the ValueAnimator, which worked perfectly for me. I created my own class that extended the ValueAnimator and within the class I control how long each animation must be and also other aspects like running indefinitely until the user interrupts it on the screen. Thanks a lot guys, I really appreciate the help.
I have a view that contains a user's drawing. When clicking a 'play' button I want to have a loop that draws the image from start to finish.
In attempting to do this I basically have a loop inside of an onClickListener for the play button that essentially invalidates the view, waits, sets the next set of points and invalidates again.
The problem is that the image doesn't actually redraw until after the entire image is draw. So essentially nothing happens and then it's all of a sudden done. After doing some research, my assumption is that invalidate is telling the main UI thread to redraw when it gets time, but it's already hung up on dealing with the listener, so it doesn't actually draw until the loop is finished. I've tried calling onDraw directly, using postInvalidate, and just about any other ridiculous thing I can think of, but I'm not sure how to get this to work.
Here are some code snippets:
In my PaintActivity(Which has a PaintAreaView)
The scrubber indicates the progress of the drawing. The first to lines in onProgressChanged works when I manually use the seek bar, but not when pressing play, which is why I tried adding all the extras.
_scrubber.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
#Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
_paintAreaView.setPointsToDraw(_scrubber.getProgress());
_paintAreaView.invalidate();
_mainViewGroup.invalidate();
_paintAreaView.postInvalidate();
_mainViewGroup.postInvalidate();
_paintAreaView.drawPoints(_paintAreaView.getCanvas());
_paintAreaView.invalidate();
}...
My Play Button stuff:
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
playDrawing();
...
}
});
private void playDrawing()
{
int endPoint = getPaintPointCount();
while(_scrubber.getProgress() < endPoint)
{
_scrubber.incrementProgressBy(1);
try{
Thread.sleep(10);
}catch(InterruptedException e)
{
Thread.currentThread().interrupt();
}
//_paintAreaView.setPointsToDraw(_scrubber.getProgress());
//_paintAreaView.invalidate();
//_mainViewGroup.invalidate();
if(_isPaused)
break;
}
}
I'm not a huge fan of using that sleep, but I've struggled with other solutions and that's my next thing to research. But for this question, incrementing the progress bar does successfully call onProgressChanged, but again it just isn't drawing the view until it's out of that play button click listener.
If I have to wait until I'm out of the listener to get this to work, I'm new enough that I'm not sure how I would approach that.
Sorry for my bad code, any help is much appreciated to help me understand what's happening here and what I need to understand to get this to work.
Thank you!
I got it to work, I'm not sure if all I did was necessary, but here are the changes I made based on my Main UI thread theory being the problem.
I created a class Thread member variable:
private Thread _drawThread;
In onCreate():
_drawThread = new Thread(){
public void run(){
playDrawing();
}
};
play Button onClick:
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
...
_drawThread.start();
}
});
Seems to be doing just what I want! Except the app crashes the second time I hit play :) From here I don't think it'll be to bad to figure out that issue though.
EDIT-----
Creating the Thread in my play button onClickListener instead of having it be a member variable fixed the crashing. I incorrectly assumed the thread would be destroyed as soon as the listener went out of scope on the main thread, but I guess that's not the case.
I have a simple sample for TransitionDrawable, when I click on ImageView one picture goes to second picture. But how on next click go back from second picture to one?
image.setImageDrawable(mTransition);
mTransition.startTransition(1000);
Just an idea,it may work for you.
take another transition animation xml file and reverse the images
take a vriable
int v=2;
and inside onClick,
public void onClick(){
if(v%2==0){
image.setImageDrawable(mTransition1);
mTransition1.startTransition(1000);
v++;
}
else{
image.setImageDrawable(mTransition2);
mTransition2.startTransition(1000);
v++;
}
}
Im working on changing the image being shown when I have my ImageView Clicked. Im trying to use a similar code that I used for accomplishing this with a TextView but I can't seem to find the right terms to get it to work. Here is my current code. Thanks
electronconfiguration.setOnClickListener(new View.OnClickListener() {
public void onClick(View drawable) {
if (drawable.equals(R.drawable.element_el))
electronconfiguration.setImageDrawable(R.drawable.aluminum_el);
else if (drawable.equals(R.drawable.aluminum_el))
electronconfiguration.setImageDrawable(R.drawable.element_el);
}
});
Why don't you use a ViewSwitcher, it's designed to switch between two views
drawable probably doesn't equal R.drawable.element_el. R.drawable.element_el is probably some random implementation of the image. Try drawable.getId().equals(R.drawable.element_el). I've never tried this so I have no idea
I have a strange issue - from time to time the animation that should fade out my control (ImageButton) does not kick in immediately. I am using the fadeout animation to hide it and then in myListener on its end (onAnimationEnd) I put new resource as the image on the button.
Somewhere in my app code:
Animation a = AnimationUtils.loadAnimation(this,R.anim.fadeout);
a.setAnimationListener(new myListener(location));
buttons[location].setAnimation(a);
a.startNow(); // regardless if its start() or startnNow()
// it will work in most of the cases but not 100% reliable
// I actually can see in debug Log when its late, happens after few more clicks
Then in myListener.onAnimationEnd(Animation a):
buttons[location].setImageResource(R.drawable.standard_button);
Seems there is a rule that the every 4th or 5th animation does not start ...
Thanks for help!
adding
buttons[location].invalidate();
after
a.startNow();
has fixed my issue.
You can also use
buttons[location].startAnimation(a);