RecyclerView Animators

https://github.com/wasabeef/recyclerview-animators

Android View Animations

https://github.com/daimajia/AndroidViewAnimations

android-flip

https://github.com/openaphid/android-flip

android-pagecurl

https://github.com/harism/android-pagecurl

Android Sliding Activity Library

https://github.com/klinker41/android-slidingactivity

android animation의 종류로는 기본적으로 3가지가 있다.

1. frame animation

2. tween animation (view animation)

3. property animation

.

.

.

.

.

.

.

.

frame animation

frame animation은 xml화일에 <animation-list> 와 <item>을 이용하여 만든다. 이를 ImageView에 src에 연결한다. 코드상에서는 ImageView를 통해서 AnimationDrawable obj형태로 받아오게된다.

res/drawable에 xml 형태로 저장된다.

참조) android docs AnimationDrawable https://developer.android.com/reference/android/graphics/drawable/AnimationDrawable

예시코드)

<!-- Animation frames are wheel0.png through wheel5.png
     files inside the res/drawable/ folder -->
 <animation-list android:id="@+id/selected" android:oneshot="false">
    <item android:drawable="@drawable/wheel0" android:duration="50" />
    <item android:drawable="@drawable/wheel1" android:duration="50" />
    <item android:drawable="@drawable/wheel2" android:duration="50" />
    <item android:drawable="@drawable/wheel3" android:duration="50" />
    <item android:drawable="@drawable/wheel4" android:duration="50" />
    <item android:drawable="@drawable/wheel5" android:duration="50" />
 </animation-list>
// Load the ImageView that will host the animation and
 // set its background to our AnimationDrawable XML resource.
 ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
 img.setBackgroundResource(R.drawable.spin_animation);

 // Get the background, which has been compiled to an AnimationDrawable object.
 AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();

 // Start the animation (looped playback by default).
 frameAnimation.start();

.

.

.

.

.

.

.

.

tween animation (view animation)

  • view의 display형태만 바꾸는 방법이며 실제로 view의 위치는 바뀌지 않는다. 사용자가 이동된 위치에서 터치를 해도 반응하지 않는다. 
  • animation은 translate, scale, rotate, alpha 4가지가 있다.
  • xml 형태로 만든 animation은 res/anim 폴더안에 넣는다.
  • tween animation은 view, drawable (ShapeDrawable, BitmapDrawable), layout에 적용가능하다.
  • tween animation은 내부적으로 Matrix, Transformation class를 사용한다. 
  • AnimationUtils의 loadAnimation()를 이용해서 xml형태의 Animation을 가져온다.

tween animation에서 만들때 사용가능한 animation tag들은 아래와 같다.

image
image

.

.

image
image
image
image

.

.

<set>을 이용하여 여러가지 animation을 동시에 구현할수 있다.

image
image
image
image

.

.

일반적으로 사용되는 위의 4가지 animation이 아닌 다른 움직임을 구현하기 위해서는 custom animation을 이용한다. 이는 Animation을 extends하고 필요한 method를 override해서 구현한다.

image

.

.

xml형태로 만들어진 tween animation은 layoutAnimation에 적용가능하다. layoutAnimation을 이용하면 layout내의 view들이 처음 등장할때 animation대로 등장하게된다.

https://youtu.be/qMQar9UNqjU?t=2311

image

.

.

activity간 전환에 적용되는 animation도 tween animation (view animation) 이다.

app 내에서 모든 window의 생성, 사라짐에 사용되는 animation를 지정할때는 theme에서 사용될 view animation을 지정해 주면된다.

image
image

단하나 주의점은 animation의 작동시간을 지정해도 0.25초안에 마무리 되게 된다. 

image
image

.

.

fragment 전환간 animation에도 tween animation (view animation)이 사용된다.

image
image

.

.

추가적으로 ViewSwitcher (TextSwitcher, ImageSwitcher), ViewFlipper는 tween animation (view animation)을 이용한다. 맨 아래부분 참조

.

.

.

.

.

.

.

.

property animation

ValueAnimator, ObjectAnimator를 이용하는 방법이 있다. 기본적으로 ObjectAnimator는 ValueAnimator를 기반으로 extends 해서 만들어졌다.

ValueAnimator는 특정범위에안에서 변화된 값을 만들어낸다. 이때 addUpdateListener를 통해 연결된 listener에서 onAnimationUpdate() 안에서 변화되는 값에 접근할수 있다.

Animator, ObjectAnimator를 xml로 만드는 경우에는 res/animator에 만든다.

아래는 code에서 ValueAnimator를 이용한 경우

image

.

아래는 xml를 이용한 ValueAnimator 경우

image
image

.

ObjectAnimator를 code에서 이용하는 법과 xml을 통해 이용하는 방법을 보여주고 있다.

image
image

.

.

animator 를 이용한 animation을 AnimatorSet으로 묶어서 순서를 가지고 수행하거나 동시에 수행하는 방법을 설명하고 있다.

image
image

.

.

Animator를 이용해서 layout내의 view가 등장하거나 사라지거나 다른 view가 등장 사라짐에따라 위치가 변경되는 경우에 사용되는 animation을 만들수 있으며 이를 LayoutTransition이라고 한다.

image

.

.

Animator를 이용한 animation인데 기존의 경우 ValueAnimator가 특정범위에안에서 변화된 값을 만들어내고 addUpdateListener를 통해 연결된 listener에서 onAnimationUpdate() 안에서 변화되는 값을 통해 view의 속성값을 변화시켰다. 아래의 경우도 같은 효과를 가진다. 다만 ViewPropertyAnimator (support library를 사용한겨우 ViewPropertyAnimatorCompat)를 생성하기위해 View.animate (또는 support 라이브러리의 경우 ViewCompat.animate) 에 속성값을 animate할 view를 arg로 받게 된다.

image
image

.

.

RecyclerView내의 item이 생성되거나 사라질때 애니메이션을 이용할수 있는데 이때에도 Animator를 기반으로한 property animation을 사용한다. 

참조 영상 ) RecyclerView 내의 item 생성소멸시 animation 사용예 https://youtu.be/8sQmuafiaAQ?t=220  

image
image

.

.

AdapterViewAnimator, AdapterViewFlipper, StackView는 property animator를 기반으로 하고 있다.

.

.

.

.

.

이름이 ViewAnimator이지만 기본적으로 ViewSwitcher (TextSwitcher, ImageSwitcher), ViewFlipper는 tween animation (view animation)을 이용한다.

AdapterViewAnimator, AdapterViewFlipper, StackView는 property animator를 기반으로 하고 있다.

실제 사용 예시)

https://youtu.be/kRSIWh4WlMc?t=365

DrawerLayout 

의 사용예시를 보여준다.  DrawerLayout은 화면 양 옆에서 서랍처럼 등장하는 추가 layout을 만들수 있게 해준다. 이는 단순히 layout의 구조만을 만든다. 양쪽에서 등장하는 내용과는 무관하다. 이 서랍에 해당하는 부분에 NavigationView를 만들어 넣으면 아래와 같이 만들수 있다.  

NavigationView

는 menu xml화일을 이용해서 navigation menu를 생성한다. 

Navigation drawer template

은 아래 그림과 같이 android studio에서 주어지는 template이다.이를 통해 NavigationView, DrawerLayout 를 종합으로 사용한 구조를 만들수 있게 된다.

original source : https://ranyalbegwein.silvrback.com/transforming-image-behavior

참고자료 ) https://www.androidauthority.com/using-coordinatorlayout-android-apps-703720/

coordinatorlayout을 이용해서 구현가능한 작업 예시

1. Intro

A CoordinatorLayout is this thing:

public class CoordinatorLayout extends ViewGroup implements NestedScrollingParent {
    ... 
}

from the support library ( compile 'com.android.support:design:25.3.1' ), which seems at first like an innocent old FrameLayout, until you discover its real powers – Behaviors!

CoordinatorLayout는 기본적으로 FrameLayout이다. 

A Behavior is an object attached to a child of a CoordinatorLayout, which defines its interaction with another View, ( a dependency) within the same layout.

CoordinatorLayout 아래에 있는 한 element가 다른 View(dependency라고 불리는) 의 변화에 따라 어떻게 변화할것인지를  정의하고 있는 object가 Behavior 이다. 상태변화가 관찰되어지는 View를 dependency라고 한다. 

So, a CoordinatorLayout monitors every movement of its children, and notifies the ones with attached Behaviors for a dependency change.

Something like this:

The SnackBar here is called a dependency – which makes sense, because the child depends on its movement in order to behave in a certain way specified by its attached Behavior.

Following Material Design guidelines, this behavior is the correct interaction between a SnackBar and a FloatingActionButton.

2. Let’s get started!

Everything should run in a context or under the supervision of a CoordinatorLayout, so let’s create a fresh Activity with a CoordinatorLayout as its content-view root element.

Create a new project, and add a new Activity by selecting the “Basic Activity” template:

Take a look at activity_main.xml, it should contain the following:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.rany.albeg.wein.behaviors.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_height="wrap_content"
        android:layout_width="match_parent"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

Since the default behavior of FloatingActionButton is to run away from the SnackBar like we wish to implement ourselves, take it off of the XML tree and insert something like an AppCompatButton:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout>

     ...

    <android.support.v7.widget.AppCompatButton
        android:id="@+id/bt_click_me"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="16dp"
        android:text="Click me"/>

</android.support.design.widget.CoordinatorLayout>

Edit MainActivity accordingly, and modify onCreate():

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        AppCompatButton btn = (AppCompatButton) findViewById(R.id.bt_click_me);
        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Yeah buddy!", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });
    }

3. Implementation

To create a Behavior we’ll need to create a class that extends CoordinatorLayout.Behavior<V>where V is a type of a class which extends View and represents the type of the child – in our case it’ll be AppCompatButton:

public class CustomMoveUpBehavior extends 
                                  CoordinatorLayout.Behavior<AppCompatButton> {
    ...
}

We’re almost done! To complete programming our custom behavior and define the unique interaction between a child and a dependency, we’ll need to:

  • Override layoutDependsOn(...)

This method gets called ( at least once in response to a layout request ) by the parent CoordinatorLayout to determine whether the supplied child view has another specific sibling view as a layout dependency.
In other words, CoordinatorLayout sees the SnackBar and asks us :

“Hey, is this AppCompatButton depends on this SnackBar ?” and we should answer “Yes!” in order to further react in accordance to SnackBar’s movement:

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent,
                                   AppCompatButton child,
                                   View dependency) {

        return dependency instanceof Snackbar.SnackbarLayout;
    }

위의 코드를 설명하면 CoordinatorLayout내의 element 상태가 변화하면 CoordinatorLayout는 layoutDependsOn()를 통하여 View obj인 dependency가 Snackbar.SnackbarLayout instance인지 확인한다. 맞으면 true를 return한다. CoordinatorLayout는 자신의 모든 child element를 이 함수layoutDependsOn()에 넣어 해당 View가 dependency가 맞는지 아닌지 확인한다. 사실 layoutDependsOn()는 상태 변화에도 호출되지만 최초로 화면이 구성될때도 호출된다.

  • Override onDependentViewChanged(...)

This method gets called by the parent CoordinatorLayout after the relevant layoutDependsOn(...)returns true, in which we need to actually move stuff!

In our case, for the button to run away from the SnackBar, we’ll want to translate its Y position to be the difference between SnackBar’s current Y translation and its height!

    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent,
                                          AppCompatButton child,
                                          View dependency) {

        float tY = dependency.getTranslationY() - dependency.getHeight();
        child.setTranslationY(tY);
        return true;
    }

위위의 코드 layoutDependsOn 의 과정을 거쳐 dependency의 변화가 관측되었다면 onDependentViewChanged()에 전달된 상태변화가 감지된 dependency와 그에 따라 조정이 필요한 child view를 함수내에서 조정한다.  

We return true to say: “Hey CoordinatorLayout! Our Behavior changed AppCompatButton’s position”

CustomMoveUpBehavior is done and ready to be attached!

There are several ways to attach a Behavior to View, and I’ll choose to go with the common way – via XML.

In order to attach CustomMoveUpBehavior to AppCompatButton via XML, add the following constructor first:

public CustomMoveUpBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
}

and now jump into activity_main.xml and just add the following attribute to AppCompatButton’s XML tag:

    <android.support.v7.widget.AppCompatButton
    ...
        app:layout_behavior="your.package.name.CustomMoveUpBehavior"
    ...
    />

replacing your.package.name as necessary.

original source : https://proandroiddev.com/how-to-animate-on-android-f8d227135613

위 페이지에서는 물리를 이용, pathinterpolator를 이용한 경우도 설명한다.

https://youtu.be/iZ4spzwjt8E

15:36 layout transition animation 은 layout내에 있는 view가 생성되거나 삭제될때 사용되는 transition animation을 말한다. 

 23:17 activity transition animation은 한 activity에서 다른 activity로 전환될대 사용되는 transition animation을 말한다. 

25:12 fragment 전환 animation은 fragment 생성, 제거, 교환, backstack에서 pop 시에 사용되는 animation을 말한다. 

 TextSwitcher 예시 https://youtu.be/Aybw0wDeaSQ 

ImageSwitcher 예시 https://youtu.be/WS1Ta_S3WYI?t=788 

ViewFlipper 예시 https://youtu.be/2c-GbJ-c_eA 

AdapterViewFlipper 예시 https://youtu.be/2jiiUqlKCaQ

original source : https://github.com/harism/android-pagecurl

original source : https://github.com/openaphid/android-flip

android에서 activity 전환시 flip animation (책장 넘기는 듯한 애니메이션)을 구현하는 library