Upgrade to Pro — share decks privately, control downloads, hide ads and more …

XML details for Android UI

XML details for Android UI

2020 NAVER TECH CONCERT에서 발표한 내용입니다.
http://techcon.naver.com/
https://github.com/fornewid/TECHCON-2020-Sample

Sungyong An

August 19, 2020
Tweet

More Decks by Sungyong An

Other Decks in Programming

Transcript

  1. 안드로이드에서 XML은 어디에 사용할까? - 애니메이션 - 이미지 - UI

    레이아웃 - 메뉴 - 앱 탐색 그래프 - 리소스 (문자열, 크기, 색상 등) … 다양한 곳에 사용하고 있다! 어떻게 사용될까? 개발할때,조금더신경쓰면좋을내용을다뤄봅시다.
  2. 버튼이 잘 안 눌러지는 이유 주로 이미지 버튼에서 발생하는데, View

    영역이 손가락으로 누를 수 있을만큼 적절하게 확보되지 않는 것이 원인이다. <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="24dp" android:src="@drawable/ic_search" ... 아이콘은24x24dp크기
  3. 버튼이 잘 안 눌러지는 이유 Margin은 View 터치 영역으로 간주되지

    않는다. 디자인 가이드를 맹목적으로 따르지 말고 사용성을 고려하여 터치영역을 적절히 확보하는 것이 좋다. <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="12dp" android:padding="12dp" android:src="@drawable/ic_search" ... XML코드한줄에도큰차이가발생할수있다!
  4. 버튼이 안 눌러지는 것처럼 보이는 이유 <FrameLayout android:foreground="?selectableItemBackground"> 사용하는 View(=FrameLayout)에

    있는 속성만 아니라 상속하는 상위 View 속성도 사용할 수 있다는 것을 알 수 있다.
  5. <LinearLayout> <View /> <View /> <LinearLayout> <ImageView /> <TextView />

    </LinearLayout> </LinearLayout> 레이아웃 XML이 화면에 어떻게 그려지게 되는지 과정이 궁금하다면? 3
  6. LayoutInflater override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) } @Override

    public void setContentView(int resId) { ... LayoutInflater.from(mContext).inflate(resId, ...); ... }
  7. LayoutInflater <View /> <View /> <View /> View는 선언된 순서대로

    그려진다. 레이아웃이 겹쳐지는 경우에는 고민이 필요하다. (ex. RecyclerView + Button 등)
  8. LayoutInflater Z축을 변경하는 방법을 사용할 수도 있다. 단, BG가 있으면

    그림자 효과가 나타나니 주의할 것. <View /> <View android:elevation="12dp" android:translationZ="12dp" /> <View />
  9. 4 android:tint 속성을 이용하여, 상태에 따라 아이콘 색상을 다르게 보여줄

    수 있다. <ImageView android:src="@drawable/ic_heart" android:tint="@color/selector_heart" ... /> <selector> <item android:color="@color/alert" /> </selector>
  10. AppCompat 하지만 API 21 미만에서는 런타임에 오류가 발생한다. <ImageView android:src="@drawable/ic_heart"

    android:tint="@color/selector_heart" ... /> 위 속성에서 발생한 문제다.
  11. AppCompat <ImageView android:src="@drawable/ic_heart" app:tint="@color/selector_heart" ... /> 플랫폼 속성 대신 커스텀

    속성으로 변경하면 API 21 미만에서도 ColorStateList가 동작한다. 무슨 차이가 있는 걸까?
  12. <declare-styleable name="ImageView"> <!-- The tinting color for the image. By

    default, the tint will blend using SRC_ATOP mode. Please note that for compatibility reasons, this is NOT consistent with the default SRC_IN tint mode used by {@link android.widget.ImageView#setImageTintList} and by similar tint attributes on other views. --> <attr name="tint" format="color" /> </declare-styleable> <declare-styleable name="AppCompatImageView"> <!-- Tint to apply to the image source. --> <attr format="color" name="tint"/> </declare-styleable> android:tint 는 ImageView의 속성이고, app:tint 는 AppCompatImageView의 속성이다.
  13. AppCompat <ImageView android:src="@drawable/ic_heart" app:tint="@color/selector_heart" ... /> 잠깐! ImageView가 어떻게 AppCompatImageView가

    된걸까요? class MainActivity : AppCompatActivity() 비밀(?)은 상속에 숨어 있습니다.
  14. AppCompat과 MDC 상속 테마에 따라 View 구현체가 달라진다. AS 4.0

    까지는 기본 프로젝트를 생성하면 AppCompat을 상속하지만, AS 4.1 부터는 MDC를 상속하는 것으로 변경되었으니 주의할 것!
  15. Style과 Theme <LinearLayout android:theme="@style/AppTheme"> <Button style="@style/Widget.AppCompat.Button.Colored" android:text=" TOP " />

    <androidx.constraintlayout.widget.ConstraintLayout android:theme="@style/AppTheme.Grayscale"> <Button style="@style/Widget.AppCompat.Button.Colored" android:text=" LEFT " /> <Button android:text=" RIGHT "/> </androidx.constraintlayout.widget.ConstraintLayout> <Button android:text=" BOTTOM " /> </LinearLayout> <style name="AppTheme" parent="Theme.AppCompat.Light"> <item name="colorAccent">#FF2C2C</item> </style> <style name="AppTheme.Grayscale"> <item name="colorAccent">#000000</item> </style>
  16. Style과 Theme <LinearLayout android:theme="@style/AppTheme"> ... <Button android:text=" BOTTOM " />

    </LinearLayout> 아무것도설정하지않은버튼의기본색상은뭘까? 즉, Theme는 자신을 포함하여 하위 View에도 영향을 준다.
  17. Style과 Theme <manifest> <application android:theme="@style/AppTheme"> <activity android:theme="@style/AppTheme.Specific" /> </application> </manifest>

    상황에 따라 화면 단위로 Theme를 적절히 설정해주고, 세세하게 변경이 필요하면 해당 View에 Style을 설정하는 것을 추천한다.
  18. WindowBackground 이 경우, 개발자 옵션으로 overdraw를 확인해보면 화면의 모든 영역이

    불필요하게 한번씩 더 그려진다. background 속성을 사용하지 않고, 기본 배경색을 변경할 수는 없을까?
  19. WindowBackground <style name="AppTheme" parent="..."> <item name="android:windowBackground">#ffffff</item> </style> <LinearLayout> ... </LinearLayout>

    windowBackground 속성을 이용하면 이 부분을 개선할 수 있다. 어디에 그려지는지는 직접 찾아보면 재미있겠죠?
  20. 7 <shape> drawable 많이 쓰시나요? <shape android:shape="rectangle"> <corners android:radius="24dp" />

    <solid android:color="#DDDDDD" /> <stroke android:width="4dp" android:color="#CCCCCC" /> </shape>
  21. 생각보다 강력한 Drawable <ripple android:color="#FF2C2C"> <item android:drawable="@drawable/shape" /> <item android:id="@android:id/mask"

    android:drawable="@drawable/ic_bug" /> </ripple> Ripple 효과의 영역을 다르게 설정할 수도 있다. (= mask)
  22. 생각보다 강력한 Drawable 조금 복잡한 조건의 배터리 UI를 만들어보자! A.

    0 ~ 100% 단계가 1% 단위로 보인다. B. 1 ~ 20% 단계에서는 빨간색으로 보인다. C. 0 ~ 1% 단계에서는 경고 아이콘(❗)이 보인다. D. 충전중에는 0 ~ 20% 단계에서도 검정색으로 보이고, 충전 아이콘(⚡)이 함께 보인다. Java 또는 Kotlin 코드 없이도 이미지 5장만으로 구현할 수 있다면? empty low full alert charge
  23. 생각보다 강력한 Drawable <selector> <item android:state_activated="true"> <layer-list> <item android:drawable="@drawable/empty" />

    <item> <clip android:drawable="@drawable/full" android:clipOrientation="vertical" android:gravity="bottom" /> </item> <item android:drawable="@drawable/charge" /> ⚡ </layer-list> </item> <item /> <!-- Normal --> </selector> selector, layer-list, level-list, clip 등을 혼합하면 가능하다. 먼저 충전중 상태부터 구현해보자. 임시로 Activated 상태를 충전중이라 가정했다. 이미지를 겹쳐 보여줘야 할 때 사용한다. ProgressBar 처럼 이미지를 단계 별로 자를 때 사용한다.
  24. 생각보다 강력한 Drawable <level-list> <item android:minLevel="0" android:maxLevel="100"> <layer-list /> ❗

    </item> <item android:minLevel="101" android:maxLevel="2000"> <layer-list /> </item> <item android:minLevel="2001" android:maxLevel="10000"> <layer-list /> </item> </level-list> 다음으로 기본 상태를 살펴보자. level-list를 사용하여 각 level에 맞는 이미지 조합을 보여주자. 참고로 level은 0 ~ 10000 단계를 가진다.
  25. 생각보다 강력한 Drawable <ImageView android:src="@drawable/ic_battery" /> val level: Int =

    ... // 0 ~ 100 val batteryView: ImageView = ... batteryView.setImageLevel(level * 100) batteryView.isActivated = isCharging setActivated, setImageLevel API를 호출하면 구현 완료! Drawable 구현체가 궁금하다면?
  26. Resource Qualifier 색상 외에 이미지 등 다른 리소스도 -night qualifier를

    사용할 수 있다. <resources> <color name="background">#202020</color> <color name="icon">#FFFFFF</color> </resources> res/values-night/colors.xml res/drawable/ic_drink.xml res/drawable-night/ic_drink.xml
  27. Resource Qualifier 이외에도 다양한 Qualifier를 이용하여, 안드로이드의 파편화된 기기 생태계에

    적응할 수 있다. res/layout-land/activity_main.xml res/values-v23/styles.xml res/values-ko/string.xml res/values-sw600dp/dimens.xml
  28. tools 이용하기 레이아웃 XML을 작성하면 왼쪽 화면처럼 보인다. <androidx.constraintlayout.widget.ConstraintLayout> <androidx.appcompat.widget.Toolbar

    /> <androidx.recyclerview.widget.RecyclerView /> </androidx.constraintlayout.widget.ConstraintLayout> 빌드하기 전에 미리 볼 수 있는 방법이 있다면?
  29. tools 이용하기 <ConstraintLayout> <CircleImageView tools:src="@tools:sample/avatars" /> <TextView tools:text="@tools:sample/full_names" /> <ImageView

    /> </ConstraintLayout> 미리 정의된 tools 샘플 데이터를 이용하면 좀 더 실제처럼 보인다.
  30. tools 이용하기 <ConstraintLayout> <CircleImageView /> <TextView tools:text="@sample/labels" /> <ImageView />

    </ConstraintLayout> {project}/{module}/sampledata/labels 샘플 데이터를 직접 정의할 수도 있다. tools를 이용하여 빌드 횟수를 줄이고, 생산성을 높여보자. I am debugging. My foldable phone. NAVER TECHCON 2020 ⷎ
  31. 정리 margin, padding tools Attribute LayoutInflater AppCompat, MDC WindowBackground Drawable

    Qualifier XML 오늘은 안드로이드를 구성하는 XML 코드에 대해서 살펴봤습니다. 어떤가요. 안드로이드 앱 개발 재미있어 보이지 않나요? Style, Theme