티스토리 뷰
지난 포스트에 생각보다 반응이 좋아 이번 포스트에서는 이전 포스트에서 진행하였던 Gradle Sync 세팅을 바탕으로 기본적인 Material Design 을 활용하여 안드로이드 화면 내에 Material Button 을 표시해 보겠다.
이번 포스트는 이전 포스트와 비교해 버전 차이가 있을 수 있으므로 다음 build.gradle 파일을 참조하여 버전을 맞추기 바란다. (2020년 7월 기준)
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.example.materialtestapplication"
minSdkVersion 24
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
// 코틀린 지원
implementation 'androidx.core:core-ktx:1.3.0'
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation 'com.google.android.material:material:1.1.0'
}
이전 프로젝트에서는 Java 언어를 베이스로 프로젝트를 구성하였지만, 올해에 구글에서 코틀린(Kotlin) 언어를 공식 언어로 지정함에 따라 다음 코드를 추가하여 코틀린 지원을 포함하도록 한다.
dependencies {
// ...
// 코틀린 지원
implementation 'androidx.core:core-ktx:1.3.0'
// ...
}
위 프로젝트 세팅을 마치고 Gradle Build 까지 완료되었다면 res/layout/activity_main.xml 파일로 이동한다.
레이아웃의 배치를 보면, 다음과 같이 ConstraintLayout 내에 TextView가 기본적으로 배치되어 있는 것을 볼 수 있다.
<androidx.constraintlayout.widget.ConstraintLayout
...
...>
<TextView
...
... />
</androidx.constraintlayout.widget.ConstraintLayout>
Android Studio 의 버전에 따라 해당 파일의 배치가 다를 수 있다. 2020년 7월 기준으로 구버전(3버전 이하)의 경우 ConstraintLayout이 아닌 LinearLayout일 수 있으나, Gradle 의 dependencies에서 constraintlayout 의존성을 추가하였다면 ConstraintLayout을 정상적으로 사용할 수 있다. 현재 Android Studio의 버전은 4.0 이므로, 되도록 최신 버전을 사용하는 것을 권장한다.
이제 로딩된 레이아웃 파일을 확인하였으니 본격적으로 버튼을 배치해 보자. 이제부터 할 작업은 Google Material Design의 Button 안드로이드 컴포넌트 가이드 문서에서도 동일하게 확인할 수 있다.
Google Material 가이드 문서에는 개발 뿐만 아니라 디자인 철학, 디자이너를 위한 디자인 배치 요소, 무료 아이콘 등 아주 폭넓은 서비스를 제공하니, 꼭 개발자가 아니더라도 알아두는 것이 좋다. 본 포스트의 모든 내용은 다음 링크를 참조한다.
Buttons - Material Components for Android
우선 Material Design 에서 제공하는 버튼에는 크게 네 가지의 종류가 있다.
기본적인 버튼들을 모두 설명하고 그에 대한 속성들도 일부 다룰 것이다.
첫 번째로, Contained Button 버튼이다.
가장 일반적으로 볼 수 있는 버튼으로, 텍스트 앞에 아이콘을 붙일 수도 있다. 버튼을 누르면 동그란 모양으로 효과가 일어나며, 이 또한 Material 시스템에서 기본적으로 제공하는 효과이다.
둘째로, Outlined Button 버튼이다.
말 그대로 Outlined 즉, 바깥에 선이 있다는 뜻이다.
Contained 버튼과 달리 버튼 내부의 텍스트가 버튼 색상을 가지며, 버튼 바깥에 선을 표시함으로써 보다 깨끗한 UI를 구성할 수 있다. 주로 배경색상이 흰색일 경우, 버튼에 너무 과한 강조를 주고 싶지 않을 때 사용하는 편이다. 딱히 사용 목적에 제약이 있지는 않다.
셋째로, Text Button 버튼이다.
버튼의 형태가 없는 텍스트 형식의 버튼이다. 나중에 언급할 CardView와 같은, 특정 컴포넌트 안에 들어가는 컴포넌트의 경우 버튼 자체를 배치하면 복잡한 느낌을 줄 수 있기에 텍스트의 형태를 띠고, 누르면 버튼처럼 효과를 주는 용도로 주로 사용한다. 마찬가지로, 딱히 사용 목적에 제약이 있지는 않다.
넷째로, Toggle Button 버튼이다. 이 버튼을 일반적인 버튼의 형태와는 다르며, 여러 개의 항목 중 한 항목을 선택해야 할 때 주로 사용된다.
이제 차례대로 구현해 보겠다.
우선 Contained Button 버튼을 구현한다. 기본적으로 ConstraintLayout 내에 TextView가 구현된 코드 중 TextView에 해당하는 코드를 지운다. 그리고 다음과 같이 Android Studio의 자동화 기능을 이용하여 MaterialButton 컴포넌트를 호출한다. 그리고, layout_width, layout_height를 자동으로 설정해 주는데, layout_width는 match_parent로, layout_height는 wrap_content로 설정하자.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</androidx.constraintlayout.widget.ConstraintLayout>
코드에 대한 설명을 덧붙이자면,
layout_width : 해당 레이아웃 (여기에서는 MaterialButton) 의 너비 값을 지정한다.
layout_height: 해당 레이아웃의 높이 값을 지정한다.
여기까지 진행하면, 아마 MaterialButton 컴포넌트의 선언부에 빨간 줄이 그어지며 에러가 날 것이다.
This view is not constrained vertically; at runtime it will jump to the top unless you add a vertical constraint
해석하자면, '이 뷰는 수직적으로 제약되어 있지 않습니다. 수직적 제약조건을 설정하지 않는다면 실제 구동환경에서 이 뷰는 가장 위로 위치할 것입니다' 로 해석된다.
기본적으로 ConstraintLayout은 뷰에 제약 조건을 지정함으로써 실제 배치가 이루어진다. 따라서 Split에서 오른쪽 Component Tree 또는, Design 탭에서 MaterialButton 뷰의 상단 핸들(Handle)을 Parent ViewGroup인 ConstraintLayout 최상단으로 드래그해 제약 조건을 설정해 준다. 또한, 왼쪽, 오른쪽도 parent로 제약 조건을 걸어 준다.
(ConstraintLayout에 대한 이해도가 없으신 분께서는 본 포스팅의 배치 작업이 조금 어려울 수 있다. LinearLayout에서 비슷하게 시도해 보거나 ConstraintLayout에 대한 공부를 선행하시는 것을 추천드린다.)
코드로 표현하면 다음과 같다.
<com.google.android.material.button.MaterialButton
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
이제 당장 급한 에러는 없어질 테고, 다음과 같은 상태가 될 것이다.
그러면 이제 이 버튼에 배경 색상과 텍스트 그리고 아이콘도 추가해 보자.
android:background="@color/colorPrimary" android:text="Button"
속성 |
설명 |
android:background |
컴포넌트의 배경 색상을 지정한다. 이 속성에는 굳이 색상 값이 아니어도 그라데이션이나 다른 값이 올 수도 있다. 본 포스트에서는 values/colors.xml에 기본적으로 정의되어 있는 colorPrimary 값을 가져왔다. |
android:text |
컴포넌트에 포함될 글자의 값을 지정한다. |
추가로 글자의 색상도 흰색으로 바꿔 보자.
android:textColor="@android:color/white"
속성 |
설명 |
android:textColor |
글자의 색상을 변경할 수 있다. 색상을 직접 지정할 수도 있고, @android:color를 통해 android에서 내부적으로 제공하는 색상을 사용할 수도 있다. |
결과물은 다음과 같을 것이다.
성능 최적화를 위해 글자를 별도로 분리해서 작성하는 것이 원칙이지만, 편의를 위해 그냥 넘어가겠다.
마지막으로, 실제 앱의 테마에 Material Components를 적용하기 위해 values/styles.xml 파일을 열어 theme을 수정한다.
<resources>
<!-- style의 parent를 아래와 같이 수정한다. -->
<style name="AppTheme" parent="Theme.MaterialComponents.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>
</resources>
어떤 결과물이 나오는지 실제 기기를 구동하여 테스트해 보자. 본 포스트에서는 편의를 위해 가상 디바이스 (AVD) 를 사용할 것이다. 되도록이면 실제 기기를 사용해 테스트하는 것을 권장한다.
기본적인 버튼이 정상적으로 출력되었다. 약간의 UI 개선 이후 아이콘도 추가해 보겠다.
layout_width 값을 150dp로 변경하였다. 이제 버튼 텍스트 왼쪽에 아이콘을 추가해 보자.
Material Components 에서는 MaterialButton 의 구조를 다음과 같이 설명하고 있다.
간단하다. 텍스트, 컨테이너, 아이콘 끝이다. 추가적으로 제공하는 속성에는 다음과 같은 요소들이 있다.
모두 실습해 볼 것이기에 한번 훑어보고 넘어가도 된다.
텍스트 속성들
Text label attributes
|
속성 |
연관 속성 |
기본 값 |
텍스트 라벨 (Text label) |
android:text |
setText getText |
null |
색상 (Color) |
android:textColor |
setTextColor getTextColor |
?attr/colorPrimary |
글씨체 (Typography) |
android:textAppearance |
setTextAppearance |
?attr/textAppearanceButton |
거의 모든 속성들을 본 적이 있을 것이다. 텍스트를 지정하거나, 색상을 지정하는 함수들이다. textAppearance의 경우는 텍스트의 크기를 지정하는 역할을 한다.
버튼 컨테이너 속성들
Container attributes
|
속성 |
연관 속성 |
기본 값 |
색상 (Color) |
app:backgroundTint |
setBackgroundColor setBackgroundTintList getBackgroundTintList |
@android:color/transparent |
테두리 색상 (Stroke color) |
app:strokeColor |
setStrokeColor setStrokeColorResource getStrokeColor |
null |
테두리 너비 (Stroke width) |
app:strokeWidth |
setStrokeWidth setStrokeWidthResource getStrokeWidth |
0dp |
모양 (Shape) |
app:shapeAppearance |
app:shapeAppearanceModel getShapeAppearanceModel |
?attr/shapeAppearanceSmallComponent |
입체 효과 (Elevation) |
app:elevation |
setElevation getElevation |
0dp |
효과 색상 (Ripple color) |
app:rippleColor |
setRippleColor setRippleColorResource getRippleColor |
?attr/colorPrimary 의 12% 투명도 |
아이콘 속성들
Icon attributes
|
속성 |
연관 속성 |
기본 값 |
아이콘 (Icon) |
app:icon |
setIcon setIconResource getIcon |
null |
색상 (Color) |
app:iconTint |
setIconTint setIconTintResource getIconTint |
?attr/colorPrimary |
크기 (Size) |
app:iconSize |
setIconSize getIconSize |
wrap_content |
위치 (Gravity) |
app:iconGravity |
setIconGravity getIconGravity |
start |
여유공간 (Padding) |
app:iconPadding |
setIconPadding getIconPadding |
4dp |
간단히 실습을 통해 속성을 알아보겠다.
<com.google.android.material.button.MaterialButton
android:layout_width="150dp"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:elevation="5dp"
android:text="Button"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/white"
app:icon="@drawable/ic_launcher_foreground"
app:iconGravity="start"
app:iconPadding="@dimen/cardview_compat_inset_shadow"
app:iconSize="50dp"
app:iconTint="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:rippleColor="@color/colorAccent"
app:strokeColor="@color/colorAccent" app:strokeWidth="3dp" />
코드를 작성한 후 MaterialButton 컴포넌트의 코드만 가져와 보았다. 전체 코드에 대한 설명은 다음과 같다.
android:layout_width="150dp" |
너비를 150dp로 정한다. |
android:layout_height="wrap_content" |
높이를 해당 컴포넌트의 최적의 크기로 자동 조절한다. |
android:backgroundTint="@color/colorPrimary" |
버튼의 배경 색상을 colorPrimary 색상으로 정한다. |
android:elevation="5dp" |
버튼의 입체 효과를 위한 그림자를 적용한다. |
android:text="Button" |
버튼의 텍스트를 지정한다. |
android:textAppearance="@style/TextAppearance.AppCompat.Medium" |
버튼의 텍스트 크기를 미리 지정되어 있는 Medium 크기로 정한다. |
android:textColor="@android:color/white" |
텍스트의 크기를 흰색으로 지정한다. |
app:icon="@drawable/ic_launcher_foreground" |
MaterialButton에 아이콘을 추가한다. |
app:iconGravity="start" |
해당 아이콘의 위치를 버튼의 시작 지점 (왼쪽) 으로 정한다. |
app:iconPadding="@dimen/cardview_compat_inset_shadow" |
해당 아이콘의 여유공간을 지정한다. |
app:iconSize="50dp" |
해당 아이콘의 크기를 지정한다. |
app:iconTint="@android:color/white" |
아이콘의 색상을 지정한다. |
app:layout_constraintEnd_toEndOf="parent" |
버튼 컴포넌트에 parent 레이아웃의 제약 조건을 지정한다. |
app:layout_constraintStart_toStartOf="parent" |
버튼 컴포넌트에 parent 레이아웃의 제약 조건을 지정한다. |
app:layout_constraintTop_toTopOf="parent" |
버튼 컴포넌트에 parent 레이아웃의 제약 조건을 지정한다. |
app:rippleColor="@color/colorAccent" |
버튼 컴포넌트의 터치 효과 색상을 지정한다. |
app:strokeColor="@color/colorAccent" |
버튼의 테두리 색상을 지정한다. |
app:strokeWidth="3dp" |
버튼의 테두리 너비를 지정한다. |
접두어가 android: 인 경우에는 안드로이드 고유 속성을 의미하고, 접두어가 app: 인 경우는 Material Components 에서 제공하는 속성을 의미한다.
위 코드의 결과는 다음과 같다.
전체 코드는 다음과 같이 공개한다.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.button.MaterialButton
android:layout_width="150dp"
android:layout_height="wrap_content"
android:backgroundTint="@color/colorPrimary"
android:elevation="5dp"
android:text="Button"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
android:textColor="@android:color/white"
app:icon="@drawable/ic_launcher_foreground"
app:iconGravity="start"
app:iconPadding="@dimen/cardview_compat_inset_shadow"
app:iconSize="50dp"
app:iconTint="@android:color/white"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:rippleColor="@color/colorAccent"
app:shapeAppearance="@style/ShapeAppearance.MaterialComponents.MediumComponent"
app:strokeColor="@color/colorAccent"
app:strokeWidth="3dp" />
</androidx.constraintlayout.widget.ConstraintLayout>
다음 포스트에서는 OutlinedButton 버튼을 구현해 보겠다.
질문과 댓글은 언제나 환영한다.
'프로그래밍 > Android' 카테고리의 다른 글
[Google Material Design] Bottom Navigation 만들기 -1 (0) | 2020.07.14 |
---|---|
[Google Material Design] Button 만들기 -2 (0) | 2020.07.13 |
[안드로이드] Google Material Design 적용하기 (0) | 2020.07.11 |
- Total
- Today
- Yesterday
- 메터리얼
- EC2
- main
- 테라폼
- entrypoint
- 스타트업
- 도커
- Terraform
- ecr
- 자바
- 안드로이드
- 컨테이너
- dockerhub
- AWS
- docker
- Operator
- HCL
- 자료형
- env
- 자격증명
- DESIGN
- 디자인
- 머티리얼
- uiux
- cmd
- Material
- dockerfile
- Android
- Java
- Container
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |