본문 바로가기

Android

(76)
[Jetpack Compose] Image 의 ContentScale Jetpack Compose Image 안드로이드 앱 개발 시 이미지 표시를 위해 사용되는 Composable 입니다. 기존 XML 의 ImageView 와 같은 역할을 하며, Painter 를 기본적으로 지원하고 Bitmap 까지 지원합니다. 해당 Composable 의 파라미터 중 contentScale 은 이미지를 Composable 규격 내에서 어떻게 표시할 것인가를 결정합니다. XML 의 ImageView 속성 중 android:sacleType 속성과 역할이 같습니다. 다음은 각 속성값에 따른 이미지 표시를 정리했습니다. 보다 정확한 비교를 위해 5*5 의 체커보드 이미지를 사용했습니다. 1. Fit 최초로 Image Composable 을 구현하면 적용되어 있는 기본값이 Fit 입니다. 정사..
[Jetpack Compose] Clickable Ripple Effect 없애기 Android, iOS 등 모바일에서는 버튼이 눌렸다는 사실을 유저에게 알리기위해 Ripple Effect 가 존재합니다. 보통은 호숫가에 던져진 돌에 의해 파동이 일어나듯, 터치한 부분을 중심으로 원이 커져가는 형태입니다. 다만, 텍스트를 버튼 대신 사용하거나, 굳이 Ripple Effect 가 필요하지 않은 곳에는 Ripple Effect 가 없는 편이 UI적으로 더욱 좋은 경우가 있습니다. 안드로이드의 경우, XML 을 사용했을 때는 버튼 이외의 다른 View 에 지정하지 않은 Riffle 이 생성되는 경우가 적었습니다. 하지만 Compose 로 넘어오면서, Modifier.clickable { } 을 통해 클릭 이벤트를 추가해주면 자동으로 Ripple Effect 가 추가됩니다. 이를 없애는 방법..
[Jetpack Compose] ImageCropper 라이브러리 없이 구현하기 현재 진행중인 사이드 프로젝트에서는 카카오 및 구글 로그인을 사용합니다. 그러므로, 이미지를 촬영 또는 디바이스에서 불러와 이를 수정 및 등록할 수 있도록 구현해야 합니다. 당연히 유수한 ImageCropper 라이브러리가 있지만, 앱 내에서 여러 번 사용되는 기능이 아니기에 직접 구현하기로 했습니다. 단순한 기능 하나를 위해 특정 의존성을 추가하는 행위 자체가 꺼려지기도 했고, 불필요한 패키지 사이즈의 증가는 유저로 하여금 다운로드가 꺼려질 수 있기 때문입니다. 또한 UI 와 관련한 라이브러리는 가능하면 배제하자는 것이 제 주관이기도 합니다. Tl ; DR 소스 코드는 제 깃허브에서 보실 수 있습니다. GitHub - jangjh123/Jetpack-Compose-CustomView: Jetpack C..
[Jetpack Compose] 상태 호이스팅 기존 XML 방식에는 큰 문제점이 하나 있었는데, 그것은 바로 View 가 스스로의 상태를 정의하고 보존한다는 것입니다. 상태는 View 를 그 자체로 인식할 수 없도록 하며, 이는 곧 테스트 가능성과 재사용성을 저해하는 원인이 됩니다. State Hoisting Jetpack Compose 를 활용하여 UI 를 작성할 때에 사용할 수 있는 패턴입니다. Composable 은 XML 방식의 View 와 다르게, 그 자체로는 Stateless 상태입니다. 얼마든 재사용할 수 있고, 얼마든 테스트할 수 있습니다. 다만, Composable 이 특정한 상태가 부여되거나 특정 상황에 결속되는 경우가 있습니다. 전자는 TextField, Scrollable 한 Composable 이 해당하고, 후자의 경우 클릭 ..
[Jetpack Compose] LazyColumn/LazyRow/Pager OverScrollEffect 없애기. 개발중인 앱에서 HorizontalPager(LazyColumn, LazyRow, VerticalPager 모두 해당 됩니다.) 를 사용중인데, OverScrollEffect 가 적용되어 있어, Fancy 하지 못한 느낌을 줍니다. CompositionLocalProvider(LocalOverscrollConfiguration.provides(null)) { // Composable } 사용하고자 하는 Composable 을 위 CompositonLocalProvider 블록으로 감싸주면 됩니다. 주의할 점은, 여전히 체험판이기에 @OptIn Annotation 이 필요합니다. @OptIn(ExperimentalPagerApi::class, ExperimentalFoundationApi::class) C..
ViewModel 의 illegalStateException: Can not perform this action after onSaveInstanceState 앱 리팩토링 중 만나게 된 예외입니다. 위치 서비스 권한을 획득하기 위해 Callback 을 두고 Intent 로 위치 서비스 설정 창으로 이동합니다. 위치 서비스를 사용하도록 설정한 뒤 돌아와 즉시 ViewModel 을 참조하니 발생한 에러입니다. java.lang.IllegalStateException: Can not perform this action after onSaveInstanceState onSaveInstanceState() 이후에 해당 액션을 진행할 수 없다고 나옵니다. 이는 안드로이드 액티비티의 생명주기와 관련한 예외입니다. onSaveInstanceState() 에 액티비티에서 참조가 남아있는 객체들을 저장합니다. onSaveInstanceState() 는 onStop() 과 onD..
[Glide] Glide 의 Cache Glide 사용하고 계신가요? 안드로이드 개발자들이 가장 사랑하는 이미지 처리 라이브러리입니다. 저 또한 애용 중이며, 많은 분들께서 사용 중이시리라 생각합니다. 수많은 메서드를 통해 이미지 수정 및 처리가 가능하고 Third-Party-Library도 많은 데다가 gif까지 훌륭히 지원하니, 놀랍도록 우수한 라이브러리가 등장하지 않는 이상은 Glide가 다른 라이브러리에게 자리를 내어줄 일은 없어 보입니다. Glide는 기본적인 캐시(Cache)를 지원하고 있습니다. 그럴 수 밖에 없는 것이, 앱 내 리소스에 이미지를 포함시키기에는 너무나 방대한 양의 이미지 파일을 저장해야 하는 경우가 많을 것이기 때문입니다. 아래는 제가 직접 제작한 1인 개발 앱 입니다. 저는 Glide에 기본 캐시가 있다는 것을 ..
[Dagger-Hilt] ActivityScope 와 ActivityRetainedScope 의 차이 Hilt Hilt 는 현재 가장 주목 받는 DI (Dependency Injection) 라이브러리입니다. 안드로이드 제트팩 라이브러리 이기도 하죠. Hilt 에는 수많은 스코프 가 있습니다. 스코프의 존재 이유는 외부에서 생성되어 주입되는 인스턴스가 안드로이드 컨테이너의 생명주기에 따라 자동적으로 생성 및 해제되도록 하기 위해서입니다. 제 때 생성되지 않아 문제가 생기는 경우나, 해제되지 않아 지속적으로 메모리가 낭비되는 상황을 방지하기 위해서지요. Scoping an object A to another object B means that throughout the lifecycle of B, it’ll always have the same instance of A. (오브젝트 A를 B에 스코핑하는 것..