Button(IconButton, RadioButton, Switch....) 대부분의 Component 에서 minimumTouchTargetSize() 함수가 내부에서 처리되는 것을 볼 수 있습니다. 잠시 함수를 보면, 48 dp 보다 작은 경우 Component 자체에 Padding 이 들어가게 됩니다(ContentPadding 을 0 으로 줘도 Component 밖으로 Padding 이 생깁니다). 따라서 48 보다 더 작은 값을 넣고 싶은 경우, 내부에 코드들을 모두 복사해서 minimumTouchTargetSize 함수를 제거해줘야 합니다. 혹은 아래와 같이 minimumTouchTargetEnforcement 를 false 로 변경하여 처리할 수도 있습니다. CompositionLocalPr..
관련 문구 https://medium.com/androiddevelopers/navigation-multiple-back-stacks-6c67ba41952f Navigation: Multiple back stacks Welcome to another article in the second MAD Skills series on Navigation! In this article we’ll take a look at a highly requested feature… medium.com 관련 레포지토리 (NavigationAdvancedSample) https://github.com/android/architecture-components-samples/tree/master/NavigationAdvancedSa..
회사에서 필요해서 사용한 후기를 간단하게 적어둡니다. 불편했던 점 1. 사용시에 .proto 파일이 변경되면 빌드가 필요했습니다. 2. Map 같은 구조가 아니기 때문에 여러개 필요하다면, DataStore 객체를 만들어 낼 때, FileName 을 변경하여 처리했습니다.(물론 같은 이름으로 동시에 열수 없도록 처리되어 있습니다) 장점 1. 사용하기가 편합니다. 2. 빌드 이후 Generate 되는 코드를 보며 코드를 작성하면 되서 큰 어려움이 없었습니다. 아래와 같은 데이터 형식을 저장한다고 하면 val foodStores = listOf(FoodStore(....), FoodStore(....), FoodStore(....) ....) data class FoodStore( val name: Stri..
회사 선임분에게 감사의 인사를 최근에 Compose 에서 viewModel 을 파라미터로 넘겨서 사용할 때, 편의를 위해 compositionLocalOf 메서드를 사용하여 같은 Composable Scope 안에서는 currentViewModel() 과 같이 호출하여 당시에 제공하는 Composable Scope 에 맞는 ViewModelStoreOwner 를 넣어주고 viewModel 을 사용할 수 있도록 구성하여 사용하고 있습니다. compositionLocalOf 를 사용할 때, Theme 등의 전파의 개념에만 사용하는 것을 구글 가이드에서는 추천하고 있기 때문에, Interface 형식(AAC 의 의존성도 제거할겸)으로 만들어 사용하고 있습니다. 별문제 없이 사용하다가, 특정 상황에서 curre..
A Activity 에 B Fragment 가 있는 상황에서 A Activity 의 복원이 일어나면, A Activity 의 onCreate 보다 B Fragment 의 onViewCreated 가 먼저 호출됩니다. (정확하게는 A Activity super.onCreate 호출 -> B Fragment 의 onViewCreated 호출 -> A Activity onCreate 호출로 진행됩니다) 따라서 A Activity onCreate 에서 어떤 값을 초기화해주고, B 의 onViewCreated 에서 무언가에 접근하는 코드가 있다면 크래시가 발생하게 됩니다. 복원이 아닌 일반적인 경우는 A activity onCreate 이후 B Fragment onViewCreated 가 호출됩니다. 문제가 생겼..
BroadcastReceiver 를 상속 받아 사용할 때, 마치 싱글턴으로 관리 될 것 처럼 생겼지만, hashCode 찍어보면 매번 생성되는 것을 알 수 있다. 따라서 AppWidgetProvider 를 상속 받아 사용할 때 멤버 변수에 값을 저장하고 사용하는 방식등은 초기화 되기 때문에 조심해야한다. 위젯 좋은 예제
몇일전 기능 구현후 테스트 하는 과정에서 Font 관련 함수에서 특정한 상황에 크래시가 나는 상황을 경험했습니다. 멋진 팀원들의 도움을 받아 어떤식으로 해결하였는지 공유합니다. 크게 1. 왜 크래시가 났는지? 2. 왜 간헐적으로 났는지? 3. 크래시가 나지 않았을 때는 어떤 클래스에서 이를 해소해주고 있었는지? 에 대한 내용으로 구성됩니다. 문제가 생긴 함수는 아래와 비슷한 식의 Font 의 id 를 가져와서 적용해주는 코드였습니다. // 예시 함수 fun TextView.setFont(@FontRes fontRes: Int) = apply { typeface = ResourcesCompat.getFont(context, fontRes) } 크래시 재현 상황은 앱 시작하자마자 특정 화면으로 이동하거나, ..
Coil 은 썸네일 기능을 따로 제공하지 않고 있습니다. 이때 사용해 볼 수 있는 확장 함수 입니다. fun ImageView.loadOriginalImage(originUrl: String, thumbnailUrl: String) { CoroutineScope(Dispatchers.Main.immediate).launch { val thumbnail = async(Dispatchers.IO) { val request = ImageRequest.Builder(context) .data(thumbnailUrl) .build() Coil.execute(request).drawable } val original = async(Dispatchers.IO) { val request = ImageRequest.Bu..
중요) 본 글은 원하는 사이즈를 보냈을 때 리사이즈 해주는 서버가 필요합니다. 이전에 회사에서 Glide -> Coil 로 마이그레이션 작업을 진행하면서 경험한 내용으로 이미지 사이즈에만 중점을 두고 있습니다. 또한 기승전결이 부족하고 도움이 되지 않을 수도 있습니다. OnDemand image resizing 이란 ? - 클라이언트의 요청에 따라 리사이징 된 이미지가 제공 되는 것을 의미합니다. 일단은 Coil 라이브러리내에서 사이즈 관련하여, 이미지를 효율적으로 로드하기 위한 방법이 존재하기 때문에 이부분을 먼저 보고 가겠습니다. sizeResolver 부분이 이미지를 로드할 때, 사이즈를 결정하는 부분입니다. 따로 명시적으로 처리하지 않으면, resolveSizeResolver() 함수가 불리우게 ..