Confusing with getGlobalVisibleRect, different values - android

I'm try to zoom a FrameLayout with the following example from der android developers site: http://developer.android.com/training/animation/zoom.html
My concrete Problem, in the first time the animation is right, is expand from the thumbView, in the second time the animation comes from 'somewhere' (middle/top to the center).
i have nearly the same, the differents are, i have an Framelayout instead an ImageView and i extract the function to minimize the View back in an extra Method. now thats looks like so:
private void zoomImageFromThumb(final View thumbView) {
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
// here i building my custome layout
startBounds = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
thumbView.getGlobalVisibleRect(startBounds);
findViewById(R.id.container)
.getGlobalVisibleRect(finalBounds, globalOffset);
startBounds.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 60);
float startScale;
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
} else {
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
}
thumbView.setAlpha(0f);
expandedImageView.setVisibility(View.VISIBLE);
expandedImageView.setPivotX(0f);
expandedImageView.setPivotY(0f);
AnimatorSet set = new AnimatorSet();
set
.play(ObjectAnimator.ofFloat(expandedImageView, View.X,
startBounds.left, finalBounds.left))
.with(ObjectAnimator.ofFloat(expandedImageView, View.Y,
startBounds.top, finalBounds.top))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X,
startScale, 1f)).with(ObjectAnimator.ofFloat(expandedImageView,
View.SCALE_Y, startScale, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mCurrentAnimator = null;
}
#Override
public void onAnimationCancel(Animator animation) {
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
}
the startBounds Variable is global, cause i need this to know where the position is for the minimize process. Here the minimize Method:
private void minimizeViewFromThumb(final View thumbView) {
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator
.ofFloat(expandedImageView, View.X, startBounds.left))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.Y,startBounds.top))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_X, startScaleFinal))
.with(ObjectAnimator
.ofFloat(expandedImageView,
View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
#Override
public void onAnimationCancel(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
}
if i debug this whole process i can see that the method getGlobalVisibleRect from the method zoomViewFromThumb give me another value.
if i debug the line
finalBounds.offset(-globalOffset.x, -globalOffset.y);
in the first time the two parameters are 0 and -60 and in the second time (after minimize and recreate there are 15 and 360.
i have no idea why thats happen.
i have try to set the View.X and View.Y parameter append from the given thumbView, i have try to work with constant Values for the View.X, View.Y parameter in the ObjectAnimator but nothing fix my problem.
now please help me.
Greets Manu
1. EDIT: the fail is on Android Version 4.1.2 i have test it in the emulator with Android 4.0 and there it works fine
2. EDIT: Here are the xml files, the first one is the xml File that representing my main Activity (with the animation), the second one represent the TableLayout what i push in the FrameLayout of the main xml. (Please notice, currently I'm at work and i have no access to the original, now these xml files are good as far I can remember)
the first
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relZoom"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<FrameLayout
android:id="#+id/frameZoomOne"
android:layout_width="160dp"
android:layout_height="215dp"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginBottom="10dp"
android:layout_marginLeft="10dp" >
</FrameLayout>
<FrameLayout
android:id="#+id/frameZoomTwo"
android:layout_width="160dp"
android:layout_height="215dp"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_marginRight="10dp"
android:layout_marginTop="10dp" >
</FrameLayout>
<FrameLayout
android:id="#+id/container"
android:layout_width="300dp"
android:layout_height="408dp"
android:visibility="invisible" >
</FrameLayout>
<FrameLayout
android:id="#+id/containerTwo"
android:layout_width="300dp"
android:layout_height="408dp"
android:visibility="invisible" >
</FrameLayout>
</RelativeLayout>
the second
<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/tableLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TableRow
android:id="#+id/tableRow1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="#+id/textView1"
android:text="Column 1"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView2"
android:text="Column 2"
android:textAppearance="?android:attr/textAppearanceLarge" />
</TableRow>
<TableRow
android:id="#+id/tableRow2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<ImageView
android:id="#+id/imgView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/android" />
</TableRow>
<TableRow
android:id="#+id/tableRow3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dip" >
<TextView
android:id="#+id/textView3"
android:text="Column 3"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/textView4"
android:text="Column 4"
android:textAppearance="?android:attr/textAppearanceLarge" />
</TableRow>
</TableLayout>
3. EDIT: correct the xml file and now adding the Activity:
public class SinglePlayerSp extends Activity implements OnClickListener
{
private final Context mContext = this;
private boolean mBackZoomOne = false;
private FrameLayout frameZoomOne;
private FrameLayout frameZoomTwo;
private static Animator mCurrentAnimatorOne;
private int mShortAnimationDuration;
private float startScaleOne;
private static Animator mCurrentAnimatorTwo;
private float startScaleTwo;
private Rect startBoundsOne;
private Rect startBoundsTwo;
private static View lastViewOne;
private static View lastViewTwo;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoom);
frameZoomOne = (FrameLayout) findViewById(R.id.frameZoomOne);
frameZoomTwo = (FrameLayout) findViewById(R.id.frameZoomTwo);
frameZoomOne.setOnClickListener(this);
frameZoomTwo.setOnClickListener(this);
mShortAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
cardItems = getIntent().getParcelableArrayListExtra(CARD_ITEMS);
java.util.Collections.shuffle(cardItems);
}
private void flipCard(boolean playerOneDeck, final int selectionFromPlayer, final boolean result)
{
Card cardItemOne = null;
if (oneCards.get(0) != null)
{
cardItemOne = oneCards.get(0);
}
if (!mBackZoomOne)
{
getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
R.id.frameZoomOne, new CardBackFragment()).commit();
mBackZoomOne = true;
}
else
{
getFragmentManager().beginTransaction().setCustomAnimations(R.animator.card_flip_right_in,
R.animator.card_flip_right_out, R.animator.card_flip_left_in, R.animator.card_flip_left_out).replace(
R.id.frameZoomOne,
CardFrontFragment.newInstance(cardItemPlayerOne, selectionFromPlayer, playerOneDeck)).commit();
mBackZoomOne = false;
zoomViewOneFromThumb(frameZoomOne, cardItemOne);
}
}
private void zoomViewOneFromThumb(final View thumbView, final Card cardItem)
{
if (mCurrentAnimatorOne != null)
{
mCurrentAnimatorOne.cancel();
}
lastViewOne = thumbView;
View.getDefaultSize(0, 0);
final FrameLayout expandFrameLayout = (FrameLayout) findViewById(R.id.container);
LayoutInflater inflater =
(LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.fragment_card_front_clickable, null);
TableRow rowOne = (TableRow) layout.findViewById(R.id.tableRow1);
rowOne.setOnClickListener(this);
TextView cardone = (TextView) layout.findViewById(R.id.textView1);
TextView cardtwo = (TextView) layout.findViewById(R.id.textView2);
TextView cardthree = (TextView) layout.findViewById(R.id.textView3);
TextView cardfour = (TextView) layout.findViewById(R.id.textView4);
Locale locale = getApplicationContext().getResources().getConfiguration().locale;
cardone.setText(cardItem.TextOne());
cardtwo.setText(cardItem.getTextTwo());
cardthree.setText(cardItem.getTextThree());
cardfour.setText(cardItem.TextFour());
expandFrameLayout.addView(layout);
startBoundsOne = new Rect();
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
thumbView.getGlobalVisibleRect(startBoundsOne);
findViewById(R.id.containerSp).getGlobalVisibleRect(finalBounds, globalOffset);
startBoundsOne.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x + 15, -globalOffset.y + 50);
if ((float) finalBounds.width() / finalBounds.height() > (float) startBoundsOne.width()
/ startBoundsOne.height())
{
startScaleOne = (float) startBoundsOne.height() / finalBounds.height();
float startWidth = startScaleOne * finalBounds.width();
float deltaWidth = (startWidth - startBoundsOne.width()) / 2;
startBoundsOne.left -= deltaWidth;
startBoundsOne.right += deltaWidth;
}
else
{
startScaleOne = (float) startBoundsOne.width() / finalBounds.width();
float startHeight = startScaleOne * finalBounds.height();
float deltaHeight = (startHeight - startBoundsOne.height()) / 2;
startBoundsOne.top -= deltaHeight;
startBoundsOne.bottom += deltaHeight;
}
thumbView.setAlpha(0f);
expandFrameLayout.setVisibility(View.VISIBLE);
expandFrameLayout.setPivotX(0f);
expandFrameLayout.setPivotY(0f);
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left, finalBounds.left)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top, finalBounds.top)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleOne, 1f)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleOne, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
mCurrentAnimatorOne = null;
}
#Override
public void onAnimationCancel(Animator animation)
{
mCurrentAnimatorOne = null;
}
});
set.start();
mCurrentAnimatorOne = set;
startScaleFinal = startScaleOne; // with this or without this, i have the same problem
}
private void minimizeViewOne(final View expandFrameLayout)
{
AnimatorSet set = new AnimatorSet();
set.play(ObjectAnimator.ofFloat(expandFrameLayout, View.X, startBoundsOne.left)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.Y, startBoundsOne.top)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_X, startScaleFinal)).with(
ObjectAnimator.ofFloat(expandFrameLayout, View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter()
{
#Override
public void onAnimationEnd(Animator animation)
{
lastViewOne.setAlpha(1f);
expandFrameLayout.setVisibility(View.GONE);
mCurrentAnimatorOne = null;
}
#Override
public void onAnimationCancel(Animator animation)
{
lastViewOne.setAlpha(1f);
expandFrameLayout.setVisibility(View.GONE);
mCurrentAnimatorOne = null;
}
});
set.start();
mCurrentAnimatorOne = set;
}
}
OK that's now the full code. At the End is an onClick Method, in there I receive user actions. from there I call the minimizeView Method, then some checks, after this I call the flipCard. That's all.

As per google Developer:
getGlobalVisibleRect(Rect r, Point globalOffset);
If some part of this view is not clipped by any of its parents, then return that area in r in global (root) coordinates.
ex:
thumbView.getGlobalVisibleRect(startBounds);
here suppose thumbview has width of 100 and height 75 and marging from left and and top 16 and 51 respectively this method store value in startBound(Rect) as left 16 , top 51 , right 16+100 = 116 , bottom 51+75 = 126. i.e. (16 , 51 , 116 , 126)

im not sure where you are assigning the event to close the view. but i would say that the point that is causing the error, is where you read some variables such as startScaleFinal = startScale; that has to be done before the enlarge animation start and proabaly others.
ill post my full working example with the diferent functions, and frameviews:
It is working perfectly.
activity:
/*
* Copyright 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.example.android.animationsdemo;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import android.view.animation.DecelerateInterpolator;
import android.widget.FrameLayout;
/**
* A sample showing how to zoom an image thumbnail to full-screen, by animating the bounds of the
* zoomed image from the thumbnail bounds to the screen bounds.
*
* <p>In this sample, the user can touch one of two images. Touching an image zooms it in, covering
* the entire activity content area. Touching the zoomed-in image hides it.</p>
*/
public class ZoomActivity extends FragmentActivity {
/**
* Hold a reference to the current animator, so that it can be canceled mid-way.
*/
private Animator mCurrentAnimator;
/**
* The system "short" animation time duration, in milliseconds. This duration is ideal for
* subtle animations or animations that occur very frequently.
*/
private int mShortAnimationDuration;
final Rect finalBounds = new Rect();
final Point globalOffset = new Point();
final Rect startBounds = new Rect();
float startScale;
FrameLayout expandedImageView;
float startScaleFinal ;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_zoom);
// Hook up clicks on the thumbnail views.
final View thumb1View = findViewById(R.id.thumb_button_1);
thumb1View.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
zoomImageFromThumb(thumb1View, R.drawable.image1);
}
});
final View thumb2View = findViewById(R.id.thumb_button_2);
thumb2View.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
zoomImageFromThumb(thumb2View, R.drawable.image2);
}
});
// Retrieve and cache the system's default "short" animation time.
mShortAnimationDuration = getResources().getInteger(android.R.integer.config_shortAnimTime);
}
private void zoomImageFromThumb(final View thumbView, int imageResId) {
// If there's an animation in progress, cancel it immediately and proceed with this one.
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
// Load the high-resolution "zoomed-in" image.
expandedImageView = (FrameLayout) findViewById(R.id.expanded_image);
// The start bounds are the global visible rectangle of the thumbnail, and the
// final bounds are the global visible rectangle of the container view. Also
// set the container view's offset as the origin for the bounds, since that's
// the origin for the positioning animation properties (X, Y).
thumbView.getGlobalVisibleRect(startBounds);
findViewById(R.id.container).getGlobalVisibleRect(finalBounds, globalOffset);
startBounds.offset(-globalOffset.x, -globalOffset.y);
finalBounds.offset(-globalOffset.x, -globalOffset.y);
// Adjust the start bounds to be the same aspect ratio as the final bounds using the
// "center crop" technique. This prevents undesirable stretching during the animation.
// Also calculate the start scaling factor (the end scaling factor is always 1.0).
if ((float) finalBounds.width() / finalBounds.height()
> (float) startBounds.width() / startBounds.height()) {
// Extend start bounds horizontally
startScale = (float) startBounds.height() / finalBounds.height();
float startWidth = startScale * finalBounds.width();
float deltaWidth = (startWidth - startBounds.width()) / 2;
startBounds.left -= deltaWidth;
startBounds.right += deltaWidth;
} else {
// Extend start bounds vertically
startScale = (float) startBounds.width() / finalBounds.width();
float startHeight = startScale * finalBounds.height();
float deltaHeight = (startHeight - startBounds.height()) / 2;
startBounds.top -= deltaHeight;
startBounds.bottom += deltaHeight;
}
// Hide the thumbnail and show the zoomed-in view. When the animation begins,
// it will position the zoomed-in view in the place of the thumbnail.
thumbView.setAlpha(0f);
expandedImageView.setVisibility(View.VISIBLE);
// Set the pivot point for SCALE_X and SCALE_Y transformations to the top-left corner of
// the zoomed-in view (the default is the center of the view).
expandedImageView.setPivotX(0f);
expandedImageView.setPivotY(0f);
// Construct and run the parallel animation of the four translation and scale properties
// (X, Y, SCALE_X, and SCALE_Y).
AnimatorSet set = new AnimatorSet();
set
.play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left,
finalBounds.left))
.with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top,
finalBounds.top))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_X, startScale, 1f))
.with(ObjectAnimator.ofFloat(expandedImageView, View.SCALE_Y, startScale, 1f));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
mCurrentAnimator = null;
}
#Override
public void onAnimationCancel(Animator animation) {
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
// Upon clicking the zoomed-in image, it should zoom back down to the original bounds
// and show the thumbnail instead of the expanded image.
startScaleFinal = startScale;
expandedImageView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
minimizeViewFromThumb(thumbView);
}
});
}
private void minimizeViewFromThumb(final View thumbView) {
// Upon clicking the zoomed-in image, it should zoom back down to the original bounds
// and show the thumbnail instead of the expanded image.
if (mCurrentAnimator != null) {
mCurrentAnimator.cancel();
}
// Animate the four positioning/sizing properties in parallel, back to their
// original values.
AnimatorSet set = new AnimatorSet();
set
.play(ObjectAnimator.ofFloat(expandedImageView, View.X, startBounds.left))
.with(ObjectAnimator.ofFloat(expandedImageView, View.Y, startBounds.top))
.with(ObjectAnimator
.ofFloat(expandedImageView, View.SCALE_X, startScaleFinal))
.with(ObjectAnimator
.ofFloat(expandedImageView, View.SCALE_Y, startScaleFinal));
set.setDuration(mShortAnimationDuration);
set.setInterpolator(new DecelerateInterpolator());
set.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
#Override
public void onAnimationCancel(Animator animation) {
thumbView.setAlpha(1f);
expandedImageView.setVisibility(View.GONE);
mCurrentAnimator = null;
}
});
set.start();
mCurrentAnimator = set;
}
}
layout:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView style="?android:textAppearanceSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/message_zoom_touch_expand" />
<!-- This is an example layout containing thumbnail image buttons that, when pressed,
zoom in to show more detail. All of the zooming and animation logic is in
the ZoomActivity class. -->
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:orientation="horizontal">
<!-- These buttons don't have any decorations (3D bevel, etc.), but it's still
important to show feedback on touch or focus. The custom
"ToughHighlightImageButton" ImageButton subclass helps achieve this by drawing
the standard system "pressed" and "focused" overlay upon user interaction. -->
<FrameLayout
android:id="#+id/thumb_button_1"
android:layout_width="100dp"
android:layout_height="75dp"
android:background="#android:color/holo_orange_light"
android:contentDescription="#string/description_image_2" />
<FrameLayout
android:id="#+id/thumb_button_2"
android:layout_width="100dp"
android:layout_height="75dp"
android:background="#android:color/darker_gray"
android:contentDescription="#string/description_image_2" />
</LinearLayout>
</LinearLayout>
<!-- This initially-hidden ImageView will hold the expanded/zoomed version of the
images above. Without transformations applied, it takes up the entire screen.
To achieve the "zoom" animation, this view's bounds are animated from the
bounds of the thumbnail buttons above, to its final laid-out bounds. The implementation
of this animation is in the ZoomActivity class. -->
<FrameLayout
android:id="#+id/expanded_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:background="#android:color/holo_blue_light" />
</FrameLayout>

Related

How to make buttons text get different directions animation in android studio

I want to bring the text of the buttons from different directions.
I looked at the ObjectAnimatore but couldn't.
ObjectAnimator colorAnim = ObjectAnimator.ofInt(altbutonlar.get(i), "textColor", Color.BLACK, Color.TRANSPARENT);
colorAnim.setDuration(100);
colorAnim.setEvaluator(new ArgbEvaluator());
colorAnim.setRepeatCount(ValueAnimator.INFINITE);
colorAnim.setRepeatMode(ValueAnimator.REVERSE);
colorAnim.start();
Why not creating a TextView inside a FrameLayout and set the style so that the FrameLayout looks like a Button and you can animate the TextView like you want.
Here is an example of what i'm talking about
in the Layout use FrameLayout like this :
<FrameLayout
android:id="#+id/buttonContainer"
style="#style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/toolBar">
<TextView
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:gravity="center"
android:paddingStart="8dp"
android:paddingTop="5dp"
android:paddingEnd="8dp"
android:paddingBottom="5dp"
android:text="Test"
android:textColor="#android:color/white"
android:textSize="17sp" />
</FrameLayout>
And this is how I animate the TextView in the Activity:
public class MainActivity extends AppCompatActivity {
private TextView textView;
private FrameLayout buttonContainer;
private static final int DIRECTION_L = -1;
private static final int DIRECTION_R = 1;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.button);
buttonContainer = findViewById(R.id.buttonContainer);
buttonContainer.setOnClickListener(v -> animate(DIRECTION_L, DIRECTION_R, "Hello world"));
}
/**
* #param directionOut direction out -1 from left or 1 from right
* #param directionIn direction in -1 from left or 1 from right
* #param newText the new text you want to added in textView
*/
private void animate(int directionOut, int directionIn, String newText) {
int lastPosition = buttonContainer.getWidth() / 2 + textView.getWidth() / 2;// get the position x to TextView inside frameLayout
ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "TranslationX", 0, directionOut * lastPosition);
animator.setInterpolator(new AnticipateOvershootInterpolator(1.5f));
animator.setDuration(600);
animator.start();
animator.addListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
addNewText(directionIn, newText);
animation.removeAllListeners();
}
});
}
/**
* if you want to add new new text that slide In
*
* #param directionIn -1 from left or 1 from right
* #param newText the new text you want to added in textView
*/
private void addNewText(int directionIn, String newText) {
textView.setText(newText);
int lastPosition = buttonContainer.getWidth() / 2 + textView.getWidth() / 2;// get the position x to TextView inside frameLayout
ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "TranslationX", directionIn * lastPosition, 0);
animator.setInterpolator(new AnticipateOvershootInterpolator(1.5f));
animator.setDuration(600);
animator.start();
}
}
And this is how the result looks:

Implement rotation and scall in View

I want to implement single figure rotation and scalling functinality on Frame Layout using bottom right cornor button of Framlayout.following is my code that not working fine.I am triying more than 15 days for it but not find the solution for layout rotation.there are lots of demo available for image rotatin.but i want layout rotation.
layout
<FrameLayout
android:id="#+id/fl_main"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/imgPhotoEditorClose"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="top|start"
android:elevation="1dp"
android:src="#drawable/ic_remove" />
<FrameLayout
android:id="#+id/frmBorder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="8dp"
android:background="#drawable/rounded_border_tv">
<ImageView
android:id="#+id/imgPhotoEditorImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:adjustViewBounds="true"
android:contentDescription="#string/app_name"
android:scaleType="fitCenter"
android:src="#drawable/ic_remove" />
</FrameLayout>
<ImageView
android:id="#+id/imgPhotoEditorPush"
android:layout_width="25dp"
android:layout_height="25dp"
android:layout_gravity="bottom|end"
android:elevation="1dp"
android:src="#drawable/ic_remove" />
java
final View imageRootView = getLayout(ViewType.IMAGE);
final ImageView imageView = imageRootView.findViewById(R.id.imgPhotoEditorImage);
final FrameLayout frmBorder = imageRootView.findViewById(R.id.frmBorder);
final ImageView imgClose = imageRootView.findViewById(R.id.imgPhotoEditorClose);
final ImageView imgPhotoEditorPush = imageRootView.findViewById(R.id.imgPhotoEditorPush);
imgPhotoEditorPush.setOnTouchListener(new View.OnTouchListener()
{
float centerX, centerY, startR, startScale, startX, startY;
float startAngle;
float zeroAngle;
int firstPointX;
int firstPointY;
public boolean onTouch(View v, MotionEvent e)
{
if (e.getAction() == MotionEvent.ACTION_DOWN)
{
// calculate center of image
centerX = (imageRootView.getLeft() + imageRootView.getRight()) / 2f;
centerY = (imageRootView.getTop() + imageRootView.getBottom()) / 2f;
// recalculate coordinates of starting point
startX = e.getRawX() - imgPhotoEditorPush.getX() + centerX;
startY = e.getRawY() - imgPhotoEditorPush.getY() + centerY;
// get starting distance and scale
startR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
startScale = imageRootView.getScaleX();
int[] locationOfLayout = new int[2];
int[] locationOfDrag = new int[2];
imageRootView.getLocationOnScreen(locationOfLayout);
imgPhotoEditorPush.getLocationOnScreen(locationOfDrag);
firstPointX = locationOfLayout[0];
firstPointY = locationOfLayout[1];
float secondPointX = e.getRawX();
float secondPointY = e.getRawY();
zeroAngle = findRotation(firstPointX, firstPointY, secondPointX, secondPointY); // remember
// "zero"
// angle
startAngle = imageRootView.getRotation(); // remember angle at
// which layout is
// rotated at the start
} else if (e.getAction() == MotionEvent.ACTION_MOVE) {
// calculate new distance
float newR = (float) Math.hypot(e.getRawX() - startX, e.getRawY() - startY);
// set new scale
float newScale = newR / startR * startScale;
imageRootView.setScaleX(newScale);
imageRootView.setScaleY(newScale);
// move handler image
imgPhotoEditorPush.setX(centerX + imageRootView.getWidth() / 2f * newScale);
imgPhotoEditorPush.setY(centerY + imageRootView.getHeight() / 2f * newScale);
imageRootView.setRotation(findRotation(firstPointX, firstPointY, e.getRawX(), e.getRawY()) - zeroAngle + startAngle); // rotate relative to start and zero
// angle
}
else if (e.getAction() == MotionEvent.ACTION_UP)
{
}
return true;
}
});
Please help me.Thaks.

Scale a layout to match parent with animation

In my sample project i have a linear layout, its height is set to wrap content in xml and there is also a fragment below it which takes all the remaining space. The fragment contains a button which when clicked will remove the fragment and the height of the linear layout is set to match parent. I tried adding android:animateLayoutChanges="true" but the transition from wrap_content to match_parent is not smooth. How can i animate from android:layout_height="wrap_content" to android:layout_height="match_parent"
Here is the layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg"
android:orientation="vertical"
android:id="#+id/layoutRoot"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/cloudHolder"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:gravity="center"
android:layout_height="wrap_content">
<ImageButton
android:layout_width="100dp"
android:layout_gravity="center"
android:layout_height="100dp"
android:background="#drawable/play"/>
</LinearLayout>
#tdjprog Answer with some edit
1 - Stritch
private void animateViewTostritch_height(final View target) {
int fromValue = 0;
// int fromValue = target.getHeight();
// int toValue = ((View) target.getParent()).getHeight();// matchparent
int toValue = (int) getResources().getDimension(R.dimen.dialog_header_height);//spesific hight
// int toValue = (int) (getResources().getDimension(R.dimen.dialog_header_height) / getResources().getDisplayMetrics().density);
ValueAnimator animator = ValueAnimator.ofInt(fromValue, toValue);
animator.setDuration(2000);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
target.getLayoutParams().height = (int) animation.getAnimatedValue();
target.requestLayout();
}
});
animator.start();
}
Call animateViewTostritch_height(your_View);
2 - Scale %
public void scaleView(View v, float startScale, float endScale) {
Animation anim = new ScaleAnimation(
1f, 1f, // Start and end values for the X axis scaling
startScale, endScale, // Start and end values for the Y axis scaling
Animation.RELATIVE_TO_SELF, 0f, // Pivot point of X scaling
Animation.RELATIVE_TO_SELF, 1f); // Pivot point of Y scaling
anim.setFillAfter(true); // Needed to keep the result of the animation
anim.setDuration(1000);
v.startAnimation(anim);
}
Call scaleView(your_View,0f,10f); // 10f match parent
You may need to try adding android:animateLayoutChanges="true" in the parent layout itself like for example:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bg"
android:orientation="vertical"
android:animateLayoutChanges="true"
android:id="#+id/layoutRoot"
tools:context=".MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:id="#+id/cloudHolder"
android:orientation="vertical"
android:gravity="center"
android:layout_height="wrap_content">
<ImageButton
android:layout_width="100dp"
android:layout_gravity="center"
android:layout_height="100dp"
android:background="#drawable/play"/>
</LinearLayout>
</LinearLayout>
If the above code doesn't work, you might need to take a look at:
Animation of height of LinearLayout container with ValueAnimator
Or
Animation in changing LayoutParams in LinearLayout
I think relying on animateLayoutChanges isn't a good idea. Try below code instead.
import android.view.ViewPropertyAnimator;
// In your activity
private int parentHeight;
private int childHeight;
private float childScaleFactor;
//In onCreate()
mChildView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
parentHeight = mParentView.getMeasuredHeight();
childHeight = mChildView.getMeasuredHeight();
childScaleFactor = parentHeight/childHeight;
}
});
mChildView.animate()
.scaleY(childScaleFactor)
.setDuration(500)
.start();
If this doesn't work, refer to this answer on another post
try this:
private void animateViewToMatchParent(final View target) {
int fromValue = target.getHeight();
int toValue = ((View) target.getParent()).getHeight();
ValueAnimator animator = ValueAnimator.ofInt(fromValue, toValue);
animator.setDuration(250);
animator.setInterpolator(new DecelerateInterpolator());
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
target.getLayoutParams().height = (int) animation.getAnimatedValue();
target.requestLayout();
}
});
animator.start();
}

Android - perfomance animation on canvas

I created simple animation in CustomView to transition beetwen activities. Everything is fine except animation smooth. There are visible lags when circle radius is increased. How can I performance animation to avoid lags?
public class CircleAnimationView extends View {
...
public void startAnimation(int x, int y) {
startX = x;
startY = y;
baseAnimator = ObjectAnimator.ofFloat(this, "baseRadius", 0, maxRadius)
.setDuration(1000);
baseAnimator
.setInterpolator(new AccelerateDecelerateInterpolator());
baseAnimator.start();
finalAnimator = ObjectAnimator.ofFloat(this, "finalRadius", 0, maxRadius)
.setDuration(2000);
finalAnimator
.setInterpolator(new AccelerateDecelerateInterpolator());
if(listener!=null)
finalAnimator.addListener(listener);
finalAnimator.start();
}
public void setBaseRadius(final float radius) {
radiusBase = radius;
invalidate();
}
public void setFinalRadius(final float radius) {
radiusFinal = radius;
invalidate();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (isInEditMode()) {
return;
}
canvas.drawCircle(startX, startY, radiusBase, basePaint);
canvas.drawCircle(startX, startY, radiusFinal, finalPaint);
}
};
I used view in xml:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="#+id/content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
</RelativeLayout>
<pl.org.ldi.challenge.views.CircleAnimationView
android:id="#+id/circle_animation"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:base_color="#color/blue"
app:final_color="#color/white"/>
</RelativeLayout>
Edit:
I check .trace file from animation, and it looks like that drawing large circle takes too much time - method GLES20Canvas.nDrawDisplayList
After set:
finalAnimator.setFrameDelay(0);
baseAnimator.setFrameDelay(0);
animation looks smoothly. Thanks for advice!
You can use a handler to call invalidate by help of its postDelayed() method. Call this methods at regular intervals throughout your animations duration. You can calculate the radius according by the ratio of current_time/total_time and multiplied with the maximim radius you want.

android image view scale animation

hi im wanting to know how to scale animate a logo and move its position?
i have an if statement that runs some checks and then when its done i want it to scale down an image view (logo) and move it up.
heres my layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:background="#drawable/bg_default" >
<ImageView
android:id="#+id/su_logo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="34dp"
android:src="#drawable/su_logo"
android:contentDescription="#string/cd_su_logo"/>
<ImageView
android:id="#+id/su_shirts"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:src="#drawable/su_shirts"
android:contentDescription="#string/cd_su_shirts" />
</RelativeLayout>
heres my java
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_initialsetup);
preChecks();
}
public void preChecks(){
//check for internet connection
//check version
String curVersion = getResources().getString(R.string.app_versionCode);
int curVer = Integer.parseInt(curVersion);
String LiveVersion = "100";
int liveVer = Integer.parseInt(LiveVersion);
if(curVer < liveVer) Log.v("setup", "There is a new version");
else {
//scale animation
}
}
You can do that by applying ScaleAnimation and TranslateAnimation together in AnimationSet
// Scaling
Animation scale = new ScaleAnimation(fromXscale, toXscale, fromYscale, toYscale, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
// 1 second duration
scale.setDuration(1000);
// Moving up
Animation slideUp = new TranslateAnimation(fromX, toX, fromY, toY);
// 1 second duration
slideUp.setDuration(1000);
// Animation set to join both scaling and moving
AnimationSet animSet = new AnimationSet(true);
animSet.setFillEnabled(true);
animSet.addAnimation(scale);
animSet.addAnimation(slideUp);
// Launching animation set
logo.startAnimation(animSet);

Categories

Resources