gradle 설정
version에 따라서 설정법이 2개로 나뉜다.
android{
...
// AndroidStudio 3.6 ~ 4.0
viewBinding{
enabled = true
}
// AndroidStudio 4.0 ~
buildFeatures{
viewBinding = true
}
}
Activity 설정법
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
데이터를 관리하며 데이터 원본과 어댑터뷰(ListView, GridView) 사이의 중계 역할을 한다.
Adapter가 어댑터를 사용하기 위해서는 먼저 데이터 원본이 Adapter에 설정되어야 하고, AdapterView에는 Adapter가 설정되어야 한다.
Adapter의 getCount()란 메소드를 통해 현재 어뎁터가 관리하는 데이터 항목의 총 개수를 반환한다.
AdapterView는 Adapter의 getView()란 메소드를 통해서 화면에 실제로 표시할 항목뷰를 얻고, 이를 화면에 표시한다.
사용자가 어댑터뷰의 특정 위치의 항목을 선택하였을 때, 어댑터뷰는 선택된 항목, 항목ID, 항목뷰를 어댑터의 getItem(), getItemId(), getView()
메소드를 통해 얻어와서 이를 항목 선택 이벤트 처리기에 넘겨준다.
ListView는 리스트 형태의 데이터를 수직으로 보여주기 위한 위젯이다.
따라서 list 형태의 원본 데이터가 있어야 하며 이를 adapter를 통해 각각의 아이템에 지정해준다. 이 때 어댑터는 데이터를 관리할 뿐만 아니라 뷰도 생성해준다. 이와 같은 형태로 쓰이는 위젯이 많기 때문에 리스트뷰를 통해 기본적인 사용법을 익히는 것이 좋다.
gridView는 핸드폰 갤러리를 생각해보면 된다. 수직이 아닌 격자 형식으로 나타난다. 이미지를 보여주기 적합한 뷰다.
어댑터 뷰의 항목 하나는 단순한 문자열이나 이미지뿐만 아니라,다수의 문자열이나 이미지를 포함하는 임의의 뷰를 말한다. 리사이클러뷰나 리스트뷰 등의 들어가는 아이템 뷰들이다.
<ImageView
android:id="@+id/goods_image"
android:layout_width="100dp"
android:layout_height="100dp"
android:background="@drawable/corners_round"
android:src="@drawable/ic_launcher_background"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0" />
<TextView
android:maxLines="2"
android:ellipsize="end"
android:id="@+id/g_name"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:text="@string/goods_name"
android:textStyle="bold"
android:layout_marginLeft="20dp"
android:textSize="17sp"
android:textColor="@color/black"
app:layout_constraintLeft_toRightOf="@id/goods_image"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:maxLines="2"
android:ellipsize="end"
android:id="@+id/exp"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:text="@string/experience"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"
android:textSize="15sp"
android:textColor="@color/light_gray"
app:layout_constraintLeft_toRightOf="@id/goods_image"
app:layout_constraintTop_toBottomOf="@id/g_name"/>
<TextView
android:id="@+id/g_price"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/price"
android:textSize="14sp"
android:textColor="@color/black"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="@+id/exp"
app:layout_constraintTop_toBottomOf="@+id/exp" />
RecyclerView란 한 화면에 표시할 수 없는 많은 데이터를 스크롤 가능한 리스트로 표시해주는 위젯이다.
RecyclerView 사용하면 대량의 데이터 셋을 효율적으로 표시할 수 있다.
리스트뷰는 아이템을 스크롤을 할 때마다 아이템이 생성하고 삭제 되는 걸 반복하지만 리사이클러뷰는 위에 있던 아이템을 재활용을 하는 것이기에 성능 면에서 훨씬 뛰어나다.
리사이클러뷰도 따로 의존성 추가 해줘야합니다 ~!~!
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/main_page_category_name"
android:textColor="@color/black"
android:textSize="25sp"
android:textStyle="bold|italic"
app:layout_constraintBottom_toTopOf="@+id/recyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.048"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.333" />
<ImageButton
android:id="@+id/imageButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white"
android:src="@drawable/ic_baseline_keyboard_arrow_down_24"
app:layout_constraintBottom_toBottomOf="@+id/textView"
app:layout_constraintStart_toEndOf="@+id/textView"
app:layout_constraintTop_toTopOf="@+id/textView"
app:layout_constraintVertical_bias="0.0" />
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/white"
android:src="@drawable/ic_baseline_notifications_none_24"
app:layout_constraintBottom_toTopOf="@+id/recyclerView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.925"
app:layout_constraintStart_toEndOf="@+id/imageButton"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.333" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="405dp"
android:layout_height="645dp"
android:layout_marginBottom="4dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
class GoodsAdapter(val mGoods: MutableList<GoodsData>) :
RecyclerView.Adapter<GoodsAdapter.Holder>() {
// onCreateViewHolder 메소드는 새로운 ViewHolder 객체를 생성합니다.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
val binding =
RecycleItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
// onBindViewHolder 메소드는 ViewHolder와 데이터를 연결합니다.
override fun onBindViewHolder(holder: Holder, position: Int) {
holder.goodsImage.setImageResource(mGoods[position].gImage)
holder.name.text = mGoods[position].gName
holder.exp.text = mGoods[position].gExp
holder.price.text = mGoods[position].gPrice
}
// getItemCount 메소드는 어댑터가 관리하는 데이터 아이템의 수를 반환합니다.
override fun getItemCount(): Int {
return mGoods.size
}
// getItemId 메소드는 아이템의 고유 식별자를 반환합니다.
override fun getItemId(position: Int): Long {
return position.toLong()
}
// ViewHolder 클래스는 각 아이템의 뷰 요소들을 보유합니다.
inner class Holder(val binding: RecycleItemBinding) : RecyclerView.ViewHolder(binding.root) {
val goodsImage = binding.goodsImage
val name = binding.gName
val exp = binding.exp
val price = binding.gPrice
}
}
MainActivity.kt
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
val dataList = mutableListOf<GoodsData>()
dataList.add(GoodsData(R.drawable.sample1, "산진 한달된 선풍기 팝니다", "이사가서 필요가 없어졌어요 급하게 내놓습니다", "1,000"))
dataList.add(GoodsData(R.drawable.sample2, "김치냉장고", "이사로인해 내놔요", "870,000"))
dataList.add(GoodsData(R.drawable.sample3, "샤넬 카드지갑", "고퀄지갑이구요\\n사용감이 있어서 싸게 내어둡니다", "970,000"))
dataList.add(GoodsData(R.drawable.sample4, "금고", "금고\\n떼서 가져가야함\\n대우월드마크센텀\\n미국이주관계로 싸게 팝니다", "390,000"))
dataList.add(GoodsData(R.drawable.sample5, "갤럭시Z플립3 팝니다", "갤럭시 Z플립3 그린 팝니다\\n항시 케이스 씌워서 썻고 필름 한장챙겨드립니다\\n화면에 살짝 스크래치난거 말고 크게 이상은없습니다!", "210,000"))
dataList.add(GoodsData(R.drawable.sample6, "프라다 복조리백", "까임 오염없고 상태 깨끗합니다\\n정품여부모름", "1,200,000"))
dataList.add(GoodsData(R.drawable.sample7, "울산 동해오션뷰 60평 복층 펜트하우스 1일 숙박권 펜션 힐링 숙소 별장", "울산 동해바다뷰 60평 복층 펜트하우스 1일 숙박권\\n(에어컨이 없기에 낮은 가격으로 변경했으며 8월 초 가장 더운날 다녀가신 분 경우 시원했다고 잘 지내다 가셨습니다)\\n1. 인원: 6명 기준입니다. 1인 10,000원 추가요금\\n2. 장소: 북구 블루마시티, 32-33층\\n3. 취사도구, 침구류, 세면도구, 드라이기 2개, 선풍기 4대 구비\\n4. 예약방법: 예약금 50,000원 하시면 저희는 명함을 드리며 입실 오전 잔금 입금하시면 저희는 동.호수를 알려드리며 고객님은 예약자분 신분증 앞면 주민번호 뒷자리 가리시거나 지우시고 문자로 보내주시면 저희는 카드키를 우편함에 놓아 둡니다.\\n5. 33층 옥상 야외 테라스 있음, 가스버너 있음\\n6. 고기 굽기 가능\\n7. 입실 오후 3시, 오전 11시 퇴실, 정리, 정돈 , 밸브 잠금 부탁드립니다.\\n8. 층간소음 주의 부탁드립니다.\\n9. 방3개, 화장실3개, 비데 3개\\n10. 저희 집안이 쓰는 별장입니다.", "210,000"))
dataList.add(GoodsData(R.drawable.sample8, "샤넬 탑핸들 가방", "샤넬 트랜디 CC 탑핸들 스몰 램스킨 블랙 금장 플랩백 !\\n + \"\\n\" + \"색상 : 블랙\\n\" + \"사이즈 : 25.5cm * 17.5cm * 8cm\\n\" + \"구성 : 본품더스트\\n\" + \"\\n\" + \"급하게 돈이 필요해서 팝니다 ㅠ ㅠ", "3,800,000"))
dataList.add(GoodsData(R.drawable.sample9, "4행정 엔진분무기 판매합니다.", "3년전에 사서 한번 사용하고 그대로 둔 상태입니다. 요즘 사용은 안해봤습니다. 그래서 저렴하게 내 놓습니다. 중고라 반품은 어렵습니다.\\n", "50,000"))
dataList.add(GoodsData(R.drawable.sample10, "셀린느 버킷 가방", "22년 신세계 대전 구매입니당\\n + \"셀린느 버킷백\\n\" + \"구매해서 몇번사용했어요\\n\" + \"까짐 스크래치 없습니다.\\n\" + \"타지역에서 보내는거라 택배로 진행합니당!\"", "1,350,000"))
binding.recyclerView.adapter = GoodsAdapter(dataList)
val adapter = GoodsAdapter(dataList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
}
}
data class GoodsData(val gImage:Int, val gName:String, val gExp: String,val gPrice:String)