FIX 

가장 자주 사용되는 커밋 로그 중 하나로 'Fix'가 있습니다. 보통 올바르지 않은 동작을 고친 경우에 사용합니다.


Fix A  - A를 수정합니다
  • Fix stat cache
  • Fix changelog entry

Fix A in B - B의 A를 수정합니다.

가장 자주 사용되는 패턴입니다.

  • Fix calculation in process.uptime()
    • process.uptime()에 calculation을 수정합니다.
  • Fix build warning in node_report.cc
    • node_report.cc에 빌드 경고를 수정합니다.

Fix A which B , Fix A that B - B절인 A를 수정합니다.

'Fix A'로 끝낼 수 있으나 무엇을 수정한 것인지 상세하게 설명할 때 주로 사용합니다.

  • Fix incorrect type which makes animated gifs not loop forever on device
    • 디바이스에서 애니메이션 gif가 반복되지 않는 잘못된 타입을 수정합니다
  • Fix crash that happens when a component throws an exception that contains a null message
    • 컴포넌트가 null 메세지를 포함하는 예외를 발생시키는 경우 발생하는 충돌을 수정합니다

Fix A to B , Fix A to be B - B를 위해 A를 수정합니다

왜 수정하는지를 추가로 설명합니다

  • Fix inability to remove 'Disabled' state from AccessibilityStates
    • 'Disabled' 상태를 AccessibilityState에서 제거할 수 없는걸 수정합니다
  • Fix HTTP connection timeout callback to be appropriately called
    • 적당한 호출을 위해 HTTP 연결 시간 초과 콜백을 수정합니다

Fix A so that B - A를 수정해서 B가 되었습니다

'Fix A to B'와 의미는 비슷하나, 어감이 조금 다릅니다. 고쳐진 B의 상태가 강조됩니다.

  • Fix react-native init --help so that it doesn't return undefined
    • react-native init --help를 수정해서 정의되지 않은 상태로 반한되지 않습니다

Fix A where B - B처럼 발생하는 A를 수정했습니다

여기서 A는 보통 'issue', 'error', 'crash' 등이 들어가고 B는 문제가 발생한 모습을 적어줍니다.

  • Fix case where content of inline views didn't get relaid out
    • 인라인 뷰의 내용이 전달되지 않는 케이스 수정했습니다.

Fix A when B - B일 때 발생하는 A를 수정했습니다

A는 보통 'issue', 'error', 'crash' 등이 들어가고 B는 문제가 발생한 모습을 적어줍니다.

  • Fix crash when removing root nodes
    • 루트 노드를 제거할 때 발생하는 충돌을 수정했습니다
Reference

 

 

'Git' 카테고리의 다른 글

초간단 Git 사용법  (0) 2017.09.08
1.Git 시작하기  (0) 2017.08.30

Button 속성 추가하기 ( 버튼 텍스트 소문자 )

- android:textAllCaps = "false" 


Button 이벤트 순서

- onTouch -> onClick -> onLongClick 순으로 이벤트가 전달된다.

그런데 onTouch()에서 return true를 하면 onClick과 onLongClick까지 이벤트가 전달되지 않고, false면 모두 전달된다.


uCrop 참고 : https://www.programcreek.com/java-api-examples/?class=com.yalantis.ucrop.UCrop&method=Options


 

 

Reference

 - https://wowan.tistory.com/124

 - https://marlboroyw.tistory.com/131

 - https://www.programcreek.com/java-api-examples/?class=com.yalantis.ucrop.UCrop&method=Options

 

EditText 속성

 - background 값에 @null을 추가한다.


EditText 활성화, 키패드 보이기, 커서 위치 이동

editText.isFocusableInTouchMode = true
editText.isFocusable = true
editText.selection(editText.length()) // 커서 위치 이동하기

// 키패드 보이기
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.showSoftInput(eidtText, 0)

EditText 비활성화, 키패드 숨기기

editText.isClickable = false
editText.isFocusable = false

// 키패드 숨기기
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
imm.hideSoftInputFromWindow(edit_nickname_editmyinfo_a.windowToken, 0)

Reference

 - https://nuggy875.tistory.com/10

 - https://philip1994.tistory.com/12

 - https://programmingsummaries.tistory.com/30

 

ContentProvider

ContentProvider는 앱 사이에서 각종 데이터를 공유할 수 있게 해주는 컴포넌트입니다.

 

안드로이드 표준 시스템에서는 연락처인 Contacts나 이미지, 동영상 등의 데이터를 보관하는 MediaStore 등이 ContentProvider로 공개돼 있습니다. 데이터를 검색, 추가, 갱신, 삭제할 수 있으며, 주로 SQLite 등의 관계형 데이터 베이스 이용을 염두에 두고 설계됐습니다. 그러므로 관계형 데이터 베이스를 다룬 경험이 있다면 이해하는데 도움이 될 것이라 생각됩니다.

 

ContentProvider로부터 데이러를 읽어오려면 해당 ContentProvider가 어디에 있는지 알아야 합니다.

경로는 'content://스키마'를 가진 URI(Universal Resource Identifier)로 지정되고, 일반적으로 접근할 대상 앱에서 정의됩니다. 또한 URI는 authority로 불리며, ContentProvider를 직접 만들 때는 AndroidManifest.xml에 기술해야 합니다.

 

ContentResolver

ContentProvider가 제공하는 데이터에는 ContentResolver를 통해 접근하도록 설계돼 있고, ContentProvider 자신에 대한 참조는 필요없습니다. ContentResolver의 인스턴스는 getContentReslolver() 메서드로 가져옵니다.

 

ContentResolver에 URI를 전달함으로써 ContentProvider의 데이터에 접근할 수 있습니다. 데이터는 ContentResolver.query()를 이용해 가져옵니다.

Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder)

uri : ContentProvider가 관리하는 uri

projection : 가져오고 싶은 칼럼명 (select에 해당)

selection : 필터링할 칼럼명을 지정 (where에 해당)

selectionArgs : selection으로 지정한 칼럼명의 조건을 설정 (프리페어드 스테이트먼트에 해당)

sortOrder : 정렬하고 싶은 칼럼명을 지정 (order by에 해당)

Cursor

query()의 반환값인 Cursor는 데이터에 접근하는 포인터입니다.

2차원 표를 떠올려서 생각해보면 행과 열이 있을 때 어느 행을 가리키는지 나타내는 것이 Cursor입니다.

 

'갤러리' 앱에서 이용되는 ContentProvider에서 이미지를 가져오기

ContentProvier에 접근할 때 기본적으로 다른 앱이 이용할 수 있도록 필요한 상수는 정의돼 있습니다.

Authority를 나타내는 Uri는 보통 CONTENT_URI, EXTERNAL_CONTENT_URI 같은 상수명으로 공개됩니다.

또한 가져오고 싶은 칼럼명도 마찬가지로 정의돼 있으므로 이를 이용합니다. 우선 필요한 projection등을 작성하고, ContentResolver.query()를 호출해 Cursor를 가져옵니다.

 

 

 

19행에 Cursor.moveToFirst()를 호출해 커서를 맨 앞으로 이동해 true가 반환된 경우에만 Cursor에서 데이터를 가져옵니다. false가 반환된 경우 데이터는 비어있으므로 그 이후의 처리는 필요 없습니다. 

Cursor로부터 데이터를 가져오려면 두 단계가 필요합니다.

  1. 가져오고 싶은 칼럼의 인덱스를 얻습니다.
  2. Cursor.getString(int)를 호출해 데이터를 가져옵니다.

문자열인 경우는 getString(), 숫자인 경우는 getInt() 등 자료형에 따른 메서드가 준비돼 있고, 인수에는 가져오고 싶은 칼럼의 인덱스를 전달합니다.  Cursor의 사용이 끝나면 close()를 호출합니다. Cursor는 ContentProvider로부터 가져온 데이터에 대한 참조를 가지고 있으므로 닫아서 참조하는 데이터를 해제할 필요가 있습니다.

정리하기

  1. ContentResolver 구하기 : getContentResolver, 46행
  2. Cursor 구하기 : getImage(), 58행
  3. Cursor에서 데이터 가져오기 : try{}, 26~28행
  4. Cursor 해제하기 : cursor.close(), 38행

Reference

HandlerThread는 Thread 클래스를 상속하고 내부에서 Looper.prepare()와 Looper.loop()를 실행하는 Looper 쓰레드입니다. 

 

Looper는 자신이 속한 Thread의 Message Queue에 추가되는 message를 기다리다가 꺼내서 이를 처리할 Handler에 디스패치합니다. 스레드에 Looper를 설정하려면 정적 메서드 prepare()와 loop()를 호출해야 합니다. 단, 안드로이드 MainThread는 Looper가 기본적으로 설정되어 있습니다.

 

단일스레드에서 순차적인 작업이 필요할 때 HandlerThread를 사용합니다.

 

 

화면을 터치하면 이벤트라는 것이 발생하게 되는데 이 이벤트는 리스너라는 것을 이용하여 다룰 수 있습니다.

 

 

터치 이벤트 이외에도 단말의 방향을 가로 방향으로 돌렸을 때도 이벤트가 발생하고 키패드에서 키를 하나 눌렀을 때도 이벤트가 발생합니다.

 

 

이런 이벤트를 어떻게 처리할 수 있는지 알아봅시다.

 

 

버튼을 클릭했을 때 버튼 클릭한 것을 이벤트라고 하는 걸로 만들어서 전달받을 수 있습니다.

전달받아서 처리할 수 있는데 이것을 이벤트 리스너라고 하는걸 등록해서 처리할 수 있습니다.

이게 버튼뿐만 아니라 뷰라고 하는 거에 대해서 거의 대부분 다 적용할 수 있습니다.

 

 

그래서 기본적인 이벤트 처리방법을 이해하면 굉장히 다양한 기능을 만들 수 있습니다.

 

 

이벤트는 가장 단순한게 버튼을 클릭했을 때를 생각해볼 수 있습니다.

버튼을 클릭하면 onClick이라는 이벤트가 발생됩니다. 그래서 그때 이 버튼에다가 OnClickListener라고 하는 리스너를 설정하면 이쪽으로 이벤트를 전달해줍니다. 

 

 

그런데 이 클릭은 좀 더 세분화해보면 터치 이벤트로 나눠볼 수 있습니다.

사용자가 스마트폰 단말의 화면에다가 손가락으로 터치를 하면 손가락으로 누를 때, 누른 상태에서 움직일 때, 손가락을 뗐을 때로 구분할 수 있습니다. 

 

 

그 다음에 키패드에서 키를 하나 눌렀을 때 우리가 어떤 키를 눌렀는지 확인할 수 있는 방법도 있습니다. 그리고 손가락을 눌러서 끌어당길 때 그 때 빨리할 수도 있고 느리게 할 수도 있을텐데 그런 것들을 빨리하거나 느리게 할 때 얼마나 빨리했는지 이런것들을 일일이 계산해야 하는데 제스처라고 하는걸 쓰면 계산하는 걸 알아서 내부에서 해줍니다.

 

 

그래서 제스처 이벤트라고 하는걸 처리하는 방법이 있습니다.

 

 

뷰마다 포커스가 주어질 수 있는데 이건 실제로 쓰는 경우는 쓰게 될 일은 많지 않지만 포커스라고 하는게 있습니다.

그리고 단말의 방향을 가로로 돌렸을 때 그때 받을 수 있는 이벤트도 있습니다.

 

 

그럼 간단히 뷰를 터치했을 때 발생하는 터치 이벤트에 대한 터치 이벤트 리스너를 만들어보겠습니다.

view에 onTouchListener를 만들어줍니다. 그러면 event.action으로 터치 정보가 넘어오고 MotionEvent를 이용해 각각의 상태를 구분할 수 있습니다. 그리고 마지막에 true로 정상적으로 처리됐음을 알려줍니다.

view.setOnTouchListener { v, event ->
    var action = event.action

    val curX = event.x
    val curY = event.y

    if (action == MotionEvent.ACTION_DOWN) {
        println("손가락 눌렸음 : $curX, $curY")
    } else if (action == MotionEvent.ACTION_MOVE) {
        println("손가락 움직임 : $curX, $curY")
    } else if (action == MotionEvent.ACTION_UP) {
        println("손가락 떼졌음 : $curX, $curY")
    }

    true
}

 

그럼 직접 터치하면 엄청 많이 호출되는 것을 볼 수 있습니다. 근데 이 엄청 많이 호출되는 것을 일일이 이게 얼마나 빠른 속도로 움직이냐라고 하는걸 가지고 기능을 만들어야 될 때가 있는데 일일이 하기 힘드니까 제스처라고 하는걸 가지고 자동으로 계산되게 만들 수 있습니다.

 

 

그럼 이번에는 제스처디텍터라는 것을 만들어 view2의 영역에서 테스트를 해보겠습니다.

detector = GestureDetector(
    this, object: GestureDetector.OnGestureListener {
        override fun onDown(e: MotionEvent?): Boolean {
            println("onDown() 호출됨")
            return true
        }

        override fun onShowPress(e: MotionEvent?) {
            println("onShowPress() 호출됨")
        }

        override fun onSingleTapUp(e: MotionEvent?): Boolean {
            println("onSingleTapUp() 호출됨")
            return true
        }

        override fun onFling(
            e1: MotionEvent?,
            e2: MotionEvent?,
            velocityX: Float,
            velocityY: Float
        ): Boolean {
            println("onFling() 호출 됨 : $velocityX, $velocityY")
            return true
        }

        override fun onScroll(
            e1: MotionEvent?,
            e2: MotionEvent?,
            distanceX: Float,
            distanceY: Float
        ): Boolean {
            println("onScroll() 호출됨 : $distanceX, $distanceY")
            return true
        }

        override fun onLongPress(e: MotionEvent?) {
            println("onLongPress() 호출됨")
        }
    })

view2.setOnTouchListener { v, event ->
    detector.onTouchEvent(event)
    true
}

 

이렇게 제스처디텍터를 사용하면 좀 더 편하게 처리할 수 있는 기능이 생깁니다. 예를들어 갤러리에서 사진을 볼 때 다음 사진을 보기위해 사진을 옆으로 스크롤해 넘길 때 끝까지 넘기는게 아니라 어느정도 넘기면 옆으로 탁 튕기면서 들어가는데 이 때 제스처이벤트를 사용하면 훨씬 쉽게 그런 기능을 구현할 수 있습니다. 

 

 

이번에는 키 이벤트에 대해서 알아보겠습니다.

키는 키패드를 얘기합니다. 키패드를 누르면 KEYCODE_HOME, KEYCODE_BACK, KEYCODE_1 등과 같은 키 값이 들어옵니다. 그래서 이 키 값을 전달받아서 처리하고 싶으면 onKeyDown이라던가 onKey와 같은 메서드를 재정의해서 사용하면 됩니다.  그럼 키 이벤트를 처리하는 코드를 만들어 보겠습니다.

override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
    if (keyCode == KeyEvent.KEYCODE_BACK) {
        toast("시스템 BACK 버튼 눌림")
        return true
    }
    return false
}

시스템 BACK키를 누르면 원래 화면이 없어지는데 이렇게하면 화면이 안없어지도록 만들 수 있습니다.

그래서 '한번 더 누르면 종료됩니다' 하는 메세지를 보여주는 그런 앱들을 볼 수 있습니다.

 

 

만든 코드는 아래에 첨부했습니다.

activity_my_event.xml

MyEvent.kt

Reference

 

 

새로운 앱을 디자인할 때, 어떤 색상을 활용하는 게 좋을까?

MONOCHROMATIC (단색)

  • 단색은 색상들을 동일한 기본 색으로부터 만들기 때문에 가장 만들기 간단한 Color Scheme(색 구성표)이다.
  • 단색은 안정감을 주는 효과가 있다.
  • 특히 Blue나 Green 색상이 가장 편한 느낌을 준다.
  • Adobe Color CC를 검색해서 도움을 받을 수 있다.

ANALOGOUS(유사색)

  • 유사색은 서로 이질적이지 않은 유사한 색상으로부터 만든다.
  • 한 가지 색상이 대표색으로 사용되면서 다른 색들이 컬러를 풍부하게 만들어 준다.
  • 색이 진해 지거나 옅어질 때 어떤 방향으로 변화를 줄 것인지를 잘 선택해야 한다.
  • Calm이라는 명상 앱은 사용자에게 편안하고 평화로운 느낌을 주기 위해 blue와 green의 유사색을 사용한다.

COMPLEMENTARY(보색)

  • 보색들은 서로 강하게 대비를 이루며, 보는 사람의 주의를 끌기 위해 사용된다.
  • 강한 대비를 위해 눈에 띄는 색상과 그 색상에 대비를 이루는 색상을 사용하는 것이 좋다.
  • 예를 들면, 사람의 눈이 green으로 가득찬 사물을 볼 때, 약간의 red는 아주 눈에 잘 띄어 보인다.

CUSTOM COLOR SCHEME

  • 자신만의 컬러스킴을 만드는 쉬운 방법 중 하나는, 무채색인 팔레트에 밝은 엑센트 색상을 추가하는 것이다. 이러면 시각적으로 도드라져 보이게 할 수 있는 방법이다.

Image credit: Adobe Color CC

  • Dropbox 컬러스킴은 White 캔버스에 cool grey, blue 엑센트 색상을 적용했다.

ADOBE COLOR CC

ADOBE COLOR CC를 이용해 컬러 스킴을 훨씬 편하게 만들 수 있다.

  • 기존 Kuler로 많이 알려진 ADOBE COLOR CC는 컬러 선택을 매우 쉽게 만들어 준다. 간단한 클릭으로 기본 색상으로부터 팔레트의 모든 색상을 각각 편집할 수 있다.

색상 대비 효과 : 색상이 서로 쉽게 구분되어 보일 때 대비가 강하다고 말한다.

  • 대비가 약한 색상들을 사용하면 디자인이 아름답고 조화롭게 보이기 때문에 디자이너는 약한 대비를 선호하기도 한다. 그러나 아름다운 것이 가독성을 위해 항상 좋은 것은 아니다.
  • 텍스트에 색상을 적용할 때, 배경과 대비가 약한 색상을 적용한다면, 읽기가 매우 힘들어질 것이다. 특히 모바일 디바이스는 사용자가 화면 반사를 일으키는 밝은 야외에서 사용하는 경우가 많기 때문에 그러한 경우가 더 많다.
  • 요소들 사이에 충분한 대비를 가지도록 대비율(Contrast ratio)만 체크하면 된다. 대미율은 한 색상이 다른 색상에 비해 얼마나 다른지를 나타내는 지표이다.(보통 1:1 or 21:1로 표기됨) 두 숫자들의 차이가 클수록, 두 색상의 선명도 차이가 상대적으로 커진다.
  • W3C는 본문과 이미지 텍스트에서 아래의 대비율을 권장한다.
    • 작은 텍스트는 배경 대비 4.5:1의 대비율이 있어야 한다.
    • 큰 텍스트는(bold 14pt / regular 18pt이상) 배경 대비 3:1의 대비율이 있어야한다.
    • 이 가이드라인은 시력이 좋지 않거나 색맹인 사용자, 시야가 좋지 않은 상황에서 스크린에서 텍스트를 보고 읽을 수 있도록 해준다.

가독성이 좋은 텍스트를 적용하는 것 외에도, 대비는 화면의 특정 요소에 대해 사용자의 주의를 끌게 해 줄 수 있다.

일반적으로, 중요한 콘텐츠나 주요 요소를 강조하는데 강한 대비를 사용한다. 사용자가 어떤 것을 보거나 클릭하게 하고 싶다면, 눈에 띄게 만들어라!

 

Reference

 

 

 

 

 

 

 

 

ImageView에는 adjustViewBounds라는 속성이 있다. 

adjustViewBounds

adjustViewBounds는 src로 추가된 이미지의 원래 비율을 계산해서 ImageView의 높이가 결정된다.

주의할 점은 이미지의 height은 wrap_content여야 높이를 비율에 맞게 설정할 수 있고,

background가 아닌 src로 drawable이미지를 추가해야 한다.


더보기

안드로이드 기기 호환성

안드로이드는 휴대 전화에서 태블릿, TV에 이르기까지 다양한 유형의 기기에서 실행되도록 설계되었다. 앱이 이러한 모든 기기에서 성공하려면 일부 기능 변동을 허용하고 다양한 화면 구성에 적응할 수 있는 유연한 인터페이스를 제공해야한다. 이러한 목표를 향한 노력을 돕기 위해 Android는 정적 파일(예: 화면 크기에 따라 다른 XML 레이아웃)로 구성 별 앱 리소스를 제공할 수 있는 동적 앱 프레임 워크를 제공한다. 그런 다음 Android는 현재 기기 구성에 따라 적절한 리소스를 로드한다. 따라서 일부 앱 디자인 및 추가 앱 리소스를 고려하여 다양한 장치에서 최적화 된 사용자 환경을 제공하는 단일 애플리케이션 패키지(APK)를 게시 할 수 있다.

 

그러나 필요한 경우 앱의 기능 요구 사항을 지정하고 Google Play 스토어에서 앱을 설치할 수 있는 기기유형을 제어할 수 있다. 이 페이지에서는 앱에 액세스할 수 있는 장치를 제어하는 방법과 올바른 대상에 도달하도록 앱을 준비하는 방법에 대해 설명한다. 

 

"호환성"이란 무엇인가? 

Android개발에 대한 자세한 내용을 읽으면 다양한 상황에서 "호환성"이라는 용어가 나타날 수 있다. 호환성에는 장치 호환성과 앱 호환성의 두가지 유형이 있다. Android는 오픈 소스 프로젝트이므로 모든 하드웨어 제조업체는 Android운영체제를 실행하는 장치를 구축 할 수 있다. 그러나 기기는 Android 실행 환경 용으로 작성된 앱을 올바르게 실행할 수 있는 경우에만 "Android 호환"이다. Android 실행 환경의 정확한 세부 사항은 Android 호환성 프로그램에의해 정의되며 각 디바이스는 호환 가능한 것으로 간주 되려면 호환성 테스트 스위트(CTS)를 통과해야한다.

 

앱 개발자는 Android 호환기기만 Google Play Store를 포함하므로 기기가 Android와 호환되는지 여부에 대해 걱정할 필요가 없다. 따라서 Google Play Store에서 앱을 설치하는 사용자는 Android호환 기를 사용하고 있으므로 안심할 수 있다.

//

그러나 앱이 각 잠재적 장치 구성과 호환 되는지 여부를 고려해야한다. Android는 광범위한 기기 구성에서 실행되므로 일부 기기에서는 일부 기능을 사용할 수 없다. 예를 들어 일부 장치에는 나침반 센서가 포함되어 있지 않을 수 있지만 앱의 핵심 기능에 나침반 센서를 사용해야 하는 경우 앱은 나침반 센서가 포함되어있지 않을 수 있다. 햅의 핵심 기능에 나침반 센서를 사용해야하는 경우 앱은 나침반 센서가 포함된 장치에만 호환된다.

......

Reference

https://developer.android.com/guide/practices/compatibility?hl=ko

 

 

 

 

리사이클러 뷰에서 아이템을 클릭했을 때, 아이템의 데이터를 가지고 새로운 액티비티에 보여주려고 한다.

이 때, 아이템이 점점 커져 화면 전체를 차지해서 보여지도록 만드는게 목표였다.

공부 중에 "android:transitionName" 속성을 이용한 애니메이션 효과를 주면 만들수 있을 것 같았다. 

그래서 먼저, itemView를 클릭했을 때, 새로운 액티비티로 넘어가는 코드를 만들었다.

다음으로 android:transitionName 속성을 itemView와 액티비티에 같은 이름으로 선언하면, 액티비티에서 transitionName속성을 가진 뷰를 시작으로 점점 커지면서 화면을 채워가며 액티비티화면을 보여주게 된다.

반대로 액티비티를 종료할 때는 줄어들면서 화면이 사라진다.

 

이 때, 액티비티 화면에서는 itemView에서 보여주던 것 보다 더 많은 걸 보여주는데, 화면이 커질 때 부터 보여줘서 보기 좋지 않은 상태가 되었다.

 

처음에는 ConstraintLayout에서 뷰를 Group으로 묶을 수 있는 기능이 있어서 Group으로 원하는 부분을 묶고, 이곳에 android:transitionName 속성을 주면 되지 않을까 생각했는데 어림도 없었다.

 

두번 째로는 android:transitionName 속성의 위치를 이동시켰다. 뒤로가기 버튼으로 이동시키자 뒤로가기 버튼부터 화면이 커지기 시작하고 뒤로가기 버튼으로 작아지는 것을 확인했고, android:transitionName 속성을 itemView의 맨앞에 보여지는 title을 보여주는 텍스트뷰에 android:transitionName 속성을 지정해줬더니 텍스트뷰를 기준으로 액티비티화면이 커지고 작아졌다.

아직 조금 아쉽지만 작아질 때 뒤로가기 버튼이나 itemView에서 안보이던 부분들이 보여지는 문제가 남아있었다. 그래서 액티비티를 벗어날 때 itemView에 안보이던 것들을 뷰에서 안보이도록 설정을 바꿔주었더니 원하는 방향이 완성되었다.

 

 

머티리얼 디자인 앱의 액티비티 전환은 움직임과 변환을 통해 서로 다른 상태 간의 시각적 연결을 제공한다. 입력 및 종료 전환과 작업 간 공유 요소의 전환에 대한 사용자 정의 애니메이션을 지정할 수 있다.

 

진입(enter) 전환은 액티비티의 뷰가 장면으로 들어가는 방법을 결정한다. 예를 들어, explode 전환으로 들어갈 때, 뷰가 외부에서 장면으로 들어가 화면 중앙을 향해 날아든다.

 

종료(exit) 전환은 액티비티의 뷰가 장면으로 들어가는 방법을 결정한다. 예를 들어, explode exit 전환에서, 뷰는 화면을 중앙에서 멀리 벗어난다.

 

공유 요소(shared elements) 전환은 두 액티비티 사이에 공유되는 관점이 이들 액티비티 사이에 어떻게 전환되는지를 결정한다. 예를 들어, 두 액티비티가 서로 다른 위치와 크기로 동일한 이미지를 갖는 경우, ChangeImageTransform 공유 요소 전환은 이러한 액티비티 사이에서 이미지를 원활하게 변환하고 스케일을 조정한다. 

 

안드로이드에서 진입(enter)와 종료(exit)전환을 지원한다.

  • explode - 뷰를 화면 중심으로 이동하거나 벗어나게 한다.
  • slide - 뷰를 화면의 가장자리로 이동하거나 벗어나게 한다.
  • fade - 화면을 투명, 불투명하게 바꿈으로 화면에서 제거하고 추가한다.

Visibility 클래스를 상속하는 모든 전환은 진입(enter) 또는 종료(exit) 전환을 지원한다.

자세한 내용은 Transition 클래스에 대한 API에서 확인할 수 있다.

 

안드로이드는 공유 요소(shared elements) 전환도 지원한다.

  • ChagneBounds - 대상 뷰의 layout bounds 변경 애니메이션
  • ChangeClipBounds - 대상 뷰의 clip bounds 변경 애니메이션
  • ChangeTransform - 대상 뷰의 scale 및 rotation의 변화 애니메이션
  • ChangeImageTransform - 대상 이미지의 size 및 scale 변경 애니메이션

앱에서 액티비티 전환을 활성화하면, 기본으로 cross-fading 전환이 활성화된다.

 

액티비티 전환 API는 Android 5.0(API 21)이상에서 사용할 수 있다. 이전 버전의 Android와의 호환성을 유지하려면 API를 호출하기 전에 런타임에 시스템 버전을 확인해야한다.

// Check if we're running on Android 5.0 or higher
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
    // Apply activity transition
} else {
    // Swap without transition
}

사용자(Custom) 지정 전환

첫째, 머티리얼 테마에서 상속되는 스타일을 정의할 때 android:windowActivityTransitions 속성을 사용하여 화면 내용 전환을 사용하도록 설정한다. 또한 스타일 정의에서 진입(enter), 종료(exit) 및 공유 요소(shared element)전환을 지정할 수도 있다.

<style name="BaseAppTheme" parent="android:Theme.Material">
  <!-- enable window content transitions -->
  <item name="android:windowActivityTransitions">true</item>

  <!-- specify enter and exit transitions -->
  <item name="android:windowEnterTransition">@transition/explode</item>
  <item name="android:windowExitTransition">@transition/explode</item>

  <!-- specify shared element transitions -->
  <item name="android:windowSharedElementEnterTransition">
    @transition/change_image_transform</item>
  <item name="android:windowSharedElementExitTransition">
    @transition/change_image_transform</item>
</style>

이 예에서 chagne)image_transform 전환은 다음과 같이 정의한다.

<!-- res/transition/change_image_transform.xml -->
<!-- (see also Shared Transitions below) -->
<transitionSet xmlns:android="http://schemas.android.com/apk/res/android">
  <changeImageTransform/>
</transitionSet>

ChangeImageTransform 요소는 ChangeImageTransform 클래스에 해당한다. 

더보기

ChangeImageTransform 클래스는 API level 21부터 추가되었다. 이 전환은 화면 변경 전후에 ImageView의 매트릭스를 캡처하고 전환 중에 애니메이션한다. ChangeImageTransform은 ChangeBounds와 함께 크기, 모양 또는 ImageView를 변경할 수 있다. ScaleType을 사용하여 컨텐츠를 원활하게 애니메이션할 수 있다. 

대신 코드에서 창 내용 전환을 활성화하려면 Window.requestFeature()함수를 호출한다.

 

 

 

+ Recent posts