안드로이드 앱 개발 부트캠프 섹션4 수강을 마치고, 중요하다고 싶은 내용들을 적어보았다..
어떻게 적어야될 지 잘 모르겠어서, 일단 작성한 코드를 모두 올리고, 중요하다 싶은 내용들을 적어보겠다.
(레이아웃만 작성하는 것만해도 어렵다 ㅠ_ㅠ Material Design을 사용하는 것이 처음이라 그런가 ..? )
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/shoppi_white">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar_product_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|enterAlways"
app:navigationIcon="@drawable/ic_gnb_back" /> <!-- AppBar의 뒤로 가는 내비게이션을 지정한다. -->
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!-- 스크롤 뷰의 시작점이 appBar의 하단으로 이동.-->
<!-- NestedScrollView는 자식 뷰로 추가되는 뷰들을 감싸주는 컨테이너가 필요하다 -->
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iv_product_thumbnail"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginStart="16dp"
android:layout_marginEnd="16dp"
android:contentDescription="@string/description_product_thumbnail"
android:src="@drawable/img_pdp_top_01"
app:layout_constraintDimensionRatio="w, 1:1" width를 기준으로 height와 1:1 비율로 하겠다는 뜻
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_product_brand_name"
style="@style/TextSubtitle3.Grey03"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:layout_marginEnd="16dp"
android:text="twg. official"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iv_product_thumbnail" />
<TextView
android:id="@+id/tv_product_label"
style="@style/TextMedium"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="16dp"
android:text="[19차 리오더] 페이크 레더 숏 테일러 자켓 블랙(1 color)"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_product_brand_name" />
<TextView
android:id="@+id/tv_product_discount_rate"
style="@style/TextMedium.Purple.Bold"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:text="10%"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_product_label" />
<TextView
android:id="@+id/tv_product_discount_price"
style="@style/TextMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="10dp"
android:text="99,800원"
app:layout_constraintBottom_toBottomOf="@id/tv_product_discount_rate"
app:layout_constraintStart_toEndOf="@+id/tv_product_discount_rate"
app:layout_constraintTop_toTopOf="@id/tv_product_discount_rate" />
<TextView
android:id="@+id/tv_product_price"
style="@style/TextSubtitle2.Grey05"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text="110,000원"
app:layout_constraintBaseline_toBaselineOf="@id/tv_product_discount_price"
app:layout_constraintStart_toEndOf="@id/tv_product_discount_price" />
<View
android:id="@+id/view_divider_product"
android:layout_width="0dp"
android:layout_height="1dp"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:background="#eeeff1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tv_product_price" />
<TextView
android:id="@+id/tv_product_detail_image_title"
style="@style/TextSubtitle3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="24dp"
android:text="@string/title_product_detail_image"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/view_divider_product" />
<ImageView
android:id="@+id/iv_product_detail_image"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:layout_marginBottom="50dp"
android:contentDescription="@string/description_product_detail_image"
android:scaleType="centerCrop"
android:src="@drawable/img_pdp_top_01"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_product_detail_image_title" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
ImageView
의 scaleType
, constraintDimensionRatio
, contentDescription
정도 알아가면 좋을 것 같다.
scaleType
- 속성 값에 따라, ImageView
에 나타나는 이미지의 비율이 달라진다. ( 참고 : https://sharp57dev.tistory.com/23 )contentDimensionsRatio
- width or height 를 기준으로, 둘의 비율을 정하는 속성.contentDescription
- 내용 설명을 하는 속성.그리고 여기서 중요한 것은 Material Design
에서 추구하는 AppBar
가 스크롤 되었을 때, Scrolling Behavior
의 가이드라인에 맞추는 방법이다.
<androidx.coordinatorlayout.widget.CoordinatorLayout
...
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/topAppBar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:title="@string/page_title"
app:menu="@menu/top_app_bar"
app:navigationIcon="@drawable/ic_menu_24dp"
style="@style/Widget.MaterialComponents.Toolbar.Primary"
/>
</com.google.android.material.appbar.AppBarLayout>
<!-- Note: A RecyclerView can also be used -->
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<!-- Scrollable content -->
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
AppBar
의 Scrolling Behavior
를 구현하기 위해서는 모두를 CoordinatorLayout
으로 감싸고, Toolbar
를 AppBarLayout
으로 감싸는 형태가 되어야 하며, NestedScrollView
를 사용하여야 한다.
NestedScrollView
에서 app:layout_behavior="@string/appbar_scrolling_view_behavior"
다음과 같이 지정해주어야 한다.
AppBar
의 밑에서부터 ScrollView 를 시작하겠다는 뜻.
참고하면 좋을 사항들
NestedScrollView
의 자식 뷰들을 감싸는 컨테이너인 Layout
이 필요하다.
ToolBar
의 scrollFlags
는 Toolbar
를 감싸는 레이아웃이 얼만큼 보일 지 가릴 지를 정하는 속성이다.
scroll
부분은 -> scroll에 반응하라는 표시이고, scroll | ?
를 변경하면 된다.
exitUntilCollapsed
AppBarLayout
전체가 내려오기 시작.enterAlways
AppBarLayout
전체가 내려오기 시작.enterAlwaysCollapsed
AppBarLayout
전체가 내려오기 시작.Toolbar
의 navigationIcon
은 Toolbar
의 naviagation
의 아이콘을 지정하는 속성이고, 클릭 되었을 때, 액션을 설정하는 방법은 나중에 더 자세히 알아보자.
package com.youngsun.shoppi.app
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_product_detail)
}
}
activity_product_detail.xml
레이아웃 파일을 MainActivity
의 화면으로 지정한다.
<resources>
<string name="app_name">shoppi-android</string>
<string name="description_product_thumbnail">상품 상세 대표 이미지</string>
<string name="title_product_detail_image">상품설명</string>
<string name="description_product_detail_image">상품 상세 이미지</string>
</resources>
자주 바뀔 것 같은 문자열 값들은 values
의 strings
에 지정해두는 것이 좋다.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="shoppi_purple">#7d22ff</color>
<color name="shoppi_pink_01">#66e062ff</color>
<color name="shoppi_pink_02">#11e062ff</color>
<color name="shoppi_gradient_purple">#6b19ff</color>
<color name="shoppi_gradient_pink">#fd62ff</color>
<color name="shoppi_black_01">#000000</color>
<color name="shoppi_black_02">#111111</color>
<color name="shoppi_grey_01">#5f5f69</color>
<color name="shoppi_grey_02">#52514d</color>
<color name="shoppi_grey_03">#555555</color>
<color name="shoppi_grey_04">#888888</color>
<color name="shoppi_grey_05">#939393</color>
<color name="shoppi_grey_06">#d1d1d1</color>
<color name="shoppi_grey_07">#d6d6d6</color>
<color name="shoppi_grey_08">#e9e9e9</color>
<color name="shoppi_grey_09">#eeeff1</color>
<color name="shoppi_bluegrey">#f2f4f6</color>
<color name="shoppi_white">#ffffff</color>
<color name="shoppi_brown">#967a6d</color>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- ImageView Style -->
<style name="Circle">
<item name="cornerSize">50%</item>
</style>
<style name="RoundedBig">
<item name="cornerSize">12dp</item>
</style>
<style name="RoundedMedium">
<item name="cornerSize">8dp</item>
</style>
<!-- Text Style -->
<style name="TextHeadline32" >
<item name="android:textSize">32sp</item>
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextHeadline32.White" >
<item name="android:textColor">@color/shoppi_white</item>
</style>
<style name="TextHeadline32.White.Bold" >
<item name="android:textStyle">bold</item>
</style>
<style name="TextHeadline5.Black02" parent="TextAppearance.MaterialComponents.Headline5">
<item name="android:textColor">@color/shoppi_black_02</item>
</style>
<style name="TextHeadline5.Black02.Bold" >
<item name="android:textStyle">bold</item>
</style>
<style name="TextMedium" parent="TextAppearance.AppCompat.Medium">
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextMedium.Bold">
<item name="android:textStyle">bold</item>
</style>
<style name="TextMedium.Purple">
<item name="android:textColor">@color/shoppi_purple</item>
</style>
<style name="TextMedium.Purple.Bold">
<item name="android:textStyle">bold</item>
</style>
<style name="TextSubtitle1" parent="TextAppearance.MaterialComponents.Subtitle1">
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextSubtitle1.Bold" >
<item name="android:textStyle">bold</item>
</style>
<style name="TextSubtitle1.White">
<item name="android:textColor">@color/shoppi_white</item>
</style>
<style name="TextSubtitle1.White.Bold">
<item name="android:textStyle">bold</item>
<item name="android:textColor">@color/shoppi_white</item>
</style>
<style name="TextSubtitle2" parent="TextAppearance.MaterialComponents.Subtitle2">
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextSubtitle2.Black02" >
<item name="android:textColor">@color/shoppi_black_02</item>
</style>
<style name="TextSubtitle2.Black02.Bold" >
<item name="android:textStyle">bold</item>
</style>
<style name="TextSubtitle2.Purple" >
<item name="android:textColor">@color/shoppi_purple</item>
</style>
<style name="TextSubtitle2.Purple.Bold" >
<item name="android:textStyle">bold</item>
</style>
<style name="TextSubtitle2.Grey05" >
<item name="android:textColor">@color/shoppi_grey_05</item>
</style>
<style name="TextSubtitle3">
<item name="android:textSize">13sp</item>
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextSubtitle3.Bold">
<item name="android:textStyle">bold</item>
</style>
<style name="TextSubtitle3.Grey03">
<item name="android:textColor">@color/shoppi_grey_03</item>
</style>
<style name="TextCaption1" parent="TextAppearance.AppCompat.Caption">
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextCaption1.White" >
<item name="android:textColor">@color/shoppi_white</item>
</style>
<style name="TextCaption1.Grey01" >
<item name="android:textColor">@color/shoppi_grey_01</item>
</style>
<style name="TextCaption1.Grey03" >
<item name="android:textColor">@color/shoppi_grey_03</item>
</style>
<style name="TextCaption1.Grey05" >
<item name="android:textColor">@color/shoppi_grey_05</item>
</style>
<style name="TextCaption2" parent="TextAppearance.AppCompat.Caption">
<item name="android:textSize">11sp</item>
<item name="android:textColor">@color/shoppi_black_01</item>
</style>
<style name="TextCaption2.White" >
<item name="android:textColor">@color/shoppi_white</item>
</style>
<style name="TextCaption2.White.Bold" >
<item name="android:textStyle">bold</item>
</style>
<style name="TextCaption2.Grey04" >
<item name="android:textColor">@color/shoppi_grey_04</item>
</style>
</resources>
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Shoppiandroid" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/shoppi_purple</item>
<item name="colorPrimaryVariant">@color/shoppi_gradient_purple</item>
<item name="colorOnPrimary">@color/shoppi_white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/shoppi_pink_01</item>
<item name="colorSecondaryVariant">@color/shoppi_pink_02</item>
<item name="colorOnSecondary">@color/shoppi_black_01</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
NoActionBar
를 지정하여, 화면 위에 있는 디폴트 ActionBar
를 없애준다.
Material Guidelines - Implementing your theme 을 보면 colors
의 정보를 알 수 있다.
colorPrimary
- AppBar
의 배경 색
colorPrimaryVariant
- statusBar
의 배경 색.
on
이 붙은 color 들은text
또는icon
의 색을 나타낸다.
colorOnPrimary
- AppBar
의 icon
과 text
색.
secondary
는 버튼또는 위젯의 배경 색과 text의 색을 나타낸다.
마찬가지로 on
이 붙었을 경우, 버튼의 text
와 icon
의 색을 나타낸다고 생각하면 된다.
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.Shoppiandroid" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/shoppi_purple</item>
<item name="colorPrimaryVariant">@color/shoppi_gradient_purple</item>
<item name="colorOnPrimary">@color/shoppi_black_01</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/shoppi_pink_01</item>
<item name="colorSecondaryVariant">@color/shoppi_pink_02</item>
<item name="colorOnSecondary">@color/shoppi_black_01</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>
다크모드를 지정할 시, 이 themes.xml
에 지정된 값으로 theme이 적용된다.
NoActionBar
를 지정하여, 화면 위에 있는 디폴트 ActionBar
를 없애준다.