사과마켓 앱 제작하기 - 2
* MainActivity
package com.android.applemarket
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.DialogInterface
import android.content.Intent
import android.media.AudioAttributes
import android.media.RingtoneManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.LinearLayout
import androidx.activity.OnBackPressedCallback
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.NotificationCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.android.applemarket.databinding.ActivityMainBinding
import com.google.android.engage.food.datamodel.ProductEntity
import java.text.DecimalFormat
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
val decimal = DecimalFormat("#,###원")
val dataList = mutableListOf<MyItem>()
dataList.add(
MyItem(
R.drawable.sample1,
"산지 한달된 선풍기 팝니다",
"서울 서대문구 창천동",
decimal.format(1000),
25,
13,
"대현동",
"이사가서 필요가 없어졌어요 급하게 내놓습니다"
)
)
dataList.add(
MyItem(
R.drawable.sample2,
"김치냉장고",
"인천 계양구 귤현동",
decimal.format(25000),
28,
8,
"안마담",
"이사로인해 내놔요"
)
)
dataList.add(
MyItem(
R.drawable.sample3,
"샤넬 카드지갑",
"수성구 범어동",
decimal.format(10000),
5,
23,
"코코유",
"고퀄지갑이구요\n사용감이 있어서 싸게 내어둡니다"
)
)
dataList.add(
MyItem(
R.drawable.sample4,
"금고",
"해운대구 우제2동",
decimal.format(10000),
17,
14,
"Nicole",
"금고\n떼서 가져가야함\n대우월드마크센텀\n미국이주관계로 싸게 팝니다"
)
)
dataList.add(
MyItem(
R.drawable.sample5,
"갤럭시Z플립3 팝니다",
"연제구 연산제8동",
decimal.format(150000),
9,
22,
"절명",
"갤럭시 Z플립3 그린 팝니다\n항시 케이스 씌워서 썻고 필름 한장챙겨드립니다\n화면에 살짝 스크래치난거 말고 크게 이상은없습니다!"
)
)
dataList.add(
MyItem(
R.drawable.sample6,
"프라다 복조리백",
"수원시 영통구 원천동",
decimal.format(50000),
16,
25,
"미니멀하게",
"까임 오염없고 상태 깨끗합니다\n정품여부모름"
)
)
dataList.add(
MyItem(
R.drawable.sample7,
"울산 동해오션뷰 60평 복층 펜트하우스 1일 숙박권 펜션 힐링 숙소 별장",
"남구 옥동",
decimal.format(150000),
54,
142,
"굿리치",
"울산 동해바다뷰 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. 저희 집안이 쓰는 별장입니다."
)
)
dataList.add(
MyItem(
R.drawable.sample8,
"샤넬 탑핸들 가방",
"동래구 온천제2동",
decimal.format(180000),
7,
31,
"난쉽",
"샤넬 트랜디 CC 탑핸들 스몰 램스킨 블랙 금장 플랩백 !\n" + "\n" + "색상 : 블랙\n" + "사이즈 : 25.5cm * 17.5cm * 8cm\n" + "구성 : 본품더스트\n" + "\n" + "급하게 돈이 필요해서 팝니다 ㅠ ㅠ"
)
)
dataList.add(
MyItem(
R.drawable.sample9,
"4행정 엔진분무기 판매합니다.",
"원주시 명륜2동",
decimal.format(30000),
28,
7,
"알뜰한",
"3년전에 사서 한번 사용하고 그대로 둔 상태입니다. 요즘 사용은 안해봤습니다. 그래서 저렴하게 내 놓습니다. 중고라 반품은 어렵습니다.\n"
)
)
dataList.add(
MyItem(
R.drawable.sample10,
"셀린느 버킷 가방",
"중구 동화동",
decimal.format(190000),
6,
40,
"똑태현",
"22년 신세계 대전 구매입니당\n" + "셀린느 버킷백\n" + "구매해서 몇번사용했어요\n" + "까짐 스크래치 없습니다.\n" + "타지역에서 보내는거라 택배로 진행합니당!"
)
)
val adapter = MyAdapter(dataList)
binding.recyclerView.adapter = adapter
binding.recyclerView.layoutManager = LinearLayoutManager(this)
binding.ivBell.setOnClickListener {
notification()
}
this.onBackPressedDispatcher.addCallback(this, callback)
binding.recyclerView.apply {
setHasFixedSize(true)
addItemDecoration(DividerItemDecoration(context, LinearLayout.VERTICAL))
}
}
fun notification() {
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val builder: NotificationCompat.Builder
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// 26 버전 이상
val channelId = "one-channel"
val channelName = "My Channel One"
val channel = NotificationChannel(
channelId, channelName, NotificationManager.IMPORTANCE_HIGH
)
manager.createNotificationChannel(channel)
builder = NotificationCompat.Builder(this, channelId)
} else {
builder = NotificationCompat.Builder(this)
}
builder.run {
setSmallIcon(R.mipmap.ic_launcher)
setWhen(System.currentTimeMillis())
setContentTitle("키워드 알림")
setContentText("설정한 키워드")
setStyle(
NotificationCompat.BigTextStyle().bigText("설정한 키워드에 대한 알림이 도착했습니다!!\n알림 대체")
)
}
manager.notify(11, builder.build())
}
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
var builder = AlertDialog.Builder(this@MainActivity)
builder.setTitle("종료")
builder.setMessage("정말 종료하시겠습니까?")
builder.setIcon(R.drawable.chat)
// 버튼 클릭시에 무슨 작업을 할 것인가!
val listener = object : DialogInterface.OnClickListener {
override fun onClick(p0: DialogInterface?, p1: Int) {
when (p1) {
DialogInterface.BUTTON_POSITIVE -> finish()
DialogInterface.BUTTON_NEGATIVE -> handleOnBackCancelled()
}
}
}
builder.setPositiveButton("확인", listener)
builder.setNegativeButton("취소", listener)
builder.show()
}
}
}
* Main xml
<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/tv_my"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="내배캠동"
android:textSize="20dp"
android:textStyle="bold"
android:layout_marginStart="16dp"
android:layout_marginTop="18dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<ImageView
android:id="@+id/iv_down"
android:layout_width="14dp"
android:layout_height="18dp"
android:src="@drawable/down"
android:layout_marginStart="6dp"
app:layout_constraintTop_toTopOf="@+id/tv_my"
app:layout_constraintStart_toEndOf="@id/tv_my"
app:layout_constraintBottom_toBottomOf="@id/tv_my"/>
<ImageView
android:id="@+id/iv_bell"
android:layout_width="36dp"
android:layout_height="36dp"
android:src="@drawable/bell"
android:clickable="true"
android:layout_marginEnd="20dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="@+id/iv_down"
app:layout_constraintBottom_toBottomOf="@id/iv_down"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constrainedHeight="true"
android:layout_marginTop="12dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_my"/>
</androidx.constraintlayout.widget.ConstraintLayout>
* Adapter
package com.android.applemarket
import android.content.Intent
import android.os.Build.VERSION_CODES.M
import android.os.Build.VERSION_CODES.P
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.android.applemarket.databinding.ItemRecyclerviewBinding
class MyAdapter(val Items:MutableList<MyItem>) : RecyclerView.Adapter<MyAdapter.Holder>(){
interface ItemClick {
fun onClick(view : View, position : Int)
}
var itemClick : ItemClick? = null
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyAdapter.Holder {
val binding = ItemRecyclerviewBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return Holder(binding)
}
override fun onBindViewHolder(holder: MyAdapter.Holder, position: Int) {
holder.bind(Items[position])
}
override fun getItemCount(): Int {
return Items.size
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
inner class Holder(val binding: ItemRecyclerviewBinding) : RecyclerView.ViewHolder(binding.root){
private val context = binding.root.context
fun bind(item:MyItem) {
binding.ivImage.setImageResource(item.image)
binding.tvName.text = item.name
binding.tvLocation.text = item.location
binding.tvMoney.text = item.money
binding.tvChatCount.text = item.chat.toString()
binding.tvHeartCount.text = item.heart.toString()
itemView.setOnClickListener {
val intent = Intent(context, ProductActivity::class.java)
intent.putExtra("item",item)
intent.run { context.startActivity(this) }
}
}
}
}
* Data Class
package com.android.applemarket
import android.os.Parcelable
import kotlinx.parcelize.Parcelize
@Parcelize
data class MyItem(
val image:Int,val name:String, val location:String, val money:String,
val chat:Int, val heart:Int, val seller:String, val detail:String ):Parcelable
* Second Activity(Detail Page)
package com.android.applemarket
import android.content.ClipData.Item
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Paint
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import com.android.applemarket.databinding.ActivityProductBinding
class ProductActivity : AppCompatActivity() {
private lateinit var binding : ActivityProductBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
binding = ActivityProductBinding.inflate(layoutInflater)
setContentView(binding.root)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}
binding.tvManner.paintFlags = Paint.UNDERLINE_TEXT_FLAG
binding.ivBack.setOnClickListener {
finish()
}
var test = intent.getParcelableExtra<MyItem>("item")
test?.let { binding.ivImage.setImageResource(it.image) }
binding.tvSeller.text = test?.seller
binding.tvLocation.text = test?.location
binding.tvName.text = test?.name
binding.tvDetail.text = test?.detail
binding.tvMoney2.text = test?.money
}
}
* Second xml
<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ProductActivity">
<ImageView
android:id="@+id/iv_back"
android:layout_width="30dp"
android:layout_height="30dp"
android:translationZ="10dp"
android:src="@drawable/backping"
android:clickable="true"
android:layout_marginTop="20dp"
android:layout_marginStart="20dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="@id/ct_layout2">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ct_layout1"
android:layout_width="match_parent"
android:layout_height="660dp">
<ImageView
android:id="@+id/iv_image"
android:scaleType = "fitXY"
android:layout_width="416dp"
android:layout_height="320dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
<ImageView
android:id="@+id/iv_user"
android:layout_width="50dp"
android:layout_height="50dp"
android:src="@drawable/user"
android:layout_margin="12dp"
app:layout_constraintTop_toBottomOf="@id/iv_image"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/tv_seller"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="임시"
android:textSize="18dp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginStart="12dp"
app:layout_constraintTop_toTopOf="@id/iv_user"
app:layout_constraintStart_toEndOf="@id/iv_user"/>
<TextView
android:id="@+id/tv_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="주소 임시 텍스트"
android:textStyle="bold"
android:textColor="@color/black"
app:layout_constraintTop_toBottomOf="@id/tv_seller"
app:layout_constraintStart_toStartOf="@id/tv_seller"/>
<ImageView
android:id="@+id/iv_laugh"
android:layout_width="33dp"
android:layout_height="33dp"
android:src="@drawable/laugh"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
app:layout_constraintTop_toBottomOf="@id/iv_image"
app:layout_constraintEnd_toEndOf="parent"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="39.3°C"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="#009688"
android:layout_marginEnd="12dp"
app:layout_constraintTop_toTopOf="@id/iv_laugh"
app:layout_constraintBottom_toBottomOf="@id/iv_laugh"
app:layout_constraintEnd_toStartOf="@id/iv_laugh"/>
<TextView
android:id="@+id/tv_manner"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="매너온도"
android:textColor="#858383"
android:layout_marginTop="4dp"
android:layout_marginEnd="16dp"
app:layout_constraintTop_toBottomOf="@id/iv_laugh"
app:layout_constraintEnd_toEndOf="parent" />
<com.google.android.material.divider.MaterialDivider
android:id="@+id/dv_line"
app:dividerColor="#DAD9D9"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="20dp"
app:layout_constraintTop_toBottomOf="@id/iv_user"/>
<TextView
android:id="@+id/tv_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="제품명 임시 텍스트"
android:textStyle="bold"
android:textSize="25dp"
android:textColor="@color/black"
android:breakStrategy="simple"
android:padding="8dp"
android:layout_marginTop="8dp"
android:layout_marginStart="6dp"
app:layout_constraintTop_toBottomOf="@id/dv_line"
app:layout_constraintStart_toStartOf="parent"/>
<TextView
android:id="@+id/tv_detail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="상품을 설명하는 내용 임시 텍스트입니다. \n 길이 체크 및 글씨 크기 체크"
android:textSize="18dp"
android:textColor="@color/black"
android:breakStrategy="simple"
android:padding="8dp"
app:layout_constraintTop_toBottomOf="@id/tv_name"
app:layout_constraintStart_toStartOf="@id/tv_name"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/ct_layout2"
android:layout_width="match_parent"
android:layout_height="80dp"
app:layout_constraintBottom_toBottomOf="parent">
<ImageView
android:id="@+id/iv_heart2"
android:layout_width="35dp"
android:layout_height="35dp"
android:src="@drawable/heart"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<com.google.android.material.divider.MaterialDivider
android:id="@+id/dv_line2"
app:dividerColor="#DAD9D9"
android:layout_width="2dp"
android:layout_height="match_parent"
android:layout_marginStart="12dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintStart_toEndOf="@id/iv_heart2"/>
<TextView
android:id="@+id/tv_money2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="금액 임시 텍스트"
android:textSize="20dp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_marginStart="16dp"
app:layout_constraintStart_toEndOf="@id/dv_line2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<Button
android:layout_width="100dp"
android:layout_height="40dp"
android:background="@drawable/btn_background"
android:text="채팅하기"
android:textSize="16dp"
android:textColor="@color/white"
android:textStyle="bold"
android:layout_marginEnd="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
* RecyclerView에 사용할 xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="180dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.cardview.widget.CardView
android:id="@+id/cv_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
android:layout_marginStart="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
<ImageView
android:id="@+id/iv_image"
android:layout_width="130dp"
android:layout_height="130dp"
android:src="@drawable/sample1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</androidx.cardview.widget.CardView>
<TextView
android:id="@+id/tv_name"
android:layout_width="240dp"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:text="산지 한달된 선풍기 팝니다"
android:textSize="18dp"
android:textStyle="bold"
android:maxLines="2"
android:ellipsize="end"
android:layout_marginStart="14dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toTopOf="@+id/cv_image"
app:layout_constraintStart_toEndOf="@id/cv_image"/>
<TextView
android:id="@+id/tv_location"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="서울 서대문구 창천동"
android:textSize="14dp"
android:textColor="@color/black"
android:layout_marginStart="14dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toBottomOf="@+id/tv_name"
app:layout_constraintStart_toEndOf="@id/cv_image"/>
<TextView
android:id="@+id/tv_money"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1000"
android:textSize="20dp"
android:textColor="@color/black"
android:textStyle="bold"
android:inputType="number"
android:layout_marginStart="14dp"
android:layout_marginTop="4dp"
app:layout_constraintTop_toBottomOf="@+id/tv_location"
app:layout_constraintStart_toEndOf="@id/cv_image"/>
<ImageView
android:id="@+id/iv_chat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/chat"
android:layout_marginEnd="70dp"
android:layout_marginBottom="18dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
<TextView
android:id="@+id/tv_chat_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="25"
android:textColor="@color/black"
android:inputType="number"
app:layout_constraintTop_toTopOf="@+id/iv_chat"
app:layout_constraintStart_toEndOf="@+id/iv_chat"
app:layout_constraintBottom_toBottomOf="@+id/iv_chat"/>
<ImageView
android:id="@+id/iv_heart"
android:layout_width="22dp"
android:layout_height="wrap_content"
android:src="@drawable/heart"
android:layout_marginStart="6dp"
app:layout_constraintTop_toTopOf="@+id/tv_chat_count"
app:layout_constraintStart_toEndOf="@+id/tv_chat_count"
app:layout_constraintBottom_toBottomOf="@+id/tv_chat_count"/>
<TextView
android:id="@+id/tv_heart_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="13"
android:textColor="@color/black"
android:inputType="number"
app:layout_constraintTop_toTopOf="@+id/iv_heart"
app:layout_constraintStart_toEndOf="@+id/iv_heart"
app:layout_constraintBottom_toBottomOf="@+id/iv_heart"/>
</androidx.constraintlayout.widget.ConstraintLayout>
* 출력 화면
'Android 앱개발 공부 > TIL(Today I Learned)' 카테고리의 다른 글
[Android] TIL 41일차 (1) | 2024.07.23 |
---|---|
[Android] TIL 40일차 (3) | 2024.07.22 |
[Android] TIL 37일차 (0) | 2024.07.16 |
[Android] TIL 36일차 (0) | 2024.07.15 |
[Android] TIL 35일차 (0) | 2024.07.12 |