Share
Embed
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
Transcript
70 slides
-
안드로이드에서 XML은 어디에 사용할까? - 애니메이션 - 이미지 - UI
레이아웃 - 메뉴 - 앱 탐색 그래프 - 리소스 (문자열, 크기, 색상 등) … 다양한 곳에 사용하고 있다! 어떻게 사용될까? 개발할때,조금더신경쓰면좋을내용을다뤄봅시다. -
버튼이 잘 안 눌러지는 이유 주로 이미지 버튼에서 발생하는데, View
영역이 손가락으로 누를 수 있을만큼 적절하게 확보되지 않는 것이 원인이다. <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="24dp" android:src="@drawable/ic_search" ... 아이콘은24x24dp크기 -
버튼이 잘 안 눌러지는 이유 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코드한줄에도큰차이가발생할수있다! -
버튼이 안 눌러지는 것처럼 보이는 이유 이럴 때는 foreground와 같은
속성을 사용하여 해결할 수 있다. -
버튼이 안 눌러지는 것처럼 보이는 이유 <androidx.constraintlayout.widget.ConstraintLayout android:background="?selectableItemBackground"> <androidx.constraintlayout.widget.ConstraintLayout android:foreground="?selectableItemBackground">
안드로이드 앱은 OS 버전에 따라 API가 지원되지 않을 수 있다. 이 때는 적절한 대안을 만들면 된다. -
버튼이 안 눌러지는 것처럼 보이는 이유 <FrameLayout android:foreground="?selectableItemBackground"> 그런데 FrameLayout에서는
API 21에서도 foreground 속성이 잘 동작한다. 도대체 왜? -
버튼이 안 눌러지는 것처럼 보이는 이유 <FrameLayout android:foreground="?selectableItemBackground"> 사용하는 View(=FrameLayout)에
있는 속성만 아니라 상속하는 상위 View 속성도 사용할 수 있다는 것을 알 수 있다. -
<LinearLayout> <View /> <View /> <LinearLayout> <ImageView /> <TextView />
</LinearLayout> </LinearLayout> 레이아웃 XML이 화면에 어떻게 그려지게 되는지 과정이 궁금하다면? 3 -
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, ...); ... } -
LayoutInflater <View /> <View /> <View /> View는 선언된 순서대로
그려진다. 레이아웃이 겹쳐지는 경우에는 고민이 필요하다. (ex. RecyclerView + Button 등) -
LayoutInflater Z축을 변경하는 방법을 사용할 수도 있다. 단, BG가 있으면
그림자 효과가 나타나니 주의할 것. <View /> <View android:elevation="12dp" android:translationZ="12dp" /> <View /> -
4 android:tint 속성을 이용하여, 상태에 따라 아이콘 색상을 다르게 보여줄
수 있다. <ImageView android:src="@drawable/ic_heart" android:tint="@color/selector_heart" ... /> <selector> <item android:color="@color/alert" /> </selector> -
AppCompat 하지만 API 21 미만에서는 런타임에 오류가 발생한다. <ImageView android:src="@drawable/ic_heart"
android:tint="@color/selector_heart" ... /> 위 속성에서 발생한 문제다. -
AppCompat <ImageView android:src="@drawable/ic_heart" app:tint="@color/selector_heart" ... /> 플랫폼 속성 대신 커스텀
속성으로 변경하면 API 21 미만에서도 ColorStateList가 동작한다. 무슨 차이가 있는 걸까? -
<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의 속성이다. -
AppCompat <ImageView android:src="@drawable/ic_heart" app:tint="@color/selector_heart" ... /> 잠깐! ImageView가 어떻게 AppCompatImageView가
된걸까요? class MainActivity : AppCompatActivity() 비밀(?)은 상속에 숨어 있습니다. -
LayoutInflater를 통해 레이아웃 XML을 View 구현체로 변환하려고 할 때, 우선적으로
Factory를 이용한다. -
AppCompat과 MDC 상속 테마에 따라 View 구현체가 달라진다. AS 4.0
까지는 기본 프로젝트를 생성하면 AppCompat을 상속하지만, AS 4.1 부터는 MDC를 상속하는 것으로 변경되었으니 주의할 것! -
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> -
Style과 Theme <LinearLayout android:theme="@style/AppTheme"> ... <Button android:text=" BOTTOM " />
</LinearLayout> 아무것도설정하지않은버튼의기본색상은뭘까? 즉, Theme는 자신을 포함하여 하위 View에도 영향을 준다. -
Style과 Theme <manifest> <application android:theme="@style/AppTheme"> <activity android:theme="@style/AppTheme.Specific" /> </application> </manifest>
상황에 따라 화면 단위로 Theme를 적절히 설정해주고, 세세하게 변경이 필요하면 해당 View에 Style을 설정하는 것을 추천한다. -
6 <LinearLayout android:background="#ffffff"> ... </LinearLayout> 혹시 배경이 흰색이 아니라서 root에
background를 설정한 적이 있다면? -
WindowBackground 이 경우, 개발자 옵션으로 overdraw를 확인해보면 화면의 모든 영역이
불필요하게 한번씩 더 그려진다. background 속성을 사용하지 않고, 기본 배경색을 변경할 수는 없을까? -
WindowBackground <style name="AppTheme" parent="..."> <item name="android:windowBackground">#ffffff</item> </style> <LinearLayout> ... </LinearLayout>
windowBackground 속성을 이용하면 이 부분을 개선할 수 있다. 어디에 그려지는지는 직접 찾아보면 재미있겠죠? -
7 <shape> drawable 많이 쓰시나요? <shape android:shape="rectangle"> <corners android:radius="24dp" />
<solid android:color="#DDDDDD" /> <stroke android:width="4dp" android:color="#CCCCCC" /> </shape> -
생각보다 강력한 Drawable <ripple android:color="#FF2C2C"> <item android:drawable="@drawable/shape" /> </ripple> shape
drawable에 Ripple 효과를 쉽게 추가할 수 있다. -
생각보다 강력한 Drawable <ripple android:color="#FF2C2C"> <item android:drawable="@drawable/shape" /> <item android:id="@android:id/mask"
android:drawable="@drawable/ic_bug" /> </ripple> Ripple 효과의 영역을 다르게 설정할 수도 있다. (= mask) -
생각보다 강력한 Drawable 조금 복잡한 조건의 배터리 UI를 만들어보자! A.
0 ~ 100% 단계가 1% 단위로 보인다. B. 1 ~ 20% 단계에서는 빨간색으로 보인다. C. 0 ~ 1% 단계에서는 경고 아이콘(❗)이 보인다. D. 충전중에는 0 ~ 20% 단계에서도 검정색으로 보이고, 충전 아이콘(⚡)이 함께 보인다. Java 또는 Kotlin 코드 없이도 이미지 5장만으로 구현할 수 있다면? empty low full alert charge -
생각보다 강력한 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 처럼 이미지를 단계 별로 자를 때 사용한다. -
생각보다 강력한 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 단계를 가진다. -
생각보다 강력한 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 구현체가 궁금하다면? -
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 -
Resource Qualifier 이외에도 다양한 Qualifier를 이용하여, 안드로이드의 파편화된 기기 생태계에
적응할 수 있다. res/layout-land/activity_main.xml res/values-v23/styles.xml res/values-ko/string.xml res/values-sw600dp/dimens.xml -
이런 목록형 UI를 구현할 때의 과정을 생각해본다면 레이아웃 변경사항을 확인하려고
매번 빌드하지는 않았나? 9 -
tools 이용하기 레이아웃 XML을 작성하면 왼쪽 화면처럼 보인다. <androidx.constraintlayout.widget.ConstraintLayout> <androidx.appcompat.widget.Toolbar
/> <androidx.recyclerview.widget.RecyclerView /> </androidx.constraintlayout.widget.ConstraintLayout> 빌드하기 전에 미리 볼 수 있는 방법이 있다면? -
tools 이용하기 <RecyclerView android:orientation="vertical" app:layoutManager="...LinearLayoutManager" tools:itemCount="3" tools:listitem="@layout/item" /> <ConstraintLayout> <CircleImageView
/> <TextView /> <ImageView /> </ConstraintLayout> tools를 이용하여, 목록의 개수/방향 등을 설정할 수 있다. -
tools 이용하기 <ConstraintLayout> <CircleImageView tools:src="@tools:sample/avatars" /> <TextView tools:text="@tools:sample/full_names" /> <ImageView
/> </ConstraintLayout> 미리 정의된 tools 샘플 데이터를 이용하면 좀 더 실제처럼 보인다. -
tools 이용하기 <ConstraintLayout> <CircleImageView /> <TextView tools:text="@sample/labels" /> <ImageView />
</ConstraintLayout> {project}/{module}/sampledata/labels 샘플 데이터를 직접 정의할 수도 있다. tools를 이용하여 빌드 횟수를 줄이고, 생산성을 높여보자. I am debugging. My foldable phone. NAVER TECHCON 2020 ⷎ -
정리 margin, padding tools Attribute LayoutInflater AppCompat, MDC WindowBackground Drawable
Qualifier XML 오늘은 안드로이드를 구성하는 XML 코드에 대해서 살펴봤습니다. 어떤가요. 안드로이드 앱 개발 재미있어 보이지 않나요? Style, Theme