kotlin SAM, WindowInsets

CmplxN·2020년 8월 23일
0

Kotlin SAM 다루기

SAM은 Single Abstract Method로, SAM을 사용하면 인터페이스(추상 클래스는 안됨)의 단일 추상 함수를 람다함수로 구현할 수 있다. 이를 통해 boilerplate code를 줄일 수 있다.

사용 예시

Android에서는 대표적으로 이벤트 리스너의 등록에 SAM 전환을 사용한다.
예전에 Java에서는 익명 객체를 만들거나, 사용하는 곳에서 인터페이스를 상속 받아 구현했다.

btn.setOnClickListener(this); // interface must be implemented in class
btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
      
    }
});

그러나 kotlin에서는 SAM을 이용, 아래와 같이 OnClickListener를 등록할 수 있다.

btn.setOnClickListenr { ... }

kotlin 인터페이스의 SAM

kotlin 1.4 이전에는 kotlin 인터페이스는 SAM을 사용할 수 없었다.
위에서 기술한 Java 방식을 사용하거나, 고차함수를 사용해서 구현해왔다고 한다.
이제 kotlin 인터페이스에서도 사용 가능하지만, 인터페이스에 fun 키워드를 붙어야한다.

public interface JSAM { // Java Interface
    int jSam(int a);
}
fun interface KSAM { // note that it is "fun" interface
    fun kSam(a: Int): Int
}
fun main() {
    val jSam: JSAM = JSAM { it }
    val kSam: KSAM = KSAM { it }
    println(jSam.jSam(10))
    println(kSam.kSam(20))
}

공식 문서

WindowInsets를 이용한 화면 정보

이전에 Status Bar까지 Activity의 UI영역을 확장하고, soft keyboard를 다루는 것을 포스팅 한 적이 있다. WindowInsets를 사용하는 방식을 알아보자. (Android 11)

soft keyboard의 높이

원래 Android에서 soft keyboard(edittext 눌렀을 때 나오는 keyboard 생각하면 된다)의 높이를 아는 방법은 없었다.
저번에 포스팅 했던 것과 같이 직접 화면의 크기가 바뀐 것을 재는 등 뭔가 찝찝한 방법을 썼어야 했다.
그러나 드디어 Android 11에서 WindowInsets를 통해 직접 키보드 높이를 구할 수 있게 되었다.

whateverWindowInsets.getInsets(WindowInsets.Type.ime())

system bar의 높이 구하기

Android 11 이전에는 아래와 같은 방법으로 system bar(status, navigation)의 windowInsets에 접근했다.

whateverWindowInsets.systemWindowInsetTop
whateverWindowInsets.systemWindowInsetBottom

그러나 Android 11에서는 keyboard를 지원해서 그런 것인지 위의 두 메소드는 deprecated되었다.
이제는 아래 방법을 사용하자.

whateverWindowInsets.getInsets(WindowInsets.Type.statusBars())
whateverWindowInsets.getInsets(WindowInsets.Type.navigationBars())

기존 방법은 키보드 높이 변화에 값이(즉 systemWindowInsetBottom이) 변화했다.
하지만 Android 11부터는 단순히 top bottom left right가 아니라, ime, status bar등 종류별로 제공되기 때문에 이렇게 바뀐 것 같다.

예시 코드

constraint layout(ct_layout)의 Guideline을 windowInsets를 이용해 올리고 내리는 코드를 보자.

ct_layout.setOnApplyWindowInsetsListener { view, windowInsets ->
   guidelineTop.setGuidelineBegin(windowInsets.getInsets(WindowInsets.Type.statusBars()).top)
   guidelineBottom.setGuidelineEnd(
       if (isKeyboardOn) windowInsets.getInsets(WindowInsets.Type.ime()).bottom + 10
       else windowInsets.getInsets(WindowInsets.Type.navigationBars()).bottom
   )
   windowInsets
}
profile
Android Developer

0개의 댓글