Using a layoutanimation on one of my views.
android:layoutAnimation="#anim/animate_layout"
The animation is done each time one enters that view. It will however not run if that view was already active and the user changed to another application and then returned to it. In order to do that, I need to overwrite the onresume() method and call it from there.
How can I call the layoutAnimation from within the code in order to run it again for the whole layout?
Another option, besides what Pentium10 suggested, would be trying to do this:
Animation animation = AnimationUtils.loadAnimation(ctx, android.R.anim.fade_out);
target.startAnimation(animation);
Where ctx could be something like YourActivity.this, and target is the View you want to animate.
Look into LayoutAnimationController and start()
I'm also trying to get my animation to start over when the user gets to se the layout again. I get force close with this code implemented.
public void onResume(){
super.onResume();
View layout = findViewById(R.layout.main);
Animation animation = AnimationUtils.loadAnimation(CrookTranslate.this, R.anim.fade_from_left);
layout.startAnimation(animation);
}
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:animation="#anim/from_left"
android:id="#+id/fade_from_left"
android:delay="3.0"
/>
enter code here
Related
Currently I have a GridView that holds some ImageViews. The GridView implements setOnItemClickListener. When the onItemClick occurs, the user gets a dialog and on back pressed or on dismiss, he returns to the current GridView.
Till now everything works fine.
I would like to know if there is a way to change the selected imageView (with another image, or even just the alpha).
I have tried inside the setOnItemClickListener to change the image, but when I try to change it back to it's normal image after the dialog.dismiss() call, a white screen pops up for some milliseconds. Although, the image is set correctly, I would like to avoid this white image.
I have tried to implement the GridView.setOnTouchListener, but I would get only a white screen (for some milliseconds) and no other operation would be executed (no pop up dialog).
I even tried to implement OnTouchListener inside the ViewHolder class and although it seemed to work with some problems (changing the alpha on ACTION_DOWN was permanent, so I had to reselect the same item to change the alpha back to normal), the setOnItemClickListener wouldn't work at all.
Can someone help me with this?
Thanks in advance!
Just for anyone having the same problem, I used TransitionDrawable. Inside my imageAdapter, I loaded the transition xml files:
<?xml version="1.0" encoding="utf-8"?>
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/soft"/>
<item android:drawable="#drawable/soft_pressed"/>
</transition>
and on gridview.setOnItemClickListener, I used this sample of code:
ViewHolder holder = (ViewHolder) v.getTag();
final ImageView imageview = holder.image;
((TransitionDrawable)imageview.getDrawable()).startTransition(2000);
And to execute the next command (some delay is needed):
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
YourMethod(...);
//reverse the transition
((TransitionDrawable)imageview.getDrawable()).reverseTransition(2000);
}
}, 2000);
I have a very strange problem with Android animations, I tried many different approaches and components, and still couldn't find any explanation.
I have a FrameLayout which is a container for views, and a Button.
This FrameLayout should display only one view at a time, and when I click on the Button, I want the FrameLayout to display another view, and start an animation on the view that is removed from the FrameLayout.
The specificity here is that I only use two views, and I want to switch between these two views.
The problem:
When I click the button multiple times really fast, and then stop clicking, the two views are shown at the same time one on top off the other, and won't disappear. The container still contains only one view though... definitely strange!
error screenshot http://i.minus.com/jDXyvUsE1LCOx.png
I was able to reproduce this with a simple example:
public class TestAnimActivity extends Activity implements OnClickListener {
private FrameLayout container;
private TextView current;
private TextView next;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
current = new TextView(this);
current.setText("View 1 YEAH");
next = new TextView(this);
next.setText(" View 2 DOH");
container = (FrameLayout) findViewById(R.id.container);
container.addView(current);
findViewById(R.id.button).setOnClickListener(this);
}
public void onClick(View v) {
Animation outAnimation = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
current.startAnimation(outAnimation);
container.addView(next);
container.removeView(current);
TextView temp = current;
current = next;
next = temp;
}
}
As you can see the animations are being started on the views while previous ones are still running, and the way I do that may somehow be the source of the problem.
If I comment the animation related code, it works perfectly:
// Animation outAnimation = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
// current.startAnimation(outAnimation);
If I stop reusing views and create new views instead, it also works perfectly:
// next = temp;
next = new TextView(this);
next.setText("View: " + new Random().nextInt());
But I don't want to create new views :-) .
It seems that the problem is related to starting animations several times on a view while adding / removing this view from its parent.
I first tried with a ViewFlipper, then a ViewAnimator, then looked up the Android source code and ended up doing this manually to reproduce the problem.
If you want the layout to be able to test by yourself, here is my main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/container"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<Button
android:id="#+id/button"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Click me fast" />
</LinearLayout>
Thank you for your time!
I finally found a way to fix the issue.
When we remove a view from a ViewGroup, if there is an animation running on this view, it is automatically added to the "disappearing children" list of the ViewGroup.
The issue seemed to appear when we tried to add to the ViewGroup a view that has been removed from it but was still in its disappearing children.
There's an easy way to fix that : viewGroup.clearDisappearingChildren();
Here would be the new implementation of the onClick() method :
public void onClick(View v) {
next.clearAnimation();
container.clearDisappearingChildren();
Animation outAnimation = AnimationUtils.loadAnimation(this, android.R.anim.fade_out);
current.startAnimation(outAnimation);
container.addView(next);
container.removeView(current);
TextView temp = current;
current = next;
next = temp;
}
If it works without quickly pressing the button, and works without the animation then you may be seeing how animations actually work. From my understanding what is displayed in the animation is separate from the View objects they are animating. You can try animating from the parent view instead of the ones that keep being added and removed. Or make sure to clean up the animation before removing the view, as it sounds like the view isn't able to get the onAnimationEnd method where it can remove the phantom image being displayed (setFillAfter(false) which is the default behavior of an Animation).
I am facing problem in getting a sequence of animation on a particular view.
I used animationset in my code and i have set the offset for each animation and the duration for the animation correctly.
somebody pls help with this.
Thanks...
To play back animations sequentially, just use the set the android:ordering property of the <set> tag to have the value "sequentially".
Then, all set items will be animated in their sequence of declaration.
For page transition use the below snippet
pageTransition(Context context, View view){
Animation mAnim = AnimationUtils.loadAnimation(context, R.anim.slide_top_to_bottom);
mAnim.setRepeatMode(Animation.ABSOLUTE);
view.startAnimation(mAnim);
}
refer the below link for more details deVogella
Suppose I have 2 XML files and my activity will setContentView the appropriate one based on some button press from the user. Is it possible to change the transition animation for the changing of content view?
So far I see super.overridePendingTransition() which is suitable for starting new activities, however my example does not start a new activity, it just changes the layout in the current one.
Mathias Lin has explained it very well.
You can always use default stock animations supplied by Android framework.
Heres an example code:
boolean isFirstXml=evaluatingConditionFunction();
LayoutInflater inflator=getLayoutInflater();
View view=inflator.inflate(isFirstXml?R.layout.myfirstxml:R.layout.myseconxml, null, false);
view.startAnimation(AnimationUtils.loadAnimation(this, android.R.anim.slide_out_right));
setContentView(view);
Call this from any of your activity which holds your Parent View.
For custom animations you can visit developer docs. Heres the documentation link.
Yes, you can apply an animation on almost any view you like. Just via view.startAnimation(animation);
Take the outer viewgroup of your respective layout (content view) and apply the animation to it. Depending what kind of animation you want to do, it might make sense to inflate/load both layouts but hide one of them and then swap. Please specify what kind of transition you have in mind.
For example: if you do an alpha transition, you would run the alphaAnimation on the current layout, when when the animation ends (AnimationListener), you set the content view to the new layout, and fade the content back in, via another alphaAnimation.
A better solution is using ViewFlipper: it is a FrameLayout, that can do animations when changing the views.
<ViewFlipper
android:id="#+id/[your_id_here]"
android:inAnimation="..."
android:outAnimation="..."
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<RelativeLayout
<!--Your first layout -->
</RelativeLayout>
<RelativeLayout
<!--Your second layout -->
</RelativeLayout>
</ViewFlipper>
Then, switch the views with setDisplayedChild(int) or showNext() or showPrevious. If you want to have different animation for left and right movement, you have to set inAnimation and outAnimation in the code before transition.
More complete example is here.
I am using a custom title view in my application for each activity. In one of the activities, based on button clicks I need to change the custom title view. Now this works fine every time when I make a call to setFeatureInt.
But if I try to update any items in the custom title (say change the text of a button or a text view on the title), the update does not take place.
Debugging through the code shows that the text view and button instances are not null and I can also see the custom title bar. But the text on the text view or the button is not updated. Has anyone else faced this problem?
How do I resolve it?
Thanks.
EDIT
Here's what I tried. Does not get updated even on calling postInvalidate.
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.text_title);
TextView databar = (TextView) findViewById(R.id.title_text);
databar.setText("Some Text");
databar.postInvalidate();
Button leftButton = (Button) findViewById(R.id.left_btn);
leftButton.setOnClickListener(mLeftListener);
leftButton.setText("Left Btn");
leftButton.postInvalidate();
Button rightBtn = (Button) findViewById(R.id.right_btn);
rightBtn.setOnClickListener(mRightListener);
rightBtn.postInvalidate();
The problem is that the only Window implementation (PhoneWindow) uses a LayoutInflater in its setFeatureInt method and instantiates the new layout with inflate and attachToRoot=true. Consequently, when you call setFeatureInt, the new layouts are not replaced but attached to the internal title container and thus drawn on top of each other.
You can workaround this by using the following helper method instead of setFeatureInt. The helper simply removes all views from the internal title container before the new custom title feature is set:
private void setCustomTitleFeatureInt(int value) {
try {
// retrieve value for com.android.internal.R.id.title_container(=0x1020149)
int titleContainerId = (Integer) Class.forName(
"com.android.internal.R$id").getField("title_container").get(null);
// remove all views from titleContainer
((ViewGroup) getWindow().findViewById(titleContainerId)).removeAllViews();
// add new custom title view
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, value);
} catch(Exception ex) {
// whatever you want to do here..
}
}
I'm not sure whether the current setFeatureInt behaviour is intended, but it is certainly not documented one way or the other which is why I'll take this to the android devs ;)
EDIT
As pointed out in the comments, the aforementioned workaround is not ideal. Instead of relying on the com.android.internal.R.id.title_container constant you could simply hide the old custom title whenever you set a new one.
Let's assume you have two custom title layouts:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/custom_title_1" ...
and
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/custom_title_2" ...
and you want to replace custom_title_1 with custom_title_2, you could hide former and use setFeatureInt to add the latter:
findViewById(R.id.custom_title_1).setVisibility(View.GONE);
getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.custom_title_2);
The correct way to do this is as follows:
requestWindowFeature( Window.FEATURE_CUSTOM_TITLE );
setContentView( R.layout.my_layout );
getWindow().setFeatureInt( Window.FEATURE_CUSTOM_TITLE, R.layout.my_custom_title );
super.onCreate( savedInstanceState );
Please note that the order of these statements is very important.
If you call super.onCreate() before any of the other statements you will get a blank title bar, which the hack of finding the title bar id and removing all the Views from it will fix but is not recommended.
Are you calling invalidate or postInvalidate to redraw the view after updating the text? If it's a custom View, can you put a breakpoint in the draw code to make sure it's getting called?
If you're on the UI thread, you can call 'invalidate' if you're not, you must call 'postInvalidate' or the view won't redraw itself.
Just my 2c worth:
When working in a MapActivity, requesting a custom title resulted in no title at all being shown.
Luckily, all I wanted to do was to set the title text differently, and I soon realized that just calling setTitle() inside of onCreate() worked for me (I called it after I called setContentView())
Sorry, but I don't have time right now to debug this any more and figure out why what I was doing didn't work, and why changing it made it work. As I said, just thought this might help someone out down the road.