Translate Animation incorrect view move - android

I have 3 view objects(essentially ImageView's) with in a LinearLayout that in turn is within a RelativeLayout , The views are aligned within the LinearLayout as follows:
1 - 2 - 3 - -
The 3 views are wrapped under the Linear layout as demonstrated above.
Basically the idea is to get the side views(1st and 3rd views) move with animation to the place of the middle view onClick() .(so if 3rd view is clicked it should move to middle view's place and the middle moves right to the 3rd view's place.)
I implemented the translate animation as such that the 3rd view when clicked over 100dp to left and 2nd view moves to right, happens fine, but when I apply the translate animation on the onClick() of 1st view to make it move to right and 2nd to move to left then the 2nd and 3rd views both move collectively!! , This means the views are mapped next to each other automatically by the Android!!(note: that's why I used a LinearLayout so that alignment problems don't occur like 2nd view is aligned_below 1st view and aligned_left of 3rd view problems. )
also another problem is that though the views make a move land on another position that was originally belonging to the other view before the animated movement they still maintain the original view ID ?? For.Example that when 3rd view moves left to 2nd views place and 2nd mvoes to 3rd views place the onClick() still is mapped to their original location's?
XML file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
</LinearLayout>
<RelativeLayout
android:id="#+id/Container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#138AF8" >
<RelativeLayout
android:id="#+id/RelativeLayout01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:background="#138AF8" >
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:orientation="horizontal" >
<ImageView
android:id="#+id/ImageView01"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/cost" />
<ImageView
android:id="#+id/imageView1"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/cost" />
<ImageView
android:id="#+id/ImageView02"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="#drawable/cost" />
</LinearLayout>
</RelativeLayout>
</RelativeLayout>
</LinearLayout>
Those 3 ImageViews with the names of ImageView1, ImageView01, ImageView02 are the one's I'm trying to animate.
Animation code:
final TranslateAnimation moveLefttoRight = new TranslateAnimation(0,
100, 0, 0);
final TranslateAnimation moveRightToLeft = new TranslateAnimation(0,
-100, 0, 0);
moveRightToLeft.setDuration(1000);
moveLefttoRight.setDuration(1000);
moveRightToLeft.setFillAfter(true);
moveLefttoRight.setFillAfter(true);
final ImageView image1 = (ImageView) findViewById(R.id.imageView1);
final ImageView image2 = (ImageView) findViewById(R.id.ImageView01);
final ImageView image3 = (ImageView) findViewById(R.id.ImageView02);
image1.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
Toast.makeText(getApplicationContext(), "image1 clicked",
Toast.LENGTH_SHORT).show();
}
});
image2.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
Toast.makeText(getApplicationContext(), "image2 clicked",
Toast.LENGTH_SHORT).show();
image2.startAnimation(moveLefttoRight);
image1.startAnimation(moveRightToLeft);
}
});
image3.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
Toast.makeText(getApplicationContext(), "image3 clicked",
Toast.LENGTH_SHORT).show();
image2.startAnimation(moveLefttoRight);
image3.startAnimation(moveRightToLeft);
}
});

Translate animation doesn't actually move the view, it just makes it look like that. You have to set the params before the end of the animation so that the button moves as well.example
with the other issue can you post your xml layout file? do you use weights in the imageviews?

I ended up using ObjectAnimator builtin animating API and this moves the view's position permanently to the co-ords. requested.

Related

Translate Animation is not working perfectly in dynamic view

In this project, I want to move TextView's clone from top TextView place to bottom TextView place when button is click.
I got a problem in using Translate Animation. I want to move a view to exact position(Like in Zapya).
In Zapya, when user select item and choose "send", the gridview item's clone move to user icon.
So, I use Translate Animation to move view. And I created a view dynamically to show item's clone.
Using Translate Animation works with view that is initially created in xml but not with view that is dynamically created.
The code is here
top = (TextView) findViewById(R.id.textviewtop);
bottom = (TextView) findViewById(R.id.textviewbottom);
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
int []from = new int[2];
int []to = new int[2];
from[0] = (int) top.getX();
from[1] = (int) top.getY();
to[0] = (int) bottom.getX();
to[1] = (int) bottom.getY();
ViewGroup vg = (ViewGroup) top.getParent();
view = new TextView(getApplicationContext());
view.setWidth(top.getWidth());
view.setHeight(top.getHeight());
view.setX(from[0]);
view.setY(from[1]);
view.setText(top.getText());
view.setVisibility(View.VISIBLE);
view.setTextColor(Color.BLACK);
view.setId(0x23454657);
vg.addView(view);
TranslateAnimation anim = new TranslateAnimation( 0, 0 , from[1], to[1] );
anim.setDuration(1000);
anim.setFillAfter( true );
view.startAnimation(anim);
}
});
and xml file
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/rl"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<TextView
android:id="#+id/textviewtop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:text="#string/hello_world" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Move"/>
<TextView
android:id="#+id/textviewbottom"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_alignParentBottom="true"
android:text="#string/hello_world" />
</RelativeLayout>
"view" show only starting and ending time. But not in between. How can I solve that.
Please tell if there's any other way. I will thanks a ton.
Increase the duration Time, may be that is a problem
anim.setDuration(4000);

Translate a View from One Layout to Another with Translate Animation

I am new in Android animation and my requirement is to translate a view from one layout to layout in a single xml file on click of that view.
Scenario:
Suppose I click a button, present on the top of the header in a xml file,and it should move/translate downwards (it should give an impact that it lies on the other layout downwards to header), and also I want that when the user clicks on the same again, it should now move to its original position.
Here I am explaining with my xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#drawable/app_bg"
android:orientation="vertical" >
<RelativeLayout
android:id="#+id/top"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#drawable/header"
android:paddingLeft="10dp"
android:paddingRight="10dp" >
<Button
android:id="#+id/btnSearchHeader"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_centerInParent="true"
android:background="#drawable/search_icon" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/bottom"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#color/app_transparent"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:layout_marginTop="10dp"
android:visibility="visible" >
<Button
android:id="#+id/btnMenu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginRight="5dp"
android:text="ABC" />
<Button
android:id="#+id/btnSearchSelected"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/btnMenu"
android:text="CDE" />
</RelativeLayout>
</LinearLayout>
MORE PRECISE REQUIREMENT SPECIFICATION (Kindly read carefully:)
Here I have two sub inner layouts:-
Top Layout - id-> top
Bottom Layout- id -> bottom
Now a view (Button -> btnSearchHeader) is lying in my top layout and I want to animate the same to the bottom layout (it should give an impact that it is translated with a translate animation to the bottom layout) on click of that button and when the user clicks on that button, it should again translate back to its original position with a translate animation .. i.e it should show back in the top layout
I have no idea how to give these impacts using translate animations, however i just have a basic translate animation knowledge which is insufficient for me to work upon my requirement.
Any type of related help is appreciable.
Thanks
Have you tried something simple like the following?
final int topHeight = findViewById(R.id.top).getHeight();
final int bottomHeight = findViewById(R.id.bottom).getHeight();
final View button = findViewById(R.id.btnSearchHeader);
final ObjectAnimator moveDownAnim = ObjectAnimator.ofFloat(button, "translationY", 0.F, topHeight + bottomHeight / 2 - button.getHeight() / 2);
final ObjectAnimator moveUpAnim = ObjectAnimator.ofFloat(button, "translationY", topHeight + bottomHeight / 2 - button.getHeight() / 2, 0.F);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (0.F == v.getTranslationY())
moveDownAnim.start();
else
moveUpAnim.start();
}
});
If you actually need the button view to change parents, you can use AnimatorListener to achieve this at the end of each animation. Something like:
moveDownAnim.addListener(new Animator.AnimatorListener() {
#Override
public void onAnimationEnd(Animator animation) {
((ViewGroup)findViewById(R.id.top)).removeView(button);
((ViewGroup)findViewById(R.id.bottom)).addView(button);
((RelativeLayout)button.getLayoutParams()).addRule(RelativeLayout.CENTER_IN_PARENT);
button.setTranslationY(0.F); // Since it is now positioned in the new layout, no need for translation.
}
#Override
public void onAnimationCancel(Animator animation) { /* NOP */ }
#Override
public void onAnimationRepeat(Animator animation) { /* NOP */ }
#Override
public void onAnimationStart(Animator animation) { /* NOP */ }
});
(And analogous listener for the moveUpAnim.)
However, I doubt you need to actually do this to achieve the visual effect you want. But if you do this part, you will probably also need to set a fixed height for your top view as opposed to wrap_content. (Otherwise, if a layout pass happens while the button has been moved to the bottom view, the top layout's height might go to 0 if there's nothing else in it.) Easiest would be to just do this directly in the xml layout file. However, if you want to "do it on the fly", you can change the layout's height in the onAnimationEnd() method using something like:
#Override
public void onAnimationEnd(Animator animation) {
final ViewGroup topLayout = findViewById(R.id.top);
topLayout.getLayoutParams().height = topLayout.getHeight(); // Keep it the same height...
topLayout.removeView(button);
((ViewGroup)findViewById(R.id.bottom)).addView(button);
((RelativeLayout)button.getLayoutParams()).addRule(RelativeLayout.CENTER_IN_PARENT);
button.setTranslationY(0.F); // Since it is now positioned in the new layout, no need for translation.
}

Custom View and Layout Animation android

I have a layout which at start has '0dp' width but when a button is clicked it animates from Left to right and its width is increased accordingly. In this layout I am initializing a custom view. The view is initialized correctly when I place it at right or at centre but when I place it on the left it's not shown.
Here is my XML:
<RelativeLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0"
android:background="#drawable/bg">
<com.example.Wheel
android:id="#+id/wheel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" >
</com.example.Wheel>
</RelativeLayout>
And here is what I do in java:
MenuListLeft = (RelativeLayout) findViewById(R.id.ControlLayout);
openButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
if (isExpandedLeft) {
isExpandedLeft = false;
MenuListLeft.startAnimation(new CollapseAnimationLTR(MenuListLeft, 0,(int)(screenWidth*1), 5));
}
else {
isExpandedLeft = true;
MenuListLeft.startAnimation(new ExpandAnimationLTR(MenuListLeft, 0,(int)(screenWidth*1), 5));
init();
}
}
});
You would be better of using weights in a combination of Relative and Linear Layout rather than just in a Relative Layout.
Here...
weight = 0 gets you no space expansion. Try setting it to 1.
In case you want to understand more on how weight works:
http://teamdroid.wordpress.com/2012/06/06/android-layout-weight-explained/
Also, for your case, wouldn't a View.Visibility GONE, VISIBLE...with animation may work better.

Android Shadow on bottom of RelativeLayout outside of bounds

I have a 9 patch image of a shadow that I want to add to the bottom of a RelativeLayout. The layout fills the screen, but slides up then the user taps a button. So, I would like to have the shadow image be below the RelativeLayout (pulled down with a negative bottom margin) so that when the layout sides up, the shadow is on the bottom edge of the layout, giving it a layered effect.
<ImageView
android:id="#+id/shadow"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="-10dp"
android:src="#drawable/shadow" />
I am sliding up the frame using:
ObjectAnimator mover = ObjectAnimator.ofFloat(mainView, "translationY", !historyShown ? -ph : 0);
mover.setDuration(300);
mover.start();
Strangely, when I add the image to the layout and it give it a negative margin, it just isn't shown, like it is cutting off anything outside the bounds of the layout.
Is there a way around this?
I can think of one way of doing it, but I'm sure there must be a cleaner way.
Make the layout in which the mainView resides a FrameLayout (or RelativeLayout), and include the ImageView in that, making it a sibling of mainView, but list it before mainView. Set it to be at the bottom using layout_gravity="bottom" (or layout_alignParentBottom="true" if using a RelativeLayout).
Now change the target in the ObjectAnimator to something above the mainView (so either its container View or the Activity/Fragment), and change the property to something like "scrollUp", then create a method named setScrollUp(float) in the target. In this method set the translation of the mainView and shadow using setTranslationY(). Offset the shadow by its height.
Works for me here in a simple app using solid colours:
XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#f00">
<View
android:id="#+id/shadow"
android:layout_width="match_parent"
android:layout_height="20px"
android:layout_gravity="bottom"
android:background="#00f"/>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#0f0"
android:id="#+id/container"/>
</FrameLayout>
Activity code:
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
container = findViewById(R.id.container);
shadow = findViewById(R.id.shadow);
container.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(final View v)
{
final float translationTo = (open) ? 0 : -300;
final float translationFrom = (open) ? -300 : 0;
open = !open;
ObjectAnimator anim = ObjectAnimator.ofFloat(MyActivity.this, "scrollUp", translationFrom, translationTo);
anim.setDuration(500);
anim.start();
}
});
}
public void setScrollUp(final float position)
{
container.setTranslationY(position);
shadow.setTranslationY(position + shadow.getHeight());
}

HorizontalScrollView with arrows

I'm trying to make a scrollable horizontal menu using HorizontalScrollView using the layout shown below. The menu is scrollable using the previous/next arrow buttons or on fling. When the HorizontalScrollView reach one end I'd like the arrow at the same end to be hidden (in the image shown below I'd like the left arrow to be hidden).
How can I detect that the HorizontalScrollView has reached an end?
Thanks
<RelativeLayout android:background="#drawable/bg_home_menu"
android:layout_width="fill_parent" android:layout_height="45dp">
<ImageView android:id="#+id/previous" android:src="#drawable/arrow_l"
android:layout_height="14dp" android:layout_width="10dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true" />
<ImageView android:id="#+id/next" android:src="#drawable/arrow_r"
android:layout_height="14dp" android:layout_width="10dp"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
<HorizontalScrollView android:id="#+id/horizontalScroll"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:scrollbars="none" android:fadingEdgeLength="30dp" android:layout_toLeftOf="#id/next"
android:layout_toRightOf="#id/previous" >
<LinearLayout android:id="#+id/home_menu"
android:orientation="horizontal" android:layout_width="wrap_content"
android:layout_height="fill_parent" android:gravity="center_vertical">
<Button android:id="#+id/btn_home" android:background="#drawable/btn_home_menu_on"
android:layout_height="35dp" android:layout_width="wrap_content" android:focusable="true"
android_clickable="false" android:text="#string/menu_home" android:textColor="#FFFFFF" android:tag="-1"/>
<!-- More are added dynamically -->
</LinearLayout>
</HorizontalScrollView>
</RelativeLayout>
There is no scroll listener for the HorizontalScrollView. What you can do is add an OnTouchListener to it This will fire continously when the user scrolls, and each time you can use the method getScrollX which returns the int.
Now 0 mean its left most, to find the right most(max scroll amount), you need to find the width of the child view of the horzontal scroll view. That is found by using the addOnGlobalLayoutListener else the width will always be 0 inside the onCreate method
Put this code in the onCreate method
final HorizontalScrollView hs = (HorizontalScrollView)findViewById(R.id.scroll);
ViewTreeObserver vto = hs.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
hs.getViewTreeObserver().removeGlobalOnLayoutListener(this);
maxScrollX = hs.getChildAt(0)
.getMeasuredWidth()-getWindowManager().getDefaultDisplay().getWidth();
}
});
hs.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
Log.e("ScrollValue", Integer.toString(hs.getScrollX()));
if(hs.getScrollX() == maxScrollX){
Log.e("MaxRight", "MaxRight");
}
return false;
}
});
Use getScrollX() of the LinearLayout inside your scroller to determine which is the leftmost corner on screen. If it's 0, then left arrow should be disabled.
For the right arrow, retrieve the drawing rectangle's width, add getScrollX() and compare that to getMeasuredWidth (), if it's the same, you're at the right, no need for the right arrow.
So your code will look like this:
if (homeMenu.getScrollX()==0) {
hideLeftArrow();
} else {
showLeftArrow();
}
if (homeMenu.getDrawingRect().right == homeMenu.getMeasuredWidth()) {
hideRightArrow();
} else {
showRightArrow();
}
Of course you will have to put this in an event listener. I can only think of using your own HorizontalScrollView class, with the onScroll() method overwritten to perform the checks above, see this post.

Categories

Resources