Personal Project - appleMarket

박재원·2024년 1월 11일
0

TIL

목록 보기
27/50
post-thumbnail
post-custom-banner

Post.kt

package com.example.applemarket

import android.os.Parcelable
import kotlinx.parcelize.Parcelize


@Parcelize
data class Post(
    val itemImage: Int,
    val itemTitle: String,
    val itemInfo: String,
    val itemnickname: String,
    val itemPrice: Int,
    val itemAddress: String,
    var itemheartCount: Int,
    val itemcomment: Int,
    val usermanners: String,
    val mannersImage: Int,
    var isLiked: Boolean = false,
) : Parcelable

Adapter

package com.example.applemarket

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.View.OnClickListener
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.example.applemarket.databinding.RecyclerviewItemBinding
import java.text.DecimalFormat

class Adapter(private val items: MutableList<Post>) : RecyclerView.Adapter<Adapter.Holder>() {
    var itemClick: ItemClick? = null
    var longitemClick: LongItemClick? = null

    interface ItemClick {
        fun onClick(view: View, position: Int)
    }

    interface LongItemClick {
        fun onLongClick(view: View, position: Int)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Adapter.Holder {
        val binding =
            RecyclerviewItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }

    @SuppressLint("SetTextI18n")
    override fun onBindViewHolder(holder: Adapter.Holder, position: Int) {
        val item = items[position]
        //1000단위 마다 콤마(,) 출력
        val money = item.itemPrice
        val format = DecimalFormat("#,###")

        with(holder) {
            imageView.setImageResource(item.itemImage)
            titleText.text = item.itemTitle
            address.text = item.itemAddress
            price.text = "${format.format(money)}원"
            comment.text = item.itemcomment.toString()
            heart.text = item.itemheartCount.toString()
            itemView.setOnClickListener {
                if (itemClick != null) {
                    itemClick!!.onClick(it, position)
                }
            }
        }
    }

    override fun getItemCount(): Int {
        return items.size
    }

    inner class Holder(val binding: RecyclerviewItemBinding) :
        RecyclerView.ViewHolder(binding.root) {
        val imageView = binding.ivListImage
        val titleText = binding.tvTitle
        val address = binding.tvAddress
        val price = binding.tvPrice
        val comment = binding.tvComment
        val heart = binding.tvHeart

        init {
            imageView.clipToOutline = true
            with(binding) {
                root.setOnClickListener {
                    val position = adapterPosition
                    if (position != RecyclerView.NO_POSITION) {
                        itemClick?.onClick(it, position)
                    }
                }
                root.setOnLongClickListener {
                    val position = adapterPosition
                    if (position != RecyclerView.NO_POSITION) {
                        longitemClick?.onLongClick(it, position)
                        true
                    } else false
                }
            }
        }
    }
}

MainActivity

package com.example.applemarket

import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.animation.AlphaAnimation
import android.widget.ArrayAdapter
import android.widget.LinearLayout.VERTICAL
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContract
import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.core.app.NotificationCompat
import androidx.core.os.bundleOf
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.example.applemarket.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {
    private lateinit var binding: ActivityMainBinding
    lateinit var activityResultLauncher: ActivityResultLauncher<Intent>
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        val productList = Product.productData()

        val adapter = Adapter(productList)
        binding.recyclerview.adapter = adapter
        binding.recyclerview.layoutManager = LinearLayoutManager(this)

        //상품 사이에 회색 줄 추가
        val decoration = DividerItemDecoration(this, VERTICAL)
        binding.recyclerview.addItemDecoration(decoration)

        //알림 버튼
        binding.notiButton.setOnClickListener {
            notification()
        }

        adapter.itemClick = object : Adapter.ItemClick {
            override fun onClick(view: View, position: Int) {
                val clickProduct = productList[position]
                val intent = Intent(this@MainActivity, DetailActivity::class.java)
                intent.putExtra("Item", clickProduct)
                intent.putExtra("likePosition", position)
                activityResultLauncher.launch(intent)
            }
        }
        // 롱클릭 아이템 삭제
        adapter.longitemClick = object : Adapter.LongItemClick {
            @SuppressLint("NotifyDataSetChanged")
            override fun onLongClick(view: View, position: Int) {
                val deleteItem = productList[position]
                AlertDialog.Builder(this@MainActivity).apply {
                    setIcon(R.drawable.chat)
                    setTitle("삭제")
                    setMessage("정말로 삭제하시겠습니까?")
                    setPositiveButton("확인") { _, _ ->
                        productList.remove(deleteItem)
                        //notifyDataSetChanged = 아이템 데이터 업데이트
                        adapter.notifyDataSetChanged()
                    }
                    setNegativeButton("취소") { dialog, _ ->
                        dialog.dismiss()
                    }
                    show()
                }
            }
        }

        // Spinner
        val adList = resources.getStringArray(R.array.location)
        val adAdapter =
            ArrayAdapter<String>(this, android.R.layout.simple_spinner_dropdown_item, adList)
        binding.spinner.adapter = adAdapter

        //맨위로 가기 버튼
        //addOnScrollListener = 현재 스크롤 상태 체크
        var isTop = true
        binding.recyclerview.addOnScrollListener(object : RecyclerView.OnScrollListener() {
            override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
                super.onScrollStateChanged(recyclerView, newState)
                //canScrollVertically = 스크롤이 최상단 , SCROLL_STATE_IDLE = 현재 스크롤 하지 않은 상태
                if (!binding.recyclerview.canScrollVertically(-1) && newState == RecyclerView.SCROLL_STATE_IDLE) {
                    binding.fabTop.visibility = View.INVISIBLE
                    binding.fabTop.startAnimation(AlphaAnimation(1f, 0f).also {
                        it.duration = 1000
                    })
                } else if (isTop) {
                    binding.fabTop.visibility = View.VISIBLE
                    binding.fabTop.startAnimation(AlphaAnimation(0f, 1f).also {
                        it.duration = 1000
                    })
                    isTop = false
                }
            }
        })
        binding.fabTop.setOnClickListener {
            //smoothScrollToPosition = 부드럽게 스크롤 상단으로 옮김
            binding.recyclerview.smoothScrollToPosition(0)
        }

        activityResultLauncher =
            registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
                if (it.resultCode == RESULT_OK) {
                    val likePosition = it.data?.getIntExtra("likePosition", 0) as Int
                    val isLiked = it.data?.getBooleanExtra("isLiked", false) as Boolean
                    if (isLiked) {
                        productList[likePosition].isLiked = true
                        productList[likePosition].itemheartCount++
                    } else {
                        if (productList[likePosition].isLiked) {
                            productList[likePosition].isLiked = false
                            productList[likePosition].itemheartCount--
                        }
                    }
                    adapter.notifyItemChanged(likePosition)
                }
            }
    }

    //알림
    private fun notification() {
        val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
        val builder: NotificationCompat.Builder =
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                val channelId = "one-channel"
                val channelName = "My Channel"
                val channel = NotificationChannel(
                    channelId,
                    channelName,
                    NotificationManager.IMPORTANCE_DEFAULT
                )
                manager.createNotificationChannel(channel)
                NotificationCompat.Builder(this, channelId)
            } else {
                NotificationCompat.Builder(this)
            }
        builder.run {
            setSmallIcon(R.drawable.ic_launcher_background)
            setContentTitle("키워드 알림")
            setContentText("설정한 키워드에 대한 알림이 도착했습니다!!")
        }
        manager.notify(11, builder.build())
    }

    @SuppressLint("MissingSuperCall")
    override fun onBackPressed() {
        AlertDialog.Builder(this).apply {
            setIcon(R.drawable.chat)
            setTitle("종료")
            setMessage("정말로 종료하시겠습니까?")
            setPositiveButton("확인") { _, _ ->
                finish()
            }
            setNegativeButton("취소") { dialog, _ ->
                dialog.dismiss()
            }
            show()
        }
    }
}

DetailActivity

package com.example.applemarket

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.os.Build
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.applemarket.databinding.ActivityDetailBinding
import com.example.applemarket.databinding.ActivityMainBinding
import com.google.android.material.snackbar.Snackbar
import java.text.DecimalFormat

class DetailActivity : AppCompatActivity() {
    private lateinit var binding: ActivityDetailBinding
    private var isLiked = false

    @SuppressLint("SetTextI18n", "NewApi")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityDetailBinding.inflate(layoutInflater)
        setContentView(binding.root)

        intent.getParcelableExtra("Item", com.example.applemarket.Post::class.java)
        val getItem = intent.getParcelableExtra("Item", Post::class.java)
        getItem?.let {
            val money = getItem.itemPrice
            val format = DecimalFormat("#,###")
            with(binding) {
                ivProduct.setImageResource(it.itemImage)
                ivIcon.setImageResource(it.mannersImage)
                tvDenickname.text = it.itemnickname
                tvDeadress.text = it.itemAddress
                tvTemperature.text = it.usermanners
                tvDeTitle.text = it.itemTitle
                tvDeinfo.text = it.itemInfo
                tvDeprice.text = "${format.format(money)}원"
                isLiked = it.isLiked == true

                ivDeheart.setImageResource(
                    if (isLiked) {
                        R.drawable.isheart
                    } else {
                        R.drawable.heart
                    }
                )
                ivDeheart.setOnClickListener {
                    isLiked = if (isLiked) {
                        ivDeheart.setImageResource(R.drawable.heart)
                        false
                    } else {
                        ivDeheart.setImageResource(R.drawable.isheart)
                        Snackbar.make(
                            binding.constraintLayout,
                            "관심 목록에 추가되었습니다.",
                            Snackbar.LENGTH_SHORT
                        ).show()
                        true
                    }
                }
            }
        }
        binding.backButton.setOnClickListener {
            goToMain()
        }
    }

    private fun goToMain() {
        val likePosition = intent.getIntExtra("likePosition", 0)
        val intent = Intent(this, MainActivity::class.java).apply {
            putExtra("likePosition", likePosition)
            putExtra("isLiked", isLiked)
        }
        setResult(RESULT_OK, intent)
        if (!isFinishing) finish()
    }

    @SuppressLint("MissingSuperCall")
    override fun onBackPressed() {
        goToMain()
    }
}

Product.kt

package com.example.applemarket

object Product {
    fun productData(): MutableList<Post> {
        val productList = mutableListOf<Post>()
        productList.add(
            Post(
                R.drawable.sample1,
                "산진 한달된 선풍기 팝니다",
                "이사가서 필요가 없어졌어요 급하게 내놓습니다",
                "대현동",
                1000,
                "서울 서대문구 창천동",
                13,
                25,
                "29.7°C",
                R.drawable.lv1
            )
        )
        productList.add(
            Post(
                R.drawable.sample2,
                "김치냉장고",
                "이사로 인해 내놔요",
                "안마담",
                20000,
                "인천 계양구 귤현동",
                8,
                28,
                "35.3°C",
                R.drawable.lv2
            )
        )
        productList.add(
            Post(
                R.drawable.sample3,
                "샤넬 카드지갑",
                "고퀄지갑이구요 사용감이 있어서 싸게 내어둡니다",
                "코코유",
                10000,
                "수성구 범어동",
                23,
                5,
                "36.5°C",
                R.drawable.lv3

            )
        )
        				.
                        .
                        .
        return productList
    }
}
post-custom-banner

0개의 댓글