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를 기반으로 하고 있다.

실제 사용 예시)

Swift: Firebase 3 – How to Upload Images to Firebase Storage (Ep 5)

my review point is /10

https://youtu.be/b1vrjt7Nvb0?t=2m39s   adding gesture recognizer (image view의 경우 userInteractionEnabled 프로퍼티가 true로 설정되어야 한다.)

https://youtu.be/b1vrjt7Nvb0?t=5m25s   extension을 이용한 코드 정리 (함수외부로 빼내기)

https://youtu.be/b1vrjt7Nvb0?t=5m48s   사진 선택하는 controller 불러오기 ( UIImagePickerController , UIImagePickerControllerDelegate) 열려진 picker view controller는 dismissViewControllerAnimated를 이용해 닫는다.

https://youtu.be/b1vrjt7Nvb0?t=10m25s   allow picker editing (allowEditing 프로퍼티를 이용한다.) 

https://youtu.be/b1vrjt7Nvb0?t=15m28s   upload image to firebase  ( FIRStorage.storage().reference().putdata , UIImagePNGRepresentation)

https://youtu.be/b1vrjt7Nvb0?t=26m24s   uique string 만들기 ( NSUUID().UUIDString 를 이용해 만든다. )

https://youtu.be/b1vrjt7Nvb0?t=28m29s   firebase storage에 폴더 만들어서 이미지 저장하기

Swift: Firebase 3 – How to Upload Images to Firebase Storage (Ep 5)

my review point is /10

https://youtu.be/b1vrjt7Nvb0?t=2m39s   adding gesture recognizer (image view의 경우 userInteractionEnabled 프로퍼티가 true로 설정되어야 한다.)

https://youtu.be/b1vrjt7Nvb0?t=5m25s   extension을 이용한 코드 정리 (함수외부로 빼내기)

https://youtu.be/b1vrjt7Nvb0?t=5m48s   사진 선택하는 controller 불러오기 ( UIImagePickerController , UIImagePickerControllerDelegate) 열려진 picker view controller는 dismissViewControllerAnimated를 이용해 닫는다.

https://youtu.be/b1vrjt7Nvb0?t=10m25s   allow picker editing (allowEditing 프로퍼티를 이용한다.) 

https://youtu.be/b1vrjt7Nvb0?t=15m28s   upload image to firebase  ( FIRStorage.storage().reference().putdata , UIImagePNGRepresentation)

https://youtu.be/b1vrjt7Nvb0?t=26m24s   uique string 만들기 ( NSUUID().UUIDString 를 이용해 만든다. )

https://youtu.be/b1vrjt7Nvb0?t=28m29s   firebase storage에 폴더 만들어서 이미지 저장하기

GCD (grand central dispatch)

original source : https://blog.bobthedeveloper.io/intro-to-grand-central-dispatch-in-swift-3-with-bob-lee-1d4b56f731b3 

gcd에서는 기본적으로 두가지의 종류의 작업자를 제공한다. (하나는 많은 리소스를 필요로하는 작업에 적합하고(heavy) 하나는 좀더 약한 작업에 적합하다(lightweight). 사용자가 추가로 필요한 경우 lightweigth 작업자를 추가 만들수 있다.)

let main = DispatchQueue.main // heavy 작업자 만들기
let background = DispatchQueue.global() // ios에서 제공하는 lightweight 작업자 만들기
let helper = DispatchQueue(label: "construction_worker_3") // 추가로 lightweight 작업자 만들기
func doSyncWork() { 
background.sync { for _ in 1...3 { print(“Light”) } }
for _ in 1...3 { print(“Heavy”) } } // main
doSyncWork() 
// Light
// Light
// Light
// Heavy
// Heavy
// Heavy

func doAsyncWork() { 
background.async { for _ in 1...3 { print(“Light”) } }
for _ in 1...3 { print(“Heavy”) } }                // main
doAsyncWork() 
// Light
// Heavy
// Heavy
// Light
// Heavy
// Light
let asianWorker = DispatchQueue(label: "construction_worker_1")
let brownWorker = DispatchQueue(label: "construction_worker_2")
func doLightWork() {
asianWorker.async { for _ in 1...10 { print("?") } }
 brownWorker.async { for _ in 1...10 { print("??") } } }
doLightWork()
// ?, ??, ?, ??, ?, ??, ?, ??, ?...

함수형태의 gcd 이용 예시

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {  
    // Download file or perform expensive task

    dispatch_async(dispatch_get_main_queue()) {  
        // Update the UI  
    }
}

oop 형태의 gcd 이용 예시

DispatchQueue.global(qos: .userInitiated).async {  
    // Download file or perform expensive task

    DispatchQueue.main.async {  
        // Update the UI  
    }
}

core data 

managed object context

  • performBlock:  Asynchronously performs a given block on the context’s queue.
  • performBlockAndWait:  Synchronously performs a given block on the context’s queue.

GCD (grand central dispatch)

original source : https://blog.bobthedeveloper.io/intro-to-grand-central-dispatch-in-swift-3-with-bob-lee-1d4b56f731b3 

gcd에서는 기본적으로 두가지의 종류의 작업자를 제공한다. (하나는 많은 리소스를 필요로하는 작업에 적합하고(heavy) 하나는 좀더 약한 작업에 적합하다(lightweight). 사용자가 추가로 필요한 경우 lightweigth 작업자를 추가 만들수 있다.)

let main = DispatchQueue.main // heavy 작업자 만들기
let background = DispatchQueue.global() // ios에서 제공하는 lightweight 작업자 만들기
let helper = DispatchQueue(label: "construction_worker_3") // 추가로 lightweight 작업자 만들기
func doSyncWork() { 
background.sync { for _ in 1...3 { print(“Light”) } }
for _ in 1...3 { print(“Heavy”) } } // main
doSyncWork() 
// Light
// Light
// Light
// Heavy
// Heavy
// Heavy

func doAsyncWork() { 
background.async { for _ in 1...3 { print(“Light”) } }
for _ in 1...3 { print(“Heavy”) } }                // main
doAsyncWork() 
// Light
// Heavy
// Heavy
// Light
// Heavy
// Light
let asianWorker = DispatchQueue(label: "construction_worker_1")
let brownWorker = DispatchQueue(label: "construction_worker_2")
func doLightWork() {
asianWorker.async { for _ in 1...10 { print("👷") } }
 brownWorker.async { for _ in 1...10 { print("👷🏽") } } }
doLightWork()
// 👷, 👷🏽, 👷, 👷🏽, 👷, 👷🏽, 👷, 👷🏽, 👷...

참조) https://learnappmaking.com/grand-central-dispatch-swift/

함수형태의 gcd 이용 예시 (swift 3 이전형태)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {  
    // Download file or perform expensive task

    dispatch_async(dispatch_get_main_queue()) {  
        // Update the UI  
    }
}

oop 형태의 gcd 이용 예시 (swift 3 이후형태)

DispatchQueue.global(qos: .userInitiated).async {  
    // Download file or perform expensive task

    DispatchQueue.main.async {  
        // Update the UI  
    }
}

dispatch_async와 dispatch_sync 와의 차이

https://stackoverflow.com/a/19822753/3151712

DispatchQueue에서의 qos, concurrency(제빠르게 threads간에 switch함으로써 동시에 일어나는 착각일으킴)

https://medium.com/@JoyceMatos/grand-central-dispatch-swift-3-93f995c15fd2


core data 

managed object context

  • performBlock:  Asynchronously performs a given block on the context’s queue.
  • performBlockAndWait:  Synchronously performs a given block on the context’s queue.

concurrency에 관한 tutorial

core data에서 concurrency를 이용하는 이유는 data persistence가 file에 저장하는데 시간이 걸리는데 이 동안 main ui thread가 막힘이 없게 하는것이 목적이다.

https://www.youtube.com/watch?v=lMT96wUsjMQ&index=9&list=PL23Revp-82LImHA8jL2dLaN_67pABFcyJ


Operation Queue

참고사항) https://agostini.tech/2017/07/30/understanding-operation-and-operationqueue-in-swift/#comment-141

operation을 이용한 threading 작업은 GCD를 기반으로 한다.

class 클래스이름: Operation {

   init() {

     …

   }

   override func main() {
        …
       }        

}

의 형태를 가진 작업을 만든다. 

// operationqueue를 생성한다.

private let operationQueue: OperationQueue = OperationQueue()

operationQueue.addOperations([생성된Operation, 생성된또다른Operation], waitUntilFinished: false)

수행하려는 작업이 다른 작업의 완료에 의존하는 경우(다른작업이 확실히 끝나고 나서 수행해야하는 경우)  

나중에수행될Operation.addDependency(우선수행되야하는Operation)

You might think that with OperationQueues and Operations there’s no need for GCD but they actually work together. Fun fact: Operations are built on top of GCD.Queue is a prioritised FIFO queue. he most common use of GCD is to run a piece of code on the main thread – like the ‘onCompleted’ closure in our example here: 

DispatchQueue.main.async(execute: {
  onCompleted?(listItems)
})

GCD (grand central dispatch)

original source : https://blog.bobthedeveloper.io/intro-to-grand-central-dispatch-in-swift-3-with-bob-lee-1d4b56f731b3 

gcd에서는 기본적으로 두가지의 종류의 작업자를 제공한다. (하나는 많은 리소스를 필요로하는 작업에 적합하고(heavy) 하나는 좀더 약한 작업에 적합하다(lightweight). 사용자가 추가로 필요한 경우 lightweigth 작업자를 추가 만들수 있다.)

let main = DispatchQueue.main // heavy 작업자 만들기
let background = DispatchQueue.global() // ios에서 제공하는 lightweight 작업자 만들기
let helper = DispatchQueue(label: "construction_worker_3") // 추가로 lightweight 작업자 만들기
func doSyncWork() { 
background.sync { for _ in 1...3 { print(“Light”) } }
for _ in 1...3 { print(“Heavy”) } } // main
doSyncWork() 
// Light
// Light
// Light
// Heavy
// Heavy
// Heavy

func doAsyncWork() { 
background.async { for _ in 1...3 { print(“Light”) } }
for _ in 1...3 { print(“Heavy”) } }                // main
doAsyncWork() 
// Light
// Heavy
// Heavy
// Light
// Heavy
// Light
let asianWorker = DispatchQueue(label: "construction_worker_1")
let brownWorker = DispatchQueue(label: "construction_worker_2")
func doLightWork() {
asianWorker.async { for _ in 1...10 { print("👷") } }
 brownWorker.async { for _ in 1...10 { print("👷🏽") } } }
doLightWork()
// 👷, 👷🏽, 👷, 👷🏽, 👷, 👷🏽, 👷, 👷🏽, 👷...

참조) https://learnappmaking.com/grand-central-dispatch-swift/

함수형태의 gcd 이용 예시 (swift 3 이전형태)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {  
    // Download file or perform expensive task

    dispatch_async(dispatch_get_main_queue()) {  
        // Update the UI  
    }
}

oop 형태의 gcd 이용 예시 (swift 3 이후형태)

DispatchQueue.global(qos: .userInitiated).async {  
    // Download file or perform expensive task

    DispatchQueue.main.async {  
        // Update the UI  
    }
}

dispatch_async와 dispatch_sync 와의 차이

https://stackoverflow.com/a/19822753/3151712

DispatchQueue에서의 qos, concurrency(제빠르게 threads간에 switch함으로써 동시에 일어나는 착각일으킴)

https://medium.com/@JoyceMatos/grand-central-dispatch-swift-3-93f995c15fd2


core data 

managed object context

  • performBlock:  Asynchronously performs a given block on the context’s queue.
  • performBlockAndWait:  Synchronously performs a given block on the context’s queue.

concurrency에 관한 tutorial

core data에서 concurrency를 이용하는 이유는 data persistence가 file에 저장하는데 시간이 걸리는데 이 동안 main ui thread가 막힘이 없게 하는것이 목적이다.

https://www.youtube.com/watch?v=lMT96wUsjMQ&index=9&list=PL23Revp-82LImHA8jL2dLaN_67pABFcyJ


Operation Queue

참고사항) https://agostini.tech/2017/07/30/understanding-operation-and-operationqueue-in-swift/#comment-141

operation을 이용한 threading 작업은 GCD를 기반으로 한다.

class 클래스이름: Operation {

   init() {

     …

   }

   override func main() {
        …
       }        

}

의 형태를 가진 작업을 만든다. 

// operationqueue를 생성한다.

private let operationQueue: OperationQueue = OperationQueue()

operationQueue.addOperations([생성된Operation, 생성된또다른Operation], waitUntilFinished: false)

수행하려는 작업이 다른 작업의 완료에 의존하는 경우(다른작업이 확실히 끝나고 나서 수행해야하는 경우)  

나중에수행될Operation.addDependency(우선수행되야하는Operation)

You might think that with OperationQueues and Operations there’s no need for GCD but they actually work together. Fun fact: Operations are built on top of GCD.Queue is a prioritised FIFO queue. he most common use of GCD is to run a piece of code on the main thread – like the ‘onCompleted’ closure in our example here: 

DispatchQueue.main.async(execute: {
  onCompleted?(listItems)
})

only the following types of code are affected by namespaces: classes (including abstracts and traits), interfaces, functions and constants.

Namespaces are declared using the namespace keyword. A file containing a namespace must declare the namespace at the top of the file before any other code – with one exception: the declare keyword.

Multiple namespaces may also be declared in the same file. it is recommended to use the alternate bracketed syntax.To combine global non-namespaced code with namespaced code, only bracketed syntax is supported. Global code should be encased in a namespace statement with no namespace name as in.

  • Unqualified name, or an unprefixed class name like $a = new foo(); or foo::staticmethod();. If the current namespace is currentnamespace, this resolves to currentnamespacefoo. If the code is global, non-namespaced code, this resolves to foo. One caveat: unqualified names for functions and constants will resolve to global functions and constants if the namespaced function or constant is not defined. See Using namespaces: fallback to global function/constant for details.
  • Qualified name, or a prefixed class name like $a = new subnamespacefoo(); orsubnamespacefoo::staticmethod();. If the current namespace is currentnamespace, this resolves tocurrentnamespacesubnamespacefoo. If the code is global, non-namespaced code, this resolves tosubnamespacefoo.
  • Fully qualified name, or a prefixed name with global prefix operator like $a = new currentnamespacefoo(); orcurrentnamespacefoo::staticmethod();. This always resolves to the literal name specified in the code,currentnamespacefoo.

The value of __NAMESPACE__ is a string that contains the current namespace name. In global, un-namespaced code, it contains an empty string.

All versions of PHP that support namespaces support three kinds of aliasing or importing: aliasing a class name, aliasing an interface name, and aliasing a namespace name. PHP 5.6+ also allows aliasing or importing function and constant names.

In PHP, aliasing is accomplished with the use operator.