I have two LinearLayout views that contain a number of edit texts and checkboxes for entering user information (name, email address etc). When a validation fails on one of these fields a gone textview is displayed showing the validation error.
I have enclosed the two layouts within a ViewSwitcher and I animate between the two views using the ObjectAnimator class. (Since the code needs to support older versions of Android I am actually using the nineoldandroids backwards compatibility library for this).
The bulk of the work is performed in my switchToChild method.
If I flip the views more than twice then I start to run into strange errors.
Firstly although the correct child view of the view animator is displayed it seems that the other view has focus and I can click on the views beneath the current one. I resolved this issue by adding a viewSwitcher.bringChildToFront at the end of the first animation.
When I do this however and perform a validation on the 2nd view the "gone" view that I have now set to visible is not displayed (as if the linearlayout is never being re-measured). Here is a subset of the XML file:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/TitleBar"
android:scrollbarAlwaysDrawVerticalTrack="true"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="vertical" >
<ViewSwitcher
android:id="#+id/switcher"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/page_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- Lots of subviews here -->
<LinearLayout
android:id="#+id/page_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
And this is the main method for flipping between the views:
private void switchToChild(final int child) {
final ViewSwitcher viewSwitcher = (ViewSwitcher) findViewById(R.id.switcher);
if (viewSwitcher.getDisplayedChild() != child) {
final Interpolator accelerator = new AccelerateInterpolator();
final Interpolator decelerator = new DecelerateInterpolator();
final View visibleView;
final View invisibleView;
switch (child) {
case 0:
visibleView = findViewById(R.id.page_2);
invisibleView = findViewById(R.id.page_1);
findViewById(R.id.next).setVisibility(View.VISIBLE);
findViewById(R.id.back).setVisibility(View.GONE);
break;
case 1:
default:
visibleView = findViewById(R.id.page_1);
invisibleView = findViewById(R.id.page_2);
findViewById(R.id.back).setVisibility(View.VISIBLE);
findViewById(R.id.next).setVisibility(View.GONE);
break;
}
final ObjectAnimator visToInvis = ObjectAnimator.ofFloat(visibleView, "rotationY", 0f, 90f).setDuration(250);
visToInvis.setInterpolator(accelerator);
final ObjectAnimator invisToVis = ObjectAnimator.ofFloat(invisibleView, "rotationY", -90f, 0f).setDuration(250);
invisToVis.setInterpolator(decelerator);
visToInvis.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator anim) {
viewSwitcher.showNext();
invisToVis.start();
viewSwitcher.bringChildToFront(invisibleView); // If I don't do this the old view can have focus
}
});
visToInvis.start();
}
}
Does anyone have any ideas? This is really confusing me!
It looks like the best solution was not to use a view switcher at all but instead to effectively create my own one by declaring a FrameLayout around the two pages and setting the visibility of the second page to gone.
The switchToChild method (which I should probably rename to switch to page and actually pass in the 1 or 2 value) simply sets the appropriate views to visible during the animations:
private void switchToChild(final int child) {
final Interpolator accelerator = new AccelerateInterpolator();
final Interpolator decelerator = new DecelerateInterpolator();
final View visibleView;
final View invisibleView;
switch (child) {
case 0:
visibleView = findViewById(R.id.page_2);
invisibleView = findViewById(R.id.page_1);
findViewById(R.id.next).setVisibility(View.VISIBLE);
findViewById(R.id.back).setVisibility(View.GONE);
break;
case 1:
default:
visibleView = findViewById(R.id.page_1);
invisibleView = findViewById(R.id.page_2);
findViewById(R.id.back).setVisibility(View.VISIBLE);
findViewById(R.id.next).setVisibility(View.GONE);
break;
}
if (invisibleView.getVisibility() != View.VISIBLE) {
final ObjectAnimator visToInvis = ObjectAnimator.ofFloat(visibleView, "rotationY", 0f, 90f).setDuration(250);
visToInvis.setInterpolator(accelerator);
final ObjectAnimator invisToVis = ObjectAnimator.ofFloat(invisibleView, "rotationY", -90f, 0f).setDuration(250);
invisToVis.setInterpolator(decelerator);
visToInvis.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator anim) {
visibleView.setVisibility(View.GONE);
invisibleView.setVisibility(View.VISIBLE);
invisToVis.start();
}
});
visToInvis.start();
}
}
Related
I have two layouts (green on top, red on bottom) in a vertical LinearLayout (parent) looking similar to this:
.
When focus goes from the green to red, I would like the green to slide up off the screen and have the red simultaneously slide up with it and fill the whole screen. And when focus moves from red back up I want the green to slide back into the screen and return to the original configuration. I have tried looking at many other questions but none have had the solution I need. I tried just changing visibility between gone and visible but I want it to be a smooth animation. I've tried using parentLayout.animate().translationY(greenLayout.getHeight()) on the outer LinearLayout and that does give the animation I want but then the red does not expand to fill the screen, like this:
.
I know this question is similar to this one but that question is really old and only had one answer which didn't work for me.
My solution has a lot of different pieces, so I'll start with the full XML and java code, and then talk about the important bits:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<View
android:id="#+id/green"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="#0f0" />
<View
android:id="#+id/red"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#f00"/>
</LinearLayout>
In the XML, the only really important part is that the red view uses a height of 0dp and weight of 1. This means it takes up all extra vertical space, which will be important when we get rid of the green view.
public class MainActivity extends AppCompatActivity {
private int originalHeight;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final View green = findViewById(R.id.green);
final View red = findViewById(R.id.red);
green.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
green.getViewTreeObserver().removeGlobalOnLayoutListener(this);
originalHeight = green.getHeight();
}
});
green.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
animateHeightOfView(green, originalHeight, 0);
}
});
red.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
animateHeightOfView(green, 0, originalHeight);
}
});
}
private void animateHeightOfView(final View view, int start, int end) {
ValueAnimator animator = ValueAnimator.ofInt(start, end);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
int height = (int) valueAnimator.getAnimatedValue();
ViewGroup.LayoutParams params = view.getLayoutParams();
params.height = height;
view.setLayoutParams(params);
}
});
animator.start();
}
}
In the Java, the two main parts are the ViewTreeObserver.OnGlobalLayoutListener and the animateHeightOfView() method.
The OnGlobalLayoutListener exists to capture the green view's original height. We have to use a listener to do this instead of just writing originalHeight = green.getHeight() inside onCreate() because the green view isn't actually laid out at that point, so getHeight() would return 0 if we tried that.
The animateHeightOfView() method leverages the ValueAnimator class to animate the height of whatever view you pass to it. Since there's no direct setter for a view's height, we can't use simpler methods like .animate(). We set up the ValueAnimator to produce int values on every frame, and then we use a ValueAnimator.AnimatorUpdateListener to modify the view's LayoutParams to set the height.
Feel free to play with it. I'm using click listeners to trigger the animation, and you mentioned focus, but you should be able to call animateHeightOfView() in a different way if it suits you.
I want to get the position of my ImageView programmatically. That position is for imageView in pixels relative to screen NOT to parent. actually I found some solutions when searching they working While the Layout Direction is left-to-right, but when I change direction to right-to-left it gives me strange values( is this isseu).
How can i get the position when the activity is rtl supporting.
some solution I have found:
1) private int getRelativeTop(View myView) {
if (myView.getParent() == myView.getRootView())
return myView.getTop();
else
return myView.getTop() + getRelativeTop((View) myView.getParent());}
2) image.getLocationOnScreen(int[] locaiton);
UPDATE
In my activity i have three imageviews , i move (translte animation) image3 from image1 to image2 . start moving from position image1 to position image2, when i use ltr it is animate correctlly but when i change supportrtl="true" i do not see the animation at all.
this is xml file
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:id="#+id/rootParent"
android:orientation="vertical"
android:layout_height="match_parent">
<ImageView
android:id="#+id/piece_FLOAT"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/piece1"
android:translationZ="#dimen/activity_horizontal_margin" />
<ImageView
android:id="#+id/piece_1"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="8dp"
android:src="#drawable/piece1" />
<ImageView
android:id="#+id/piece_2"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_margin="8dp"
android:src="#drawable/piece1" />
</LinearLayout>
this is java class
public class AnimateActivity extends AppCompatActivity {
ImageView imageViewfrom, imageViewto;
ImageView imageViewFLOAT;
LinearLayout L_33;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_animate);
imageViewfrom = (ImageView)findViewById(R.id.piece_1);
imageViewto = (ImageView)findViewById(R.id.piece_2);
imageViewFLOAT = (ImageView)findViewById(R.id.piece_FLOAT);
assert imageViewfrom != null;
assert imageViewto != null;
imageViewfrom.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int[] ToLocation = new int[2];
imageViewto.getLocationOnScreen(ToLocation);
float xTO = ToLocation[0];//imageViewto.getX(); //ToLocation[0];
float yTO = ToLocation[1];//imageViewto.getY();//ToLocation[1];
int[] FromLocation = new int[2];
imageViewfrom.getLocationOnScreen(FromLocation);
float xFROM = FromLocation[0];//imageViewfrom.getX();///FromLocation[0];
float yFROM = FromLocation[1]; //imageViewfrom.getY();//FromLocation[1];
Log.e("xFrom =" + xFROM, "xTo =" + xTO );
Log.e("yFrom =" + yFROM, "yTo =" + yTO );
// Log.e("offset =" + topOffset, "xTo =" + 0);
ValueAnimator animatorX = ObjectAnimator.ofFloat(imageViewFLOAT, "x", xFROM, xTO).setDuration(1500);
ValueAnimator animatorY = ObjectAnimator.ofFloat(imageViewFLOAT, "y", yFROM, yTO).setDuration(1500);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.playTogether(animatorX, animatorY);
animatorSet.start();
// Animation an = new TranslateAnimation(xFROM, xTO, yFROM , yTO);
// an.setDuration(1500);
// an.setFillAfter(true);// to keep the state after animation is finished
// imageViewFLOAT.startAnimation(an);// to start animation obviously
}
});
}
}
when I use ltr it work very will but add some pixels. when I use rtl the animation did not seen. why this happen?
thanks for any help .
The issue here isn't really in finding the View's location, as that shouldn't be affected by the layout direction. The real problem is that View animations - especially those involving translations - apparently don't work well with RTL layouts. This is not surprising, since View animations have been around since the first versions of Android, but RTL support was only added in API level 17.
The solution is to use Property Animations instead.
For example, in your snippet, you're actually only translating that ImageView along the x-axis, so we can replace your entire TranslateAnimation setup with one line:
ObjectAnimator.ofFloat(imageViewFLOAT, "x", xFROM, xTO).setDuration(1500).start();
This creates an ObjectAnimator that modifies imageViewFLOAT's x-coordinate - by calling its setX() method - in the range [xFROM...xTO] over a duration of 1500 milliseconds, and immediately starts it.
Using an AnimatorSet, we can combine multiple animations to play together, so you can simultaneously perform a y-translation, as well. For example:
AnimatorSet as = new AnimatorSet();
as.playTogether(ObjectAnimator.ofFloat(imageViewFLOAT, "x", xFROM, xTO),
ObjectAnimator.ofFloat(imageViewFLOAT, "y", yFROM, yTO));
as.setDuration(1500).start();
Property animations and their classes are rather straightforward, and can do pretty much anything that the old View animations could. Updating your code to use these should be a simple fix for your RTL animation issues.
What I'm trying to achieve
I have a group of buttons in a GridLayout. One of the buttons toggles the function of the other buttons between rounding up and rounding down.
I am trying to implement an animation that changes the color of the buttons in a ripple like effect. The circular reveal animation is the effect I want where the new colour spreads from the touch point on the toggling button to the rest of the other buttons. I only want the animation to grow outward from the touch point in both cases, switching from rounding up to rounding down and back.
Problem
The animation is only working in the first instance from rounding up to rounding down (my app starts with rounding up as the default). There is no animation when switching from rounding down back to rounding up; all the buttons just changes in colour and the toggle button changes icon.
This is my first app so I am having difficulty trying to work out where I've gone wrong.
My methodology and code
In my activity_main.xml layout file, I've created two sets of GridLayouts (each with child buttons) and layered them one on top of the other by wrapping both in a FrameLayout. One set is given a different colour to the other set; I also have a different icon for the toggling button for each set to differentiate between the two rounding method. I've set the visibility attribute on the second GridLayout parent to invisible.
<FrameLayout
<GridLayout
android:id="#+id/roundUp"
<ImageButton
android:id="#+id/buttonU1"
... />
<Button ... />
<Button ... />
</GridLayout>
<GridLayout
android:id="#+id/roundDown"
android:visibility="invisible"
<ImageButton
android:id="#+id/buttonD1"
... />
<Button ... />
<Button ... />
</GridLayout>
</FrameLayout>
In my MainActivity.java file:
import ...
boolean roundingMode;
public class MainActivity extends AppCompatActivity {
GridLayout roundUp, roundDown;
ImageButton buttonU1, buttonD1;
Button ...
#Override;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
roundUp = (GridLayout) findViewById(R.id.roundUp);
buttonU1 = (ImageButton) findViewById(R.id.buttonU1);
roundDown = (GridLayout) findViewById(R.id.roundDown);
buttonD1 = (ImageButton) findViewById(R.id.buttonD1);
roundingMode = true;
buttonU1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonCircularRevealAnim(roundDown);
roundingMode = false;
}
});
buttonD1.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
buttonCircularRevealAnim(roundUp);
roundingMode = true;
}
});
}
public void buttonCircularRevealAnim(View view) {
int originX = roundUp.getWidth() / 2;
int originY = roundUp.getHeight() / 2;
float finalRadius = (float) Math.hypot(originX,originY);
Animator anim;
if (roundingMode) {
anim = ViewAnimationUtils.createCircularReveal(roundDown, originX, originY, 0, finalRadius);
roundDown.setVisibility(View.VISIBLE);
anim.start();
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
roundUp.setVisibility(View.INVISIBLE);
}
});
} else {
anim = ViewAnimationUtils.createCircularReveal(roundUp, originX, originY, 0, finalRadius);
roundUp.setVisibility(View.VISIBLE);
anim.start();
anim.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
roundDown.setVisibility(View.INVISIBLE);
}
});
}
}
Ignore the fact that I currently have the origin of the animation in the center of the GridLayout. I just want to get the basics working first.
I think the problem lies in the logic and/or the set up of the animation?
I've tried moving the originX, originY and finalRadius calculations into the if statement and using the roundUp (for roundingMode true) and roundDown GridLayouts (for roundingMode false) but that didn't work - so I figure it doesn't matter if it is invisible (in the scenario where you're switching from rounding down to rounding up).
Eventually understood that the circular reveal animation works to reveal an overlapping view that is initially invisible. So in order to use it to change the colour of a view back and forth you have to apply the new colour (from the revealed view) to the view underneath after the animation has ended and then make the revealed view invisible again with the other colour applied to it.
My original code was trying to reveal the view underneath which is of course impossible.
I found the following page very helpful:
http://myhexaville.com/2016/12/19/keep-your-app-material/
I have the following layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent">
<FrameLayout android:id="#+id/viewgroup_left"
android:layout_height="match_parent"
android:layout_weight="2"
android:layout_width="0dp">
... children ...
</FrameLayout>
<LinearLayout android:id="#+id/viewgroup_right"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_width="0dp"
android:orientation="vertical">
... children ...
</LinearLayout>
</LinearLayout>
I end up with something like this:
+------------------------+------------+
| | |
| | |
| Left | Right |
| | |
| | |
+------------------------+------------+
When a certain toggle is toggled, I want to animate Left so that its width expands to fill the entire screen. At the same time, I would like to animate the width of Right so that it shrinks to zero. Later, when the toggle is toggled again, I need to restore things to the above state.
I've tried writing my own Animation that calls View.getWidth() but when I animate back to that value (by setting View.getLayoutParams().width) it is wider than when it began. I suspect I'm just doing it wrong. I have also read all the documentation on the Honeycomb animation stuff, but I don't want to translate or scale... I want to animate the layout width property. I can't find an example of this.
What is the correct way to do this?
Since noone helped you yet and my first answer was such a mess I'll try to give you the right answer this time ;-)
Actually I like the idea and I think this is a great visual effect which might be useful for a bunch of people. I would implement an overflow of the right view (I think the shrink looks strange since the text is expanding to the bottom).
But anyway, here's the code which works perfectly fine (you can even toggle while it's animating).
Quick explanation:
You call toggle with a boolean for your direction and this will start a handler animation call loop. This will increase or decrease the weights of both views based on the direction and the past time (for a smooth calculation and animation). The animation call loop will invoke itself as long it hasn't reached the start or end position.
The layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="10"
android:id="#+id/slide_layout">
<TextView
android:layout_weight="7"
android:padding="10dip"
android:id="#+id/left"
android:layout_width="0dip"
android:layout_height="fill_parent"></TextView>
<TextView
android:layout_weight="3"
android:padding="10dip"
android:id="#+id/right"
android:layout_width="0dip"
android:layout_height="fill_parent"></TextView>
</LinearLayout>
The activity:
public class TestActivity extends Activity {
private static final int ANIMATION_DURATION = 1000;
private View mSlidingLayout;
private View mLeftView;
private View mRightView;
private boolean mAnimating = false;
private boolean mLeftExpand = true;
private float mLeftStartWeight;
private float mLayoutWeightSum;
private Handler mAnimationHandler = new Handler();
private long mAnimationTime;
private Runnable mAnimationStep = new Runnable() {
#Override
public void run() {
long currentTime = System.currentTimeMillis();
float animationStep = (currentTime - mAnimationTime) * 1f / ANIMATION_DURATION;
float weightOffset = animationStep * (mLayoutWeightSum - mLeftStartWeight);
LinearLayout.LayoutParams leftParams = (LinearLayout.LayoutParams)
mLeftView.getLayoutParams();
LinearLayout.LayoutParams rightParams = (LinearLayout.LayoutParams)
mRightView.getLayoutParams();
leftParams.weight += mLeftExpand ? weightOffset : -weightOffset;
rightParams.weight += mLeftExpand ? -weightOffset : weightOffset;
if (leftParams.weight >= mLayoutWeightSum) {
mAnimating = false;
leftParams.weight = mLayoutWeightSum;
rightParams.weight = 0;
} else if (leftParams.weight <= mLeftStartWeight) {
mAnimating = false;
leftParams.weight = mLeftStartWeight;
rightParams.weight = mLayoutWeightSum - mLeftStartWeight;
}
mSlidingLayout.requestLayout();
mAnimationTime = currentTime;
if (mAnimating) {
mAnimationHandler.postDelayed(mAnimationStep, 30);
}
}
};
private void toggleExpand(boolean expand) {
mLeftExpand = expand;
if (!mAnimating) {
mAnimating = true;
mAnimationTime = System.currentTimeMillis();
mAnimationHandler.postDelayed(mAnimationStep, 30);
}
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.slide_test);
mLeftView = findViewById(R.id.left);
mRightView = findViewById(R.id.right);
mSlidingLayout = findViewById(R.id.slide_layout);
mLeftStartWeight = ((LinearLayout.LayoutParams)
mLeftView.getLayoutParams()).weight;
mLayoutWeightSum = ((LinearLayout) mSlidingLayout).getWeightSum();
}
}
Just adding my 2 cents here to Knickedi's excellent answer - just in case someone needs it:
If you animate using weights you will end up with issues with clipping/non-clipping on contained views and viewgroups. This is especially true if you use viewgroups with weight as fragment containers. To overcome it, you might as well need to animate margins of the problematic child views and viewgroups / fragment containers.
And, to do all these things together, its always better to go for ObjectAnimator and AnimatorSet (if you can use them), along with some utility classes like MarginProxy
A different way to the solution posted by #knickedi is to use ObjectAnimator instead of Runnable. The idea is to use ObjectAnimator to adjust the weight of both left and right views. The views, however, need to be customised so that the weight can be exposed as a property for the ObjectAnimator to animate.
So first, define a customised view (using a LinearLayout as an example):
public class CustomLinearLayout extends LinearLayout {
public CustomLinearLayout(Context context) {
super(context);
}
public CustomLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public void setMyWeight(float value) {
LinearLayout.LayoutParams p = (LinearLayout.LayoutParams)getLayoutParams();
p.weight = value;
requestLayout();
}
}
Then, update the layout XML to use this custom linear layout.
Then, when you need to toggle the animation, use ObjectAnimator:
ObjectAnimator rightView = ObjectAnimator.ofFloat(viewgroup_right, "MyWeight", 0.5f, 1.0f);
ObjectAnimator leftView = ObjectAnimator.ofFloat(viewgroup_left, "MyWeight", 0.5f, 0.0f);
AnimatorSet animatorSet = new AnimatorSet();
animatorSet.setDuration(1000); // 1 second of animation
animatorSet.playTogether(rightView, leftView);
animatorSet.start();
The above code assumes both views are linear layout and are half in weight to start with. The animation will expand the right view to full weight (so the left one is hidden). Note that ObjectAnimator is animated using the "MyWeight" property of the customised linear layout. The AnimatorSet is used to tie both left and right ObjectAnimators together, so the animation looks smooth.
This approach reduces the need to write runnable code and the weight calculation inside it, but it needs a customised class to be defined.
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.