[Android] Sunflower 클론코딩 (22.06.08)

유재민·2022년 6월 8일
0

Sunflower

목록 보기
7/12
post-thumbnail

PlantListFragment에 있는 RecyclerView를 만들자.
그 전에 RecyclerView list item인 CardView를 커스텀하자.

Custom CardView

// views/MaskedCardView

import android.graphics.Path
import com.google.android.material.R

class MaskedCardView @JvmOverloads constructor(
	context: Context,
    attrs, AttributeSet? = null,
    defStyle: Int, R.attr.materialCardViewStyle
) : MaterialCardView(context, attrs, defStyle) {
	...
}

MaterialCardView를 부모뷰로 MaskedCardView 클래스를 생성한다.
View를 상속받은 클래스를 생성할 때에는 3개의 생성자가 필요하며, constructor를 필요로 한다.

View(context: Context)
View(context: Context, attrs: AttributeSet)
View(context: Context, attrs: AttributeSet, defStyleRes: Int)

3개의 생성자가 모두 필요하지만, 생성자 오버로딩을 자동으로 해주는 @JvmOverloads 어노테이션을 사용하게 되면 코드가 한층 간결해진다.

@JvmOverloads 장점

  • 여러 개의 constructor을 상속받는 번거로움 감소
  • 모든 constructor을 생성하지 않으면 생기는 xml inflation 문제 해결 -> 코드가 간결해짐

Android Lint

  • Android 애플리케이션을 구성하는 코드(코드, 리소스, 매니페스트 등)를 정적 분석하는 도구
  • 작성한 코드 내에서 발생할 수 있는 잠재적인 문제 및 성능에 지장을 줄 수 있는 문제를 미리 검출하여 코드 품질을 높인다.
@SuppressLint("RestrictedApi")

린트 검사 사용 중지 코드
(RestrictedApi 린트 검사 중지)
해당 프로젝트에 설정된 minSdkVersion 이후에 나온 API를 사용할 때 생기는 warning을 제거하고 API를 사용할 수 있게 함

override fun onDraw(canvas: Canvas) {
	canvas.clipPath(path)
	super.onDraw(canvas)
}

클립영역을 지정하여 canvas에 그린다.

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
	...
	super.onSizeChanged(w, h, oldw, oldh)
}

CardView 사이즈 조절


List item Layout

RecyclerView에 item으로 들어갈 layout을 생성한다.

<data>
    <variable
        name="clickListener"
        type="android.view.View.OnClickListener" />
    <variable
        name="plant"
        type="com.jaemin.sunflower_clone.data.Plant" />
</data>

dataBinding에 필요한 data 변수를 선언한다.

<com.jaemin.sunflower_clone.views.MaskedCardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/card_side_margin"
    android:layout_marginEnd="@dimen/card_side_margin"
    android:layout_marginBottom="@dimen/card_bottom_margin"
    android:onClick="@{clickListener}"
    app:cardElevation="@dimen/card_elevation"
    app:cardPreventCornerOverlap="false"
    app:shapeAppearanceOverlay="@style/ShapeAppearance.Sunflower.Card">
  
  	...
  
</com.jaemin.sunflower_clone.views.MaskedCardView>

아까 생성한 CustomCardView를 배치해준다.
app:cardElevation : 그림자 효과
app:cardPreventCornerOverlap : 내용과 모서리가 겹칠 때 사용하는 속성
app:shapeAppearanceOverlay : CardView 스타일 정의

<style name="ShapeAppearance.Sunflower.Card" parent="ShapeAppearance.MaterialComponents">
    <item name="cornerFamily">rounded</item>

    <item name="cornerSizeTopLeft">0dp</item>
    <item name="cornerSizeTopRight">@dimen/card_corner_radius</item>
    <item name="cornerSizeBottomRight">0dp</item>
    <item name="cornerSizeBottomLeft">@dimen/card_corner_radius</item>
</style>
<ConstraintLayout>
  <ImageView/>
  <TextView/>
<ConstraintLayout/>

ConstraintLayout으로 이미지뷰와 텍스트 배치

app:imageFromUrl="@{plant.imageUrl}"
...
android:text="@{plant.name}"

dataBinding으로 데이터 속성과 뷰 연결

tools:text="Tomato" : 데이터바인딩으로 텍스트가 연결되어 있을 때 레이아웃 상으로는 보이지 않기 때문에, 임의의 텍스트를 레이아웃상으로 보여지게 하기 위한 속성

Binding Adapter

app:imageFromUrl 속성은 데이터바인딩의 Binding Adapter로 이루어진 속성이다.

이미지 Url을 가지고 있는 데이터 객체의 해당 url 속성과 view 를 연결시키면 이미지뷰가 나타난다.

먼저 url을 이용해서 이미지를 로드할 수 있는 Glide 라이브러리를 사용하기 위한 dependency를 추가해보자.

implementation "com.github.bumptech.glide:glide:$rootProject.glideVersion"
kapt "com.github.bumptech.glide:compiler:$rootProject.glideVersion"

그 다음 BindingAdapter를 생성해준다.

@BindingAdapter("imageFromUrl")
fun bindImageFromUrl(view: ImageView, imageUrl: String?){
    if (!imageUrl.isNullOrEmpty()) {
        Glide.with(view.context)
            .load(imageUrl)
            .transition(DrawableTransitionOptions.withCrossFade())
            .into(view)
    }
}
profile
유잼코딩

0개의 댓글