Today I Learn

Crashlytics 살피던 중, 아래와 같은 Error Report를 발견했다. Fatal Exception: java.lang.IllegalArgumentException: View=DecorView@b5f5db7[TestActivity] not attached to window manager at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:657) at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:564) at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.j..
개발을 진행하면서 App에 특정 테마 색상을 지정하고 싶은 경우가 있다. 그때 테마가 어두운 계열인지 밝은 계열인지에 따라 Full Screen이 아닌 이상 Status Bar와 Navigation바 아이콘 색상을 테마 색상에 대해 반전시키는 것이 좋다. val isDarkTheme = AppTheme.isDarkTheme() //Custom function to check if it is dark theme WindowInsetsControllerCompat(window, window.decorView).isAppearanceLightStatusBars = !isDarkTheme WindowInsetsControllerCompat(window, window.decorView).isAppearanceLi..
const val은 컴파일 시간 동안 할당되는 상수 값이다. 따라서 함수나 생성자에게도 결코 할당 불가능하며, 오직 문자열이나 기본 자료형으로만 선언될 수 있다. companion object { const val KET_POSITION = "position" } - 클래스의 프로퍼티나 지역 변수 할당이 불가능하여 companion object 내부에 선언한다. - 자바에서는 static final 같은 형태이다.
네트워크 캐시 역할 : 파일 시스템에 대한 HTTP 및 HTTPS 응답을 캐시하여 재사용할 수 있으므로 시간과 대역폭이 절약됩니다. 하지만, 간혹 서버의 변경 사항을 즉각적으로 반영해야할 때, 오히려 걸림돌이 되는 경우가 있다. builder.addInterceptor(Interceptor { val request = it.request().newBuilder().cacheControl(CacheControl.Builder().noCache().build()) Request 빌더에 캐시 기능 없음을 명시하거나 interface TestApi { @Headers("Cache-Control: no-cache") @GET("test/test.json") fun checkTest(): Call } 인터페이스에 ..
서버와의 협업 중, 어떤 사유로 반환 값이 empty body가 수신될 때, 제목과 같은 Exception이 발생했다. 명시한 data class와 별개로 해당 상황에 대한 response body convert 처리가 필요한 것으로 파악된다. 따라서 다음과 같이 Custom Converter Factory를 생성하여 Retrofit Builder에 반영해주어야한다. class EmptyResponseConverterFactory : Converter.Factory() { override fun responseBodyConverter( type: Type, annotations: Array, retrofit: Retrofit ): Converter { val delegate = retrofit.nextR..
안드로이드 시스템 환경설정에는 애니메이션 끄기 여부를 선택할 수 있는 기능이 있다. 해당 토글을 ON 처리하면 디바이스 전반적으로 애니메이션 기능이 제거된다. 하지만 애니메이션이 사용된 앱 같은 경우, 정상적인 View 동작을 위해 분기처리가 필요한 경우가 있다. 이럴 때, 다음 코드를 통해 애니메이션 활성화 여부를 확인할 수 있다. fun isAnimationEnabled(context: Context): Boolean { var isEnable = true try { isEnable = Settings.Global.getFloat(context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE) != 0f } catch (e: Settings.Set..
EditText에 하이픈(-)이 자동 추가되도록 TextWatcher에서 지원하는 PhoneNumberFormattingTextWatcher를 사용할 수 있다. 아래 Listener를 등록만 해도 자동으로 전화번호 형식이 입력되는 것을 확인 가능하다. binding.numberEdit.addTextChangedListener(PhoneNumberFormattingTextWatcher())
안드로이드의 Activity에서는 navigationBarColor를 다음과 같이 지정해줄 수 있다. activity.window.navigationBarColor = getColor(R.color.white) 그런데, Activity 수준에서 색상을 지정해도 Bottom Sheet를 열면 적용되어 있지 않아 별도로 지정이 필요하다. 다음과 같이 override되는 Dialog 객체를 통해 지정 가능하다. override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val dialog = super.onCreateDialog(savedInstanceState) dialog.window?.navigationBarColor = activity.get..
안드로이드 ImageView의 테두리 형태를 지정하기 위해 Background Drawable을 다음과 같이 구성하여 작업 중이었다. BottomSheet 형태의 디자인을 만들고, 해당 View에 원하는 이미지를 CenterCrop 형태로 채워서 넣으려했다. android:scaleType="centerCrop" -> 이미지의 가로/세로의 길이 중 짧은 쪽을 ImageView의 레이아웃에 가득 채워 출력한다. 이 때 원본 이미지 가로/세로의 비율은 유지되고 레이아웃 영역에서 벗어난 이미지는 출력되지 않는다. 하지만 이미지를 삽입하니 기존에 생성했던 Background를 무시하고 이미지의 형태가 덮어씌워졌다. ImageView는 Image를(src) 새로 삽입하면 보이는 화면과 같이 적용될 수 밖에 없다고..
안드로이드 UI 작업 중, 간혹 원 모양의 View가 필요한 경우가 있습니다. 다음과 같이 Background Resource를 커스텀으로 만들어주는 방법도 있으나, de.hdodenhof:circleimageview 라이브러리를 통해 Circle Image View를 바로 생성하는 방법 또한 있습니다. https://github.com/hdodenhof/CircleImageView ImageView를 확장해서 만들어진 라이브러리이기 때문에 기본 사용법은 ImageView와 동일합니다. implementation 'de.hdodenhof:circleimageview:3.1.0' 아래와 같이 레이아웃을 삽입해주고, 각종 속성들을 설정해줍니다. 옵션 중 civ_border_~ 형태의 옵션들을 통해 Circl..
SeungYong.Lee
'Today I Learn' 카테고리의 글 목록 (2 Page)