I tried to do a simple animation from bottom left corner to right center and then to center of the screen
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidthPx = size.x;
screenHeightPx = size.y;
final TranslateAnimation slideFromRight = new TranslateAnimation(screenWidthPx, screenWidthPx/2, screenHeightPx, screenHeightPx);
slideFromRight.setInterpolator(new AccelerateDecelerateInterpolator());
slideFromRight.setStartOffset(300);
slideFromRight.setDuration(600);
slideFromRight.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
TranslateAnimation titleIconSlideUp = new TranslateAnimation(0, screenWidthPx/2, screenHeightPx, screenHeightPx/2);
titleIconSlideUp.setInterpolator(new AccelerateDecelerateInterpolator());
titleIconSlideUp.setStartOffset(500);
titleIconSlideUp.setFillAfter(true);
titleIconSlideUp.setDuration(1000);
tvAnimView.startAnimation(titleIconSlideUp);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
tvAnimView.startAnimation(slideFromRight);
the second animation inside onAnimationEnd is working fine. But don't know why first animation is not working fine. where my layout is simple
<?xml version="1.0" encoding="utf-8"?>
<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/rl_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipChildren="false"
android:clipToPadding="false"
tools:context="broadpeak.animationlearning.AnimTestActivity">
<TextView
android:id="#+id/tv_anim_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
android:textColor="#color/colorPrimaryDark"
android:textSize="24sp" />
</RelativeLayout>
You should start your animation using this line:
tvAnimView.startAnimation(slideFromRight);
Just put this piece of code in click listener or onCreate(), onResume() methods, according to your needs.
Related
Here is what I could achieve:
package game.card.translationproblem;
import androidx.appcompat.app.AppCompatActivity;
import android.animation.AnimatorInflater;
import android.animation.AnimatorSet;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
public class MainActivity extends AppCompatActivity {
ImageView ball;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main_layout);
ball = findViewById(R.id.coloured_ball);
ball.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(MainActivity.this, R.animator.move_the_ball);
set.setTarget(ball);
set.start();
}
});
}
}
Here is the animation file:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<objectAnimator
android:propertyName="translationY"
android:valueFrom="0dp"
android:valueTo="-500dp"
android:duration="5000"/>
<objectAnimator
android:propertyName="translationY"
android:valueFrom="320dp"
android:valueTo="0dp"
android:duration="5000"
android:startOffset="5000"/>
</set>
And here is the layout file:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="700dp"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="#+id/coloured_ball"
android:layout_width="138dp"
android:layout_height="141dp"
android:gravity="center"
app:srcCompat="#drawable/ball" />
</LinearLayout>
</LinearLayout>
I want to perform a translation along the screen so that any portion of the image that goes past the upper edge of the screen immediately shows up from the bottom of the screen.
I thought of using 2 identical images and show one from the bottom at the same time while the other is disappearing from the upper edge but the major objection to this solution is that I can not guarantee the size of the screen and I might just be showing two full images at the same time.
could create the animation via the screen sizeļ¼
void moveBall(){
// getScreenHeight
Display display = getDisplay();
Point outSize = new Point();
display.getSize(outSize);
int height = outSize.y;
//create animator via height
Animation animator = new TranslateAnimation(0F, 0F, 0F, -(height / 2 + ball.getMeasuredHeight()));
animator.setDuration(2000);
animator.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
Animation animator = new TranslateAnimation(0F, 0F, +(height / 2 + ball.getMeasuredHeight()), 0F);
animator.setDuration(2000);
ball.startAnimation(animator);
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
ball.startAnimation(animator);
}
I have a view that looks like this:
https://i.stack.imgur.com/zKe01.png
When clicked, I want to animate the grey background color so that it slides from the right side to 50% of its initial width:
https://i.stack.imgur.com/s96BX.png
Here is the relevant portion of the layout xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/content_view"
android:layout_width="match_parent"
android:layout_height="44dp"
android:layout_marginBottom="4dp">
<androidx.constraintlayout.widget.Guideline
android:id="#+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="1.0"/>
<View
android:id="#+id/background"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="#+id/guideline"
android:background="#drawable/background" />
</androidx.constraintlayout.widget.ConstraintLayout>
I've tried the following:
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
ConstraintSet constraintSet = new ConstraintSet();
constraintSet.clone(contentView);
constraintSet.setGuidelinePercent(guideline.getId(), 0.5f);
TransitionManager.beginDelayedTransition(contentView);
constraintSet.applyTo(contentView);
}
});
But instead of the background color sliding from the right to the left (100% to 50%), it sort of just cross-fades.
What am I doing wrong? How would I change my code so the animation SLIDES the background color when the guideline percent changes?
You can use android.animation.ValueAnimator to change the percentage value of your guideline inside your constraintLayout, the code would be like this:
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// initialize your guideline
// Guideline guideline = findViewById ....
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1.0f, 0.5f);
// set duration
valueAnimator.setDuration(1000);
// set interpolator and updateListener to get the animated value
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
// update guideline percent value through LayoutParams
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ConstraintLayout.LayoutParams lp = (ConstraintLayout.LayoutParams) guideline.getLayoutParams();
// get the float value
lp.guidePercent = (Float) animation.getAnimatedValue();
// update layout params
guideline.setLayoutParams(lp);
}
});
valueAnimator.start();
}
});
I have an Imageview inside a FrameLayout (both have Layout_margins),also i got my custom FrameLayout(same with Layout_margins).
So what i have now:
Source code(.axml):
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#ffff363c"
android:layout_weight="100"
android:clickable="true">
<FrameLayout
android:id="#+id/MainFrameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center"
android:layout_weight="80">
<FrameLayout
android:id="#+id/SourceFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="10dp">
<ImageView
android:src="#android:drawable/ic_menu_camera"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/Img"
android:layout_margin="10dp" />
</FrameLayout>
<CustomFrameLayout
android:id="#+id/CustomView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
android:layout_margin="10dp" />
</FrameLayout>
</LinearLayout>
And what i want exactly(programmatically rotation left,right via button):
So my main goal is to rotate properly image(and CustomFrameLayout too),also i need to store my source Width/Height of image.How can i achieve this?
I tried to set scaleType.center / scaletype.centerInisde , but that is wrong idea.
Any suggestions? Thanks!
Don't know if i exactly understand your problem.
If u want programmatically rotate something u can try this:
ImageView image.animate().rotation(90).start();
or this
FrameLayout frame.animate().rotation(90).start();
or both.
To store Width/Height u can use
int image_h = image.getHeight();
int image_w = image.getWidth();
Better late than never.
I was facing the exactly same problem.
After some trying, I came with this solution:
private void rotateImageBy90(){
imageView.animate()
.rotation(90)
.setInterpolator(new AccelerateDecelerateInterpolator())
.setDuration(250)
.setListener(rotateListener)
.start();
Log.d("chatImage", "Rotating image by "+90+" degrees clockwise");
}
Declare an AnimatorListener, the one that solves the problem:
Animator.AnimatorListener rotateListener = new Animator.AnimatorListener() {
#Override
public void onAnimationStart(Animator animator) {
}
#Override
public void onAnimationEnd(Animator animator) {
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) imageView.getLayoutParams();
params.height = FrameLayout.LayoutParams.MATCH_PARENT;
params.width = FrameLayout.LayoutParams.MATCH_PARENT;
imageView.setLayoutParams(params);
imageView.requestLayout();
//This is the trick: I get the current bitmap, rotate it
Bitmap newBitmap = rotateImage(((BitmapDrawable)imageView.getDrawable()).getBitmap(),90);
//Then, rotate the imageview back to it's original position, without animation
imageView.setRotation(0);
//As I set the new, rotate bitmap, to it.
imageView.setImageBitmap(newBitmap);
}
#Override
public void onAnimationCancel(Animator animator) {
}
#Override
public void onAnimationRepeat(Animator animator) {
}
};
The rotateImage method:
public static Bitmap rotateImage(Bitmap source, float angle) {
Matrix matrix = new Matrix();
matrix.postRotate(angle);
return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix,
true);
}
After apply this animation to my (chield)RelativeLayout, my backgroud image has the good size but my Layout seem to continue to take to much place on my Page (parent)RelativeLayout. Some idea?
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true" >
<scale
android:fromXScale="1.0"
android:fromYScale="1.0"
android:toXScale="0.2"
android:toYScale="0.2"
android:duration="700"
>
</scale>
</set>
<RelativeLayout ...>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/chieldLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/bigImage"
>
<Button
style="#style/boutonBrun"
android:id="#+id/btPanier"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/full22lightgreen"
/>
</RelativeLayout>
</RelativeLayout>
I have add like you propose me a listener to fit my layout with this command :
params.width = (int) getResources().getDimension(R.dimen.size_width);
how can I know the "size_width" that I have to put? Like I ask to scale from 1.0 to 0.2 and finaly put android:layout_width="300dp", I have imagine that "size_width" have to take 60dp (300 * 0.2) but it's very to small compare to size after the animation.
Use animation listener like this
animation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
// set height for your relative layout here
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
I'm not sure if i understand your problem correctly but you can add an animation listener to your animation:
yourAnimation.setAnimationListener(new Animation.AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
}
#Override
public void onAnimationRepeat(Animation animation) {
}
});
And in onAnimationEnd try to invalidate your view.
yourView.invalidate();
Finally, I just stop to use the param android:fillAfter="true", he seem to don't change the size of the layout... I just change size of my layout with onAnimationEnd.
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) myRelativeLayout.getLayoutParams();
params.width = (int) getResources().getDimension(R.dimen.little_house_width);
params.height = (int) getResources().getDimension(R.dimen.little_house_height);
setLayoutParams(params);
I have two views on the screen
one sits at the top of the screen and on sits directly below it
I need the green view to slide out the top - and make the blue view take up the entire screen as a result
this is what i am trying to do:
-- the problem is , when the animation is finished, the blue view just "jumps" up - and i want it to ease up with the disappearing green view, how do i do that?
slide_in_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1000"
android:fromYDelta="-100%"
android:toYDelta="0%" />
</set>
slide_out_animation.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="1000"
android:fromYDelta="0%"
android:toYDelta="-100%" />
</set>
MainActivity.java
slideInAnimation = AnimationUtils.loadAnimation(mActivity, R.anim.slide_in_animation);
slideOutAnimation = AnimationUtils.loadAnimation(mActivity,R.anim.slide_out_animation);
slideInAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
mGreenView.setVisibility(View.VISIBLE);
}
#Override
public void onAnimationRepeat(Animation animation) {
// TODO Auto-generated method stub
}
#Override
public void onAnimationEnd(Animation animation) {
}
});
slideOutAnimation.setAnimationListener(new AnimationListener() {
#Override
public void onAnimationStart(Animation animation) {
}
#Override
public void onAnimationEnd(Animation animation) {
mGreenView.setVisibility(View.GONE);
}
#Override
public void onAnimationRepeat(Animation animation) {
// To change body of implemented methods use File | Settings
// | File Templates.
}
});
This worked for me
First you must import this library: http://nineoldandroids.com/
The import is done by importing existing android project into your workspace, afterwards right click your Poject -> Properties -> Android. Here you will see a library section, click the Add button and add the nineoldandroids library.
First off, here is the layout xml used for this to work:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/parentLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >
<FrameLayout
android:id="#+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<ListView
android:id="#+id/listView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#android:color/transparent"
android:divider="#android:color/transparent"
android:fastScrollEnabled="false"
android:listSelector="#android:color/transparent"
android:scrollbars="vertical"
android:smoothScrollbar="true" />
<View
android:id="#+id/greenView"
android:layout_width="match_parent"
android:layout_height="150dp"
android:background="#ff00ff00"
android:alpha="0"/>
</FrameLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="#+id/animate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickHandler"
android:text="animate" />
<Button
android:id="#+id/close"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="clickHandler"
android:text="close" />
</LinearLayout>
Notice: Both the ListView and the green View could be layouts of any types with any kind of content.
And next a proof of concept Activity.
public class TestActivity extends Activity {
private View greenView;
private ListView listView;
private int greenHeight;
private boolean isShowingBox;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_test);
// The animated view
greenView = (View)findViewById(R.id.greenView);
listView = (ListView)findViewById(R.id.listView1);
// Instanciating an array list (you don't need to do this, you already have yours)
ArrayList<String> your_array_list = new ArrayList<String>();
your_array_list.add("1");
your_array_list.add("2");
your_array_list.add("3");
your_array_list.add("4");
your_array_list.add("5");
your_array_list.add("6");
your_array_list.add("7");
your_array_list.add("8");
your_array_list.add("9");
your_array_list.add("10");
your_array_list.add("11");
your_array_list.add("12");
your_array_list.add("13");
your_array_list.add("14");
your_array_list.add("15");
// This is the array adapter, it takes the context of the activity as a first // parameter, the type of list view as a second parameter and your array as a third parameter
ArrayAdapter<String> arrayAdapter =
new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, your_array_list);
listView.setAdapter(arrayAdapter);
final LinearLayout layout = (LinearLayout)findViewById(R.id.parentLayout);
final ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT < 16) {
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
} else {
layout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
greenHeight = greenView.getHeight();
}
});
}
public void clickHandler(View v) {
if (isShowingBox) {
isShowingBox = false;
slideOut(1500, 0);
} else {
isShowingBox = true;
slideIn(1500, 0);
}
}
private void slideIn(int duration, int delay) {
AnimatorSet set = new AnimatorSet();
set.playTogether(
// animate from off-screen in to screen
ObjectAnimator.ofFloat(greenView, "translationY", -greenHeight, 0),
ObjectAnimator.ofFloat(listView, "translationY", 0, greenHeight),
ObjectAnimator.ofFloat(greenView, "alpha", 0, 0.25f, 1)
// add other animations if you wish
);
set.setStartDelay(delay);
set.setDuration(duration).start();
}
private void slideOut(int duration, int delay) {
AnimatorSet set = new AnimatorSet();
set.playTogether(
// animate from on-screen and out
ObjectAnimator.ofFloat(greenView, "translationY", 0, -greenHeight),
ObjectAnimator.ofFloat(listView, "translationY", greenHeight, 0),
ObjectAnimator.ofFloat(greenView, "alpha", 1, 1, 1)
// add other animations if you wish
);
set.setStartDelay(delay);
set.setDuration(duration).start();
}
}
Important note: Remember to import the AnimatorSet and ObjectAnimator from nineoldandroids in your class and not the Android SDK ones!!!
One potential solution that makes a nice and fluid exit is using the weight attribute of LinearLayout with a ValueAnimator. Assuming you're using LinearLayout as your parent view for your green and blue blocks, your code would look something like this.
layout.xml
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<!--Let's assume this is the view you wish you disappear-->
<View
android:id="#+id/view1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical"/>
<View
android:id="#+id/view2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2"/>
</LinearLayout>
Now with this, in your code you can use the ValueAnimator as follows:
public class MainActivity extends Activity implements AnimatorUpdateListener
{
View view1;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
view1 = (View)findViewById(R.id.view1);
}
public void someAction()
{
//This is the important part, because it is FROM the first value TO
//the second. Notice that it must be a float type
ValueAnimator anim = ValueAnimator.ofFloat(1f, 0f);
anim.setDuration(200);
anim.addUpdateListener(this);
anim.start();
}
#Override
public void onAnimationUpdate(ValueAnimator animation)
{
view1.setLayoutParams(new LinearLayout.LayoutParams(0,
LayoutParams.MATCH_PARENT,
(Float) animation.getAnimatedValue()));
}
}
The ValueAnimator will automatically calculate the increments and execute them to get the smooth transition you want with the added benefit of keeping your view running.
You may also need to handle some strange UI occurrences as a result of shrinking the view (i.e., TextViews may act funny on the transition out), but I didn't run into too much trouble patching those up and keeping it neat.
Good luck! Hope this helps.
Use following code.
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true">
<scale
android:duration="500"
android:fromXScale="1.0"
android:fromYScale="0.0"
android:interpolator="#android:anim/linear_interpolator"
android:toXScale="1.0"
android:toYScale="1.0" />
</set>