이번에는 앨범실습을 통해 안드로이드가 제공하는 다양한기능을 공부해 보았다. 기능적으로 뭐가 있는게 아니기 때문에 딱히 특별한 무엇인가가 있는건 아니지만 안드로이드 개발시 활용되는 중요한 개념들에 대해서 배웠기 때문에 나름 중요도가 있었다고 생각한다. 강의에서는 간단히 다뤘기 때문에 추가적으로 여러 레퍼런스를 찾아보았다.
# 결과물 미리보기
- 사진앨범에서 사진을 고를 수 있음
- 사진앨범에 접근하기전 권한 여부를 확인 후 권한을 얻음
- 사진앨범 접근을 거부했을 경우, 다시 사진을 선택하는 경우 다이얼로그를 띄우고, 다시 권한여부를 물어봄
- 사진이 정해진 Timer에 의해서 서서히 바뀜
- 액티비티의 생명주기에 맞게 작성하여, 백그라운드로 나갔다 와도 timer가 멈췄다가 다시 실행 됨
# 알게 된 것
-- 👇 이번 포스팅 👇--
- Layout ( xml ) 🔥
- layout_constraintDimensionRatio 속성
- scaleType
- let { ... } 🔥
- 동적으로( 여러개 ) putExtra하기 🔥
- timer() 🔥
- animate()
-- 👇 다음 포스팅 👇--
- 파일(이미지) 접근 권한 얻기
- Content Provider
- 사진첩에서 선택한 이미지 액티비티로 보내기
- 액티비티 생명주기 ( Activity LifeCycle)
## Layout ( xml )
### layout_constraintDimensionRatio
layout_constraintDimensionRatio = "가로 : 세로"
layout_constraintDimensionRatio = "3:1"
layout_constraintDimensionRatio = "W,3:1" // Hieght를 채우고 시작
layout_constraintDimensionRatio = "H,3:1" // Width를 채우고 시작
### scaleType
ImageView의 비율 및 크기를 설정해주는 옵션 8개로 세분화
1. android:scaleType="center" : 이미지 원본 크기와 비율을 유지하며 이미지의 중앙을 layout_width, layout_height 안에 출력한다. 이 때 레이아웃보다 이미지가 크면 레이아웃의 벗어난 이미지는 출력되지 않는다. 레이아웃보다 이미지가 작으면 이미지를 center 정렬 한다. => 사용했음
2. android:scaleType="centerCrop" : 이미지의 가로/세로의 길이 중 짧은 쪽을 ImageView의 레이아웃에 꽉 차게 크기를 맞춰서 출력한다. 이 때 원본 이미지 가로/세로의 비율은 유지되고 레이아웃 영역에서 벗어난 이미지는 출력되지 않는다. => 사용했음
3. android:scaleType="centerInside" : 이미지의 가로/세로의 길이 중 긴 쪽을 ImageView의 레이아웃에 맞춰서 출력한다. 이 때 원본 이미지의 가로/세로의 비율은 유지되고 레이아웃에 이미지외 빈공간은 background 속성의 color로 채워진다. fitCenter와 다른점은 원본 이미지가 ImageView이 레이아웃보다 작다면, 이미지의 크기가 유지 된다는 것이다.
4. android:scaleType="fitCenter" : 이미지의 가로/세로의 길이 중 긴 쪽을 ImageView의 레이아웃에 맞춰서 출력하다. 이 때 원본 이미지의 가로/세로의 비율은 유지되고 레이아웃에 이미지외 빈공간은 background 속성의 color로 채워진다. centerInside와 다른점은 이미지의 크기가 ImageView의 레이아웃에 크기에 따라 변한다는 것이다.
5. android:scaleType="fiStart" : ImageView 레이아웃 안에서 이미지의 가로/세로 비율을 유지하며 출력되지만 ImageView의 레이아웃의 왼쪽 상단을 기준으로 정렬된다.
6. android:scaleType="fitEnd" : ImageView 레이아웃 안에서 이미지의 가로/세로 비율을 유지하며 출력되지만 ImageView의 레이아웃의 오른쪽 하단을 기준으로 정렬된다.
7. android:scaleType="fitXY" : 가로/세로 비율에 상관없이 ImageView의 레이아웃의 각 면에 꽉 차게 출력된다.
8. android:scaleType="matrix" : 이미지 원본의 크기와 비율을 유지하며 이미지 원본대로 왼쪽 상단을 기준으로 출력된다. 이미지가 ImageView의 레이아웃 보다 크다면 나머지 이미지는 출력되지 않는다.
## let { ... }
private fun getPhotoUriFromIntent() {
val size = intent.getIntExtra("photoListSize",0)
for( i in 0..size ) {
intent.getStringExtra("photo$i")?.let{
photoList.add(Uri.parse(it))
}
}
}
주로 null이 아닐때 let안의 람다구문을 실행하기 때문에 null을 확인하는 용도로 쓰인다. 위 예시에서도 null값인 경우는 그냥 넘어가고 null이 아닌경우에 photoList.add()구문을 실행하게 된다.
## 동적으로( 여러개 ) putExtra하기
이건 하나의 코딩팁이라고 할 수 있을거 같다. 정말 안드로이드 처음시작할때 프레퍼런스를 의도치 않게 많이 활용한 경우가 있었는데 하나씩 하드코딩하면서 동적으로는 보내주지 못했던 적이 있었다. 알아두면 좋은 코딩기법이라고 생각한다. 어려운건 당연히 아니다. 여기선 Intent에서 넘겨주는건데 비슷하게 활용 할 수는 있을거 같다.
// 보낼때
// putExtra()
startPhotoFrameModeButton.setOnClickListener {
val intent = Intent(this,PhotoFrameActivity::class.java)
imageUriList.forEachIndexed { index,item ->
intent.putExtra("photo$index", item.toString())
}
intent.putExtra("photoListSize", imageUriList.size)
startActivity(intent)
}
"$"을 사용하여 string에 변수를 추가시키고, size에 대한 정보도 따로 넘겨준 후,
// 받을 때
// get...Extra()
val size = intent.getIntExtra("photoListSize",0)
for( i in 0..size ) {
intent.getStringExtra("photo$i")?.let{
photoList.add(Uri.parse(it)) // String을 Uri로 바꾸어 이미지정보를 사용
}
}
## timer()
timer는 메인쓰레드가 아닌 백그라운드 쓰레드에서 사용된다. 즉 Ui를 직접적으로 수정하는 코드는 작성할 수 없기 때문에 runOnUiTherad를 사용해야한다.
//import
kotlin.concurrent.timer
// 변수에 할당 가능
mytimer = timer(period = 1000 ) {
Log.d(tag,"timer is running")
runOnUiThread{
// TODO Ui다루는 코드 작성
}
}
// 타이머 끝내기
mytimer.cancle()
// 3초후에 타이머 실행, 1초 주기
mytimer2 = timer(period = 1000, initiaDelay=3000 ) { ... }
## animate()
runOnUiThread{
val current = currentPosition
val next = if (photoList.size <= currentPosition +1 ) 0 else currentPosition + 1
backgroundPhotoImageView.setImageURI(photoList[current])
photoImageView.alpha = 0f
photoImageView.setImageURI(photoList[next])
photoImageView.animate()
.alpha(1.0f)
.setDuration(1000)
.start()
currentPosition = next
}
위 미리보기에 있는거와 같이 배경이미지가 천천히 바뀌는 것이다. animate()를 이용해서 추가적으로 여러 옵션값을 주면서 변환이 가능하다. 지금은 이런게 있다는것만 알고 필요할때 찾아 쓰면 좋을거 같았다.
이분이 아주아주 잘 정리해주셨기 때문에 필요하면 꼭 참고하도록 하자
이번에는 간단히 알게되거나 코딩스타일들과 같은 정보를 담았다. 다음 게시글에서는 각각 Content Provider, 파일 접근 권한, 라이플 사이클에 대해서 정리하도록하겠다. 각 포스팅에 하나씩 해야할 굵은 소재들인거 같기 때문이다. 또 필수적으로 알아둬야만 할거 같은 느낌이 왔기 때문이기도 하다.
다음부터 포스팅을 할때는, 첫편에는 이렇게 간단한 소재들을 담고 뒤에서 굵은소재들은 한 포스팅에 하나씩 작성하는 방식으로 하면 좋을거 같다.
AVD에서는 사진을 찍으면 괴상한 캐릭터가 나온다. 실제 스마트폰으로 에뮬레이터를 사용하면 꽤 빠르고 좋다고하는데, 얼른 써보고 싶다.