1. 최종 프로젝트 2주차
어제는 기본적인 레이아웃을 만들다가 Coordinator Layout이라는 벽에 부딪혀서 가로막혔는데 오늘은 과연 완성시킬 수 있을까?
MountainDetailActivity 레이아웃
어제 Coordinator Layout을 잠깐 배우고 나서 곧바로 적용시켜봤다.
Coordinator Layout의 기본적인 골자는 다음과 같다.
<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">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<!-- 여기에 툴바와 이미지 등을 추가 -->
</com.google.android.material.appbar.CollapsingToolbarLayout>
</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">
<!-- 여기에 스크롤 가능한 콘텐츠를 추가 ex) RecyclerView -->
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
이를 곧바로 적용시켜서 레이아웃을 만들어봤다.
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:background="@color/white"
android:fitsSystemWindows="true"
tools:context=".ui.activity.sandetail.SanDetailActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_width="match_parent"
android:layout_height="300dp">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="top"
android:fitsSystemWindows="true"
android:src="@drawable/img_mountain" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:src="@drawable/ic_back"
android:layout_gravity="left"/>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_mountain"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginBottom="-5dp"
android:background="@drawable/ic_rounded_background"
android:clipToOutline="true"
android:padding="10dp"
app:layout_collapseMode="pin"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView
android:id="@+id/tv_mountain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:fontFamily="@font/pretendardvariable"
android:text="한라산"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_pin"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginStart="15dp"
android:layout_marginTop="5dp"
android:layout_marginEnd="15dp"
android:layout_marginBottom="10dp"
android:src="@drawable/ic_pin"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_mountain" />
<TextView
android:id="@+id/tv_address"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:fontFamily="@font/pretendardvariable"
android:hint="Address"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@id/iv_pin"
app:layout_constraintStart_toEndOf="@id/iv_pin"
app:layout_constraintTop_toTopOf="@id/iv_pin" />
<ImageView
android:id="@+id/iv_weather"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginEnd="20dp"
android:src="@drawable/ic_weather"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@id/iv_bookmark"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_bookmark"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:src="@drawable/ic_bookmark_off"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:id="@+id/sv_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="40dp"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_info"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_info_box"
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">
<TextView
android:id="@+id/tv_difficulty"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:hint="난이도"
app:layout_constraintBottom_toTopOf="@+id/tv_difficulty_info"
app:layout_constraintEnd_toStartOf="@+id/line_1"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
<TextView
android:id="@+id/tv_difficulty_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:text="difficulty"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/tv_difficulty"
app:layout_constraintStart_toStartOf="@id/tv_difficulty"
app:layout_constraintTop_toBottomOf="@+id/tv_difficulty"
app:layout_constraintVertical_bias="0.5" />
<View
android:id="@+id/line_1"
android:layout_width="1dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:layout_margin="10dp"
android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/line_2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_height"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:hint="해발고도"
app:layout_constraintBottom_toTopOf="@+id/tv_height_info"
app:layout_constraintEnd_toStartOf="@+id/line_2"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/line_1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
<TextView
android:id="@+id/tv_height_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:text="height"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/tv_height"
app:layout_constraintStart_toStartOf="@id/tv_height"
app:layout_constraintTop_toBottomOf="@+id/tv_height"
app:layout_constraintVertical_bias="0.5" />
<View
android:id="@+id/line_2"
android:layout_width="1dp"
android:layout_height="50dp"
android:layout_gravity="center"
android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/line_1"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:hint="총 등산 시간"
app:layout_constraintBottom_toTopOf="@+id/tv_time_info"
app:layout_constraintEnd_toStartOf="@id/iv_mini_clock"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@+id/line_2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.5" />
<TextView
android:id="@+id/tv_time_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:text="time"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@id/iv_mini_clock"
app:layout_constraintStart_toStartOf="@id/tv_time"
app:layout_constraintTop_toBottomOf="@+id/tv_time"
app:layout_constraintVertical_bias="0.5" />
<ImageView
android:id="@+id/iv_mini_clock"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:src="@drawable/ic_mini_clock"
app:layout_constraintBottom_toBottomOf="@id/tv_time"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@id/tv_time"
app:layout_constraintTop_toTopOf="@id/tv_time" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_intro"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="100dp"
android:fontFamily="@font/bm_hanna_11yrs_old"
android:text="산 개요"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_intro_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:fontFamily="@font/pretendardvariable"
android:text="Intro"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_intro" />
<TextView
android:id="@+id/tv_recommend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="30dp"
android:fontFamily="@font/bm_hanna_11yrs_old"
android:text="추천 이유"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_intro_info" />
<TextView
android:id="@+id/tv_recommend_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="10dp"
android:fontFamily="@font/pretendardvariable"
android:text="recommend"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_recommend" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="15dp"
android:layout_marginTop="30dp"
android:fontFamily="@font/bm_hanna_11yrs_old"
android:text="이 위치 날씨"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_recommend_info" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
이렇게 1차적으로 레이아웃이 만들어졌는데 문제점들과 아직 구현하지 못 한 레이아웃이 몇 개 있다.
- Coordinator Layout 역시 Constraint Layout이 아니어서 그런지 배치를 자유롭게 할 수가 없다. 이 때문에 이미지 부분을 위로 딱 붙이고 싶은데 그게 마음대로 안 되더라.
- 중간에 있는 흰색 레이이아웃을 배치하기가 까다로웠다. Appbar 안에 집어넣어서 어찌저찌 구현은 했는데 문제는 이렇게 하다보니 아래로 스크롤을 내리면 저 부분도 같이 사라지는 문제가 생겼다. 저것만 따로 위에 표시되게 수정해야 한다.
- '총 등산 시간' 부분에 있는 time을 누르면 상행 시간과 하행 시간을 따로 표시되게 하는 툴팁을 구현하려고 하는데 그걸 Spinner로 구현하는 것이 맞는지 모르겠다. 당장 생각나는 건 Spinner인데 Spinner는 내가 알기로는 메뉴를 선택할 때 사용하는 기능이라서 그냥 보여주기만 하면 되는 곳에도 사용해도 되는지 모르겠다.
MyInfoFragment 레이아웃
그 다음으로는 MyInfoFragment 레이아웃을 만들어봤다.
이건 위의 것보다는 더 간단하다.
우선, 백그라운드 형식에 쓸 xml 파일을 먼저 만들었다.
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#D9FFFFFF"/>
<corners android:radius="15dp"/>
<stroke android:width="2dp" android:color="#B4D6B1"/>
</shape>
그리고 바로 레이아웃 제작 돌입.
<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"
android:background="#F8F7F3"
tools:context=".ui.fragment.mydetail.MyDetailFragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="10dp"
android:fontFamily="@font/bm_hanna_pro"
android:text="@string/mydetail_myinfo"
android:textColor="#345948"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/cl_my_info"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="80dp"
android:layout_marginEnd="20dp"
android:background="@drawable/ic_rounded_background_line"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="@+id/tv_my_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="15dp"
android:fontFamily="@font/pretendardvariable"
android:text="@string/mydetail_summary"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:src="@drawable/ic_clock"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/tv_counttime"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_counttime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="@font/pretendardvariable"
android:text="@string/mydetail_counttime"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="@id/iv_time"
app:layout_constraintEnd_toStartOf="@+id/line_3"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iv_time"
app:layout_constraintTop_toTopOf="@id/iv_time" />
<View
android:id="@+id/line_3"
android:layout_width="1dp"
android:layout_height="70dp"
android:layout_gravity="center"
android:layout_marginTop="50dp"
android:layout_marginBottom="30dp"
android:background="#B4D6B1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageView
android:id="@+id/iv_tracking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_human"
app:layout_constraintBottom_toBottomOf="@id/tv_counttracking"
app:layout_constraintEnd_toStartOf="@+id/tv_counttracking"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/line_3"
app:layout_constraintTop_toTopOf="@id/tv_counttracking" />
<TextView
android:id="@+id/tv_counttracking"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:fontFamily="@font/pretendardvariable"
android:text="@string/mydetail_counttracking"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/iv_tracking"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/tv_recode"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="20dp"
android:layout_marginTop="50dp"
android:fontFamily="@font/bm_hanna_pro"
android:text="@string/mydetail_recode"
android:textColor="#345948"
android:textSize="30sp"
android:textStyle="bold"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/cl_my_info" />
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="@drawable/ic_rounded_background_line"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_recode"
tools:listitem="@layout/item_adapter_bookmark" />
</androidx.constraintlayout.widget.ConstraintLayout>
item_bookmark.xml
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/iv_mountain"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/ic_mountain"
android:layout_marginTop="20dp"
android:layout_marginStart="20dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv_mountain"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/item_bookmark_name"
android:textSize="18sp"
android:textStyle="bold"
android:fontFamily="@font/pretendardvariable"
android:layout_marginStart="20dp"
app:layout_constraintTop_toTopOf="@id/iv_mountain"
app:layout_constraintStart_toEndOf="@id/iv_mountain"/>
<TextView
android:id="@+id/tv_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/item_bookmark_time"
android:textSize="17sp"
android:fontFamily="@font/pretendardvariable"
android:layout_marginStart="20dp"
app:layout_constraintStart_toEndOf="@id/iv_mountain"
app:layout_constraintBottom_toBottomOf="@id/iv_mountain"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:hint="@string/item_bookmark_date"
android:textStyle="bold"
android:fontFamily="@font/pretendardvariable"
android:layout_marginTop="20dp"
android:layout_marginEnd="20dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
음. 알차다 알차.
이제 대략적인 레이아웃 제작은 끝마쳤다.
이 다음에 해야 할 목록을 나열하자면(물론 추가구현 말고 필수구현만)
- MountainDetailActivity
- 레이아웃 다듬기 (상단 여백부분 지우기 & 중단 부분 스크롤 내려가도 남기기)
- 이미지 부분 자동 스크롤 구현하기(RecyclerView로 변환해야 함)
- 중단 부분 북마크 활성화
- 하단 부분 '총 등산 시간'을 누르면 상행 시간, 하행 시간을 볼 수 있는 툴팁 만들기
- 산 개요, 추천 이유 각 산마다 어떻게 받아올 건지 고민하기 (API로는 안 될 가능성이 높음)
- 날씨 API 받아와서 적용시키기
- MyInfoFragment
- 총 등산 정보를 어떻게 받아올 건지 생각하기
- RecyclerView에 초록색 구분선 만들기
- '기록' 부분에 북마크한 산만 RecyclerView를 통해서 띄우기
과연 내일은 이 중에서 어디까지 완성시킬 수 있을까?
'[TIL][내일배움캠프]' 카테고리의 다른 글
[내일배움캠프][TIL] 24.02.29 (목) - 최종 프로젝트 2주차 : 개발 4일차 (2) | 2024.02.29 |
---|---|
[내일배움캠프][TIL] 24.02.28 (수) - 최종 프로젝트 2주차 : 개발 3일차 (1) | 2024.02.28 |
[내일배움캠프][TIL] 24.02.26 (월) - 최종 프로젝트 2주차 : 개발 1일차 (1) | 2024.02.26 |
[내일배움캠프][TIL] 24.02.23 (금) - 최종 프로젝트 1주차 (0) | 2024.02.23 |
[내일배움캠프][TIL] 24.02.22 (목) - 최종 프로젝트 1주차 (0) | 2024.02.22 |