How to animate an adding of a view in Android? - android

I would like to know if there is a simple way to add a view (a button) to a RelativeLayout, with some kind of scale animation.
I extended a class from Button and did something like this:
public class MyButton extends Button {
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
ScaleAnimation anim = new ScaleAnimation(0,1,0,1);
anim.setDuration(1000);
anim.setFillAfter(true);
this.startAnimation(anim);
}
Then tried to add this button to a view and it didn't work. Please help!

In your activity, use instead:
parentview.addView(myButton);
Then animate the button with this:
Animation animation = AnimationUtils.loadAnimation(getBaseContext(), R.anim.slide_right_in);
animation.setStartOffset(0);
myButton.startAnimation(animation);
This is an example of slide_right_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate android:fromXDelta="100%p" android:toXDelta="0" android:duration="800"/>
</set>
In addition,
This is a activity play animation function I wrote:
public Animation PlayAnim( int viewid, Context Con, int animationid, int StartOffset )
{
View v = findViewById(viewid);
if( v != null )
{
Animation animation = AnimationUtils.loadAnimation(Con, animationid );
animation.setStartOffset(StartOffset);
v.startAnimation(animation);
return animation;
}
return null;
}
You can call this like this:
PlayAnim(R.id.bottombar, (Context) this, R.anim.slide_right_in, 0);
Where:
1st parameter is the id of the view you want to apply the animation on.
2nd paramenter isThe context retrieved inside your activity.
3rd parameter is the desired animation that you put inside your anim resource folder or from android predefined animations.
4rd paremeter is the animation startoffset.

I tested your animated button implementation and it works correctly. There must be some other problem. Probably the way you add the button to the layout.
To add your button to the relative layout use code like this.
RelativeLayout rl = (RelativeLayout)findViewById(R.id.rl);
MyButton b1 = new MyButton(Main.this);
b1.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT,LayoutParams.WRAP_CONTENT));
rl.addView(b1);
Or you can inflate the button from layout. To do this create layout mybtn.xml containing your button implementation:
<?xml version="1.0" encoding="utf-8"?>
<PACKAGE_OF_MYBUTTON_HERE.MyButton
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
To add it to your layout call:
RelativeLayout rl = (RelativeLayout)findViewById(R.id.rl);
Button b = (Button)getLayoutInflater().inflate(R.layout.mybtn, rl, false);
rl.addView(b);
There might be a problem with proper positioning of your view when you add it to the relative layout. Just add code like this before calling rl.addView(b1) (the code snippet adds new button below someOtherView).
LayoutParams lp = new LayoutParams(b.getLayoutParams());
lp.addRule(RelativeLayout.BELOW, someOtherView.getId());
b.setLayoutParams(lp);

You can try adding this to your code just before adding view.I guess this code would work for any view changes. In my case was switching 2 views with animation.
TransitionManager.beginDelayedTransition(layoutlocation);//layoutlocation is parent layout(In my case relative layout) of the view which you gonna add.
Hope it works.Took 2 days for me to make this work.

It's not always necessary to use animation class to get actual animation. We can provide a delay when adding views to layout using handler as shown.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
Animation fadeanimation = new AlphaAnimation(0,1);
fadeanimation.setDuration(position*60+100);
child.setAnimation(fadeanimation);
linearLayout.addView(child);
}
}, position*60);

Related

Setting views dynamically with LayoutParams.addRule setting to the last position of the view

I'm dynamically adding views to a relative layout and programatically defining them. The views can be moved around the screen so their position is changing.
When I try to set a view (button2) to sit below another view (button1), button2 gets placed in the old location of button1 (the default location of where views get added before moved). I've linked images to hopefully convey this better.
This is the Original Layout
Layout after Button2 is re-positioned
I have a background LinkedList keeping track of all view changes and view attributes for the layout if that makes a difference.
Here are the code functions:
How i'm re-positioning Button1:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(positioningLayout);
baseLayout.addView(b);
Repositioning views below another view Code fragment:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.invalidate();
How I'm adding the views to the layout.
uiList.addView(new Buttons(this), "BUTTON");
setDialogView(uiList.getLast());
showDialog(SET_ID);
reloadUI();
setDialogView is just passing the view to the Dialog SET_ID so that I can manually assign an ID to the view (for testing).
reloadUI() just finds the last view added to the background LinkedList and adds it to the relativeLayout using .addView;
If you require more code please let me know. Am I missing a call to update the view layouts after making a change to the relativeLayout child views? It seems like the view is getting re-positioned visually but the actual LayoutParams are not updating so when you set Button2 to Button1 it's getting the old position.
Is there a way to force a relative layout view re-position?
I think you should try simple solution - replace b.invalidate() with b.requestLayout(). For more background check this link. I didn't test it but I hope it will work. So the code should look like:
Buttons b = (Buttons) viewIndex;
positioningLayout = new RelativeLayout.LayoutParams(b.getLayoutParams());
positioningLayout.addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.setLayoutParams(positioningLayout);
b.requestLayout();
Or maybe you can simplify this to:
Buttons b = (Buttons) viewIndex;
((RelativeLayout.LayoutParams) b.getLayoutParams()).addRule(RelativeLayout.BELOW, viewIdFromList.intValue());
b.requestLayout();
You seem to be in the right track but is doing a small mistake. Without more code it is quite difficult to provide the actual solution. But I will try to point out the mistake.
See, to relatively position items programmatically in a RelativeLayout you must assign unique ids to each of them.
Like,
Button b = new Button(this);
b.setId(1);
Button c = new Button(this);
c.setId(2);
Each element should have unique ids.
Now if you want to place the Button b vertically in the center,
layout.addRule(RelativeLayout.CENTER_VERTICAL);
b.setLayoutParams(layout);
Now if you want to place Button c below it,
layout.addRule(RelativeLayout.BELOW, b.getId());
layout.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
b.setLayoutparams(layout);
This will certainly place the button c below button b. As you said you can use a any data structure of your choice to keep track of the ids of each elements.
This is only a detail example on how you move the button correctly. So first, create a unique id for the View, i.e. create a new XML resource file in res/values/, and name it ids.xml:
And the content of ids.xml is:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item name="button_1" type="id"/>
<item name="button_2" type="id"/>
</resources>
We have to set an id to your main layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/layout_main"> <!-- the id -->
<!-- content of this layout -->
</RelativeLayout>
Then, let's create the Buttons:
RelativeLayout relativeLayout = (RelativeLayout) findViewById(R.id.layout_main);
final Button button1 = new Button(this);
button1.setId(R.id.button_1);
button1.setText("BUTTON 1");
button1.setTextColor(Color.BLACK);
final Button button2 = new Button(this);
button2.setId(R.id.button_2);
button2.setText("BUTTON 2");
button2.setTextColor(Color.BLACK);
relativeLayout.addView(button1, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
relativeLayout.addView(button2, new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
RelativeLayout.LayoutParams params1 = (RelativeLayout.LayoutParams) button1.getLayoutParams();
params1.addRule(RelativeLayout.CENTER_IN_PARENT); // set to the center of screen
button1.setLayoutParams(params1);
final RelativeLayout.LayoutParams params2 = (RelativeLayout.LayoutParams) button2.getLayoutParams();
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
button2.setLayoutParams(params2);
button2.setOnClickListener(new View.OnClickListener() {
#SuppressLint("NewApi")
#Override
public void onClick(View v) {
/* We need to remove the existing rules and update it!
* For API 16 and earlier, set the rule to 0, e.g. --> layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
* For API 17 and higher, call layoutParams.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
*/
int api = android.os.Build.VERSION.SDK_INT;
if (api >= Build.VERSION_CODES.JELLY_BEAN_MR1) { // API level 17
params2.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
params2.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
}else if (api < Build.VERSION_CODES.JELLY_BEAN_MR1) {
params2.addRule(RelativeLayout.ALIGN_PARENT_TOP, 0);
params2.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
}
params2.addRule(RelativeLayout.CENTER_IN_PARENT);
params2.addRule(RelativeLayout.BELOW, R.id.button_1); // place below button1
button2.setLayoutParams(params2);
}
});
So once you click on button2, it will move to below button1.

Hiding and showing multiple views using the same animation

I want to apply an animation for multiple views at the same time, how can I apply said animation to several types of views (buttons, imageviews, and other views)?
If what you want is to apply an animation on several views at the same time, simply call the startAnimation method on those views one after the other. They will be simultaneous
//Get your views
View view1 = findViewById(R.id.view1);
View view2 = findViewById(R.id.view2);
View view3 = findViewById(R.id.view3);
//Get your animation
Animation youranimation = AnimationUtils.loadAnimation(this, R.anim.animationid);
//Start animations
view1.startAnimation(youranimation);
view2.startAnimation(youranimation);
view3.startAnimation(youranimation);
Or if you have a lot of views:
Animation youranimation = AnimationUtils.loadAnimation(this, R.anim.animationid);
int[] viewIds = new int[]{R.id.view1,R.id.view2,R.id.view3,R.id.view4};
for(int id : viewIds) findViewById(id).startAnimation(youranimation);
That is, assuming you want to animate several views at the same time, if what your're doing is one after the other we would dive into animation listeners and that's another story
You may use object animators.
There is an easy example in that link which you can also use.
You may also use this tutorial.
Use ValueAnimator instead, and set views property in onAnimationUpdate.
mShowAnimator = ValueAnimator.ofFloat(0f, 1f);
mShowAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
for (View v : mTargetViews) {
v.setAlpha((Float)animation.getAnimatedValue());
}
}
});
You can create one large AnimatorSet() that includes several ObjectAnimators. This allows you to play all animations at the same time with no delay. See my answer here.

Android Transitions (API 19) - How to setText() on TextView before transition?

I am animating a TextView using android's API19 transitions. I defined a scene that i wish to transition to:
scene = Scene.getSceneForLayout(rootLayout, R.layout.my_scene, this);
I defined my transition:
myTransition = new ChangeBounds();
myTransition.setDuration(1000);
myTransition.setInterpolator(new BounceInterpolator());
And I begin transition:
TransitionManager.go(scene, myTransition);
Everything works as long as I have the android:text hardcoded. Here is what my_scene.xml looks like:
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<TextView
android:id="#+id/textview1"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="text1"/>
</merge>
An identical TextView with the same id is in activity_main.xml, but in a different position.
When I try to set the text dynamically using setText() it will not change the text. I am not very experienced with this transition API so any help is appreciated.
Define the scene enter action and then call the go() method in TransitionManager. Here is the code snippet
scene = Scene.getSceneForLayout(rootLayout, R.layout.my_scene, this); scene.setEnterAction(new Runnable() {
#Override
public void run() {
TextView textView1 = (TextView)rootLayout.findViewById(R.id.textView1);
textView1.setText("Hello World");
}
}); TransitionManager.go(scene, myTransition);
What if you try to delay the transition via the TextView's event queue?
final Scene scene = Scene.getSceneForLayout(rootLayout, R.layout.my_scene, this);
final ChangeBounds myTransition = new ChangeBounds();
myTransition.setDuration(1000);
myTransition.setInterpolator(new BounceInterpolator());
TextView tv;
tv.setText("Some text");
tv.post(new Runnable() {
#Override
public void run() {
TransitionManager.go(scene, myTransition);
}
});
You may try having an initial scene by initializing a Scene variable scene one and using enter() to set the initial scene.
Then, you can transition from scene1 to scene2, your target scene. Above that, I've also noticed some lag during the change of text from scene1 to scene2. In order to counteract that, I utilized the TransitionListener class to detect when the scene was finished transitioning. Then, I altered the text using setText() after the transition.

Trying to Move a Button to Another Point on the Screen

I am trying to move 3 buttons relative to their starting points:
The code for starting the animation is:
protected void showMoreBtns() {
Button btn1 = (Button)this.findViewById( R.id.more1btn );
Button btn2 = (Button)this.findViewById( R.id.more2btn );
Button btn3 = (Button)this.findViewById( R.id.more3btn );
Animation showMore = AnimationUtils.loadAnimation( this, R.anim.optionsinup1 );
btn1.startAnimation( showMore );
showMore = AnimationUtils.loadAnimation( this, R.anim.optionsinup2 );
btn2.startAnimation( showMore );
showMore = AnimationUtils.loadAnimation( this, R.anim.optioninup3 );
btn3.startAnimation( showMore );
}
And the animation is defined as:
<?xml version="1.0" encoding="utf-8"?>
<set
xmlns:android="http://schemas.android.com/apk/res/android" >
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="-60"
android:toYDelta="-30" />
</set>
All three animations follow the same format, with only the android:toDelta's being modified.
The issues is the animation runs, yet the buttons return to their original position at the end of the animation. I would like them to stay at the end point.
showMore.setFillAfter(true);
This will be placed in your java code.
I hope it will be work.If you want to use the button after complete animation you will placed onAnimationEnd(Animation animation) in that place the button using your layout.
You need two sets of buttons, and after the animation is played you have to make one set disappear, probably using View.setVisibility(View.GONE) on its parent or on each Button.
Not sure if this will help you but i was struck with the same problem i was able to do this using these methods,
setTranslationX(float)
setTranslationY(float)
you can use it Like this
Button button = (button) findViewById(your id);
button.setTranslationX(a float value);
here's the android documentation that provide more information
http://developer.android.com/reference/android/view/View.html#attr_android:translationX
also note that the minimum level of android SDK required is 11

Move an ImageButton after onClick event

I have an imageButton inside a RelativeLayaut.
My imageButton is 300x350px and positioned outside the screen (on top) -300px onClick the button go down 300px and go back to the initial position when click again. The effect is like a popup window.
I could obtain this working code.
XML
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="#drawable/pag1" android:id="#+id/relativeLayout1"
android:drawingCacheQuality="high" android:layout_width="1024px"
android:layout_height="600px">
<ImageButton android:id="#+id/imageButton8"
android:layout_width="300px"
android:layout_height="350px"
android:layout_marginLeft="720px"
android:background="#drawable/popup"
android:layout_marginTop="-300px">
</ImageButton>
</RelativeLayout>
CODE
import android.widget.RelativeLayout.LayoutParams;
...
//activity declarations
protected static final int WIDTH = 300;
protected static final int HEIGHT = 350;
int count=0;
...
///click
final ImageButton pop=(ImageButton) findViewById (R.id.imageButton8);
pop.setOnClickListener(new OnClickListener(){
public void onClick(View v) {
count++;
if (count==1){
LayoutParams lp = new LayoutParams(WIDTH,HEIGHT);
lp.setMargins(720, -20, 4, 0);
pop.setLayoutParams(lp);
}
else{
LayoutParams lp = new LayoutParams(WIDTH,HEIGHT);
lp.setMargins(720, -300, 4, 0);
pop.setLayoutParams(lp);
count=0;
}
}
});
NOW I wont to add a smooth transition to the final position. I think in a FOR cycle using a sleep function. Your HELP is welcome
I think you should start with deciding which platform you are targeting as there is a new animation framework in Honeycomb. Have a look at this article.
If however you are targeting pre-3.0 versions then the simplest way is to define your animation in anim.xml and load it in your activity by using android.view.animation.AnimationUtils. Then once you've set your new layout params on the view, simply call public void startAnimation (Animation animation) on the view and it will animate it for you. Two lines in Java and a few more in XML.
Take a look at Animation Resources too.

Categories

Resources