240226 TIL
DoDoBest
·2024. 2. 26. 22:35
오늘 학습한 내용
- Kotlin In Action 4.4 일부
- 동반 객체 companion object는 일반 object 객체와 같은 객체이다. 다만, 클래스 객체 선언 없이 접근할 수 있다.
- 동반 객체에는 이름을 지정할 수 있으나, 보통은 클래스를 통해 바로 접근할 수 있으므로 지정하지 않는다. 기본 이름은 Companion이다.
- 최상위 함수는 클래스의 private 멤버에 접근할 수 없다. 그래서 클래스의 인스턴스와 관계없이 호출해야 하지만, 클래스 내부 정보에 접근해야 하는 함수가 필요할 때, companion object에 선언해서 사용한다. - 코틀린 코루틴 7장 복습 및 나머지 부분 학습
- Android 구현
배달의 민족 배너와 같이 옆으로 넘기는 UI를 RecyclerView를 이용해 구현해봤다.
ViewHolder의 root Layout을 match_parent로 설정하여, 한 개의 ViewHolder가 전체 RecyclerView 영역을 차지하도록 설정했다.
사용자가 슬라이드한 정도에 따라 현재 ViewHolder가 중앙에 보이도록 하거나, 다음 ViewHolder 또는 이전 ViewHolder로 넘어가도록 구현했다. LinearSnapHelper를 이용했으며, 아래 StackOverFlow의 답변을 참고했다.
class SnapHelperOneByOne(
private val bannerLocationListener: BannerLocationListener, // 현재 ViewHolder의 순서를 UI에 표시하기 위한 것으로, 없어도 무방함
): LinearSnapHelper() {
override fun findTargetSnapPosition(
layoutManager: RecyclerView.LayoutManager?,
velocityX: Int,
velocityY: Int
): Int {
if (layoutManager !is RecyclerView.SmoothScroller.ScrollVectorProvider) {
return RecyclerView.NO_POSITION
}
val currentView = findSnapView(layoutManager) ?: return RecyclerView.NO_POSITION
val myLayoutManager = layoutManager as LinearLayoutManager
val firstPosition = myLayoutManager.findFirstVisibleItemPosition()
val lastPosition = myLayoutManager.findLastVisibleItemPosition()
var currentPosition = layoutManager.getPosition(currentView)
if (velocityX > 400) {
currentPosition = lastPosition
} else if (velocityX < 400) {
currentPosition = firstPosition
}
bannerLocationListener.changedTo(currentPosition) // 현재 ViewHolder의 순서를 UI에 표시하기 위한 것으로, 없어도 무방함
return currentPosition
}
}
Fragment 혹은 Activity에서 아래와 같이 사용하면 한 개의 ViewHolder만 보이도록 구현할 수 있다.
SnapHelperOneByOne(this).attachToRecyclerView(binding.recyclerviewBanner)
보통은 ViewPager를 이용해 구현한다고 한다. 튜터 님께서 ViewPager와 RecyclerView 구현에 따른 차이가 적힌 글을 알려주셨다. 아직은 왜 ViewPager를 사용해야 하는지 이해하지 못했다. 기회가 된다면 deep 하게 구현해보고, 관련 글을 남기겠다.
https://medium.com/@zzanzu/무작정-구현부터-시작하지-마세요-b38545532af
https://stackoverflow.com/a/55226941/11722881
https://developer.android.com/reference/androidx/recyclerview/widget/LinearSnapHelper
상단에 보이는 움직이는 글자는 TextView의 marquee 속성을 이용했다. 주의할 점은 maxLines가 아닌 singleLine을 사용해야 한다. maxLines가 deprecated 되어, singleLine을 단독으로 사용하면 deprecated 되었다고 나와 maxLines를 사용한 건데, 필요한 다른 attribute를 함께 설정하니 deprecated warning이 사라졌다.
움직이는 데 필요한 xml에서의 설정은 맨 위 최상단에 있는 5가지 속성이다.
<TextView
android:ellipsize="marquee"
android:focusable="true"
android:focusableInTouchMode="true"
android:marqueeRepeatLimit="marquee_forever"
android:scrollHorizontally="true"
android:singleLine="true"
android:id="@+id/text_view_team"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/content_for_team_intro"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
또한 코드에서 아래와 같이 selected를 true로 설정해줘야 한다.
binding.textViewTeam.isSelected = true
추가로 찾아보니, marquee는 사용자의 touch로 focus를 받았을 때만 움직이는 것 같다. focus가 없을 때도 움직이도록 하려면 CustomView로 직접 구현해야 한다. UI를 구현하다 보면 CustomView가 필요한 상황이 많은데, 이번 기회에 CustomView에 대해 학습한 후, touch 없이도 동작하는 marquee에 대해 구현해보겠다. Custom이 필요한 또 다른 이유로, 글자가 끊기지 않도록 연결하는 속성 값이 없다.(영상을 보면 시작과 끝 사이에 여백이 있는데, 이 공간을 줄이는 속성 값이 없음)
오늘 내일배움캠프 본 수업 1일차를 시작했다. 아직은 시간이 많다. 하지만 여전히 모르는 것은 많으며, 안드로이드 구현 과정에서 그러한 부분이 나왔을 때, 관련 공식 문서나 공신력 있는 블로그 글을 찾는 데 시간이 많이 걸리는 것이 나의 학습 방법의 단점이다. 따라서 여유 있을 때, 부족한 부분들을 채워갈 것이다. 또한 부족한 CS, 코딩테스트를 준비하여 이번 하반기 채용은 반드시 면접까지 경험하고, 합격했으면 한다.
'TIL' 카테고리의 다른 글
240228 TIL (0) | 2024.02.28 |
---|---|
240227 TIL (0) | 2024.02.27 |
240220 TIL (0) | 2024.02.21 |
240219 TIL (0) | 2024.02.19 |
240216 TIL (0) | 2024.02.16 |