-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ Team2 (Jay&Stitch) ] recyclerview 클릭 이벤트 + MVVM 패턴 적용 #18
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.example.kotlinphotos.model | ||
|
||
import android.graphics.Bitmap | ||
import com.example.kotlinphotos.model.Type.* | ||
|
||
data class Photo( | ||
val tittle: String, | ||
val bitmap: Bitmap?, | ||
val date: String, | ||
var isChecked: Boolean = false, | ||
var mode: Type = READ | ||
) | ||
|
||
enum class Type(val mode: Int) { | ||
READ(1), | ||
EDIT(2) | ||
} |
This file was deleted.
This file was deleted.
This file was deleted.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package com.example.kotlinphotos.repository | ||
|
||
import android.graphics.Bitmap | ||
import android.graphics.BitmapFactory | ||
import com.example.kotlinphotos.AssetLoader | ||
import com.example.kotlinphotos.model.Photo | ||
import kotlinx.coroutines.Dispatchers | ||
import kotlinx.coroutines.withContext | ||
import org.json.JSONArray | ||
import java.net.URL | ||
|
||
class DoodleAssetDataSource( | ||
private val assetLoader: AssetLoader | ||
) : DoodleDataSource { | ||
|
||
override suspend fun getDoodleData(): List<Photo> { | ||
val photos = mutableListOf<Photo>() | ||
val str = assetLoader.jsonToString(DOODLE_FILE_NAME) | ||
val jsonArray = JSONArray(str) | ||
|
||
val size = jsonArray.length() | ||
repeat(size) { | ||
val json = jsonArray.getJSONObject(it) | ||
val title = json.getString("title") | ||
val image = json.getString("image") | ||
val date = json.getString("date") | ||
val bitmap = loadImage(image) | ||
photos.add(Photo(title, bitmap, date)) | ||
} | ||
return photos | ||
} | ||
|
||
private suspend fun loadImage(imageUrl: String): Bitmap? { | ||
return withContext(Dispatchers.IO) { | ||
kotlin.runCatching { | ||
val url = URL(imageUrl) | ||
val stream = url.openStream() | ||
BitmapFactory.decodeStream(stream) | ||
}.getOrNull() | ||
} | ||
} | ||
|
||
companion object { | ||
const val DOODLE_FILE_NAME = "doodle.json" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.example.kotlinphotos.repository | ||
|
||
import com.example.kotlinphotos.model.Photo | ||
|
||
interface DoodleDataSource { | ||
|
||
suspend fun getDoodleData(): List<Photo> | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.example.kotlinphotos.repository | ||
|
||
import com.example.kotlinphotos.model.Photo | ||
|
||
class DoodleRepository( | ||
private val doodleAssetDataSource: DoodleAssetDataSource | ||
) { | ||
suspend fun loadDoodlePhotos(): List<Photo> { | ||
return doodleAssetDataSource.getDoodleData() | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package com.example.kotlinphotos.ui.doodle | ||
|
||
import androidx.appcompat.app.AppCompatActivity | ||
import android.os.Bundle | ||
import android.view.View | ||
import android.widget.ImageButton | ||
import androidx.activity.viewModels | ||
import androidx.recyclerview.widget.GridLayoutManager | ||
import androidx.recyclerview.widget.RecyclerView | ||
import com.example.kotlinphotos.R | ||
import com.example.kotlinphotos.ui.common.PhotosDiffCallback | ||
|
||
class DoodleActivity : AppCompatActivity() { | ||
private lateinit var backButton: ImageButton | ||
private lateinit var recyclerView: RecyclerView | ||
private lateinit var saveImageButton: ImageButton | ||
private val viewModel: DoodleViewModel by viewModels { DoodleViewModelFactory(this) } | ||
|
||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContentView(R.layout.activity_doodle) | ||
|
||
backButton = findViewById(R.id.image_button_back) | ||
recyclerView = findViewById(R.id.recyclerview_doodle) | ||
saveImageButton = findViewById(R.id.image_button_save) | ||
|
||
backButton.setOnClickListener { finish() } | ||
|
||
val doodleAdapter = DoodleAdapter(PhotosDiffCallback(), object : OnSaveListener { | ||
override fun showSaveButton() { | ||
saveImageButton.visibility = View.VISIBLE | ||
} | ||
}) | ||
recyclerView.adapter = doodleAdapter | ||
recyclerView.layoutManager = GridLayoutManager(this, 3) | ||
viewModel.photos.observe(this) { doodleAdapter.submitList(it) } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
package com.example.kotlinphotos.ui.doodle | ||
|
||
import android.view.LayoutInflater | ||
import android.view.View | ||
import android.view.ViewGroup | ||
import android.widget.CheckBox | ||
import android.widget.ImageView | ||
import androidx.recyclerview.widget.DiffUtil | ||
import androidx.recyclerview.widget.ListAdapter | ||
import androidx.recyclerview.widget.RecyclerView | ||
import com.example.kotlinphotos.R | ||
import com.example.kotlinphotos.model.Photo | ||
import com.example.kotlinphotos.model.Type.* | ||
|
||
class DoodleAdapter( | ||
diffCallback: DiffUtil.ItemCallback<Photo>, | ||
private val saveListener: OnSaveListener | ||
) : ListAdapter<Photo, DoodleAdapter.DoodleViewHolder>(diffCallback) { | ||
|
||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): DoodleViewHolder { | ||
return DoodleViewHolder( | ||
LayoutInflater.from(parent.context).inflate(R.layout.item, parent, false) | ||
) | ||
} | ||
|
||
override fun onBindViewHolder(holder: DoodleViewHolder, position: Int) { | ||
val photo = getItem(position) | ||
holder.bind(getItem(position)) | ||
|
||
holder.itemView.setOnLongClickListener { | ||
for (current in currentList) { | ||
current.mode = EDIT | ||
} | ||
false | ||
} | ||
holder.itemView.setOnClickListener { | ||
if (photo.mode == EDIT) { | ||
currentList[position].isChecked = true | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bn-tw2020 @shim506 Edit모드를 구현한 방식이 수정이 필요해 보입니다.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 1-1 . 위와 같이 구현한 이유는
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @shim506 왜 이렇게 구현하신지는 알죠~ 제가 수정 의견을 드렸던 이유는 이벤트는 LongClick으로 발생했는데 데이터 변경 처리를 바로하지 않고 다른 이벤트 처리기로 이동시키는 부분이 아쉬웠기 때문입니다~ |
||
saveListener.showSaveButton() | ||
notifyDataSetChanged() | ||
} | ||
} | ||
} | ||
|
||
inner class DoodleViewHolder(view: View) : RecyclerView.ViewHolder(view) { | ||
|
||
private val photoImageView = view.findViewById<ImageView>(R.id.view_photo) | ||
private val photoCheckBox = view.findViewById<CheckBox>(R.id.checkbox_select) | ||
|
||
fun bind(photo: Photo) { | ||
when (photo.mode) { | ||
EDIT -> photoCheckBox.visibility = View.VISIBLE | ||
READ -> photoCheckBox.visibility = View.INVISIBLE | ||
} | ||
photoCheckBox.setOnCheckedChangeListener(null) | ||
photoCheckBox.isChecked = photo.isChecked | ||
photoCheckBox.setOnCheckedChangeListener { _, value -> photo.isChecked = value } | ||
photoImageView.setImageBitmap(photo.bitmap) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@bn-tw2020 @shim506 이 코드는 holder의 itemView를 꺼내서 Listener를 할당하고 있네요~
bind 메서드 내부로 이동시키는 편이 낫지 않을까요? 어떻게 생각하세요? 바로 아래 코드도 마찬가지입니다.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
다음 PR 에 수정내용 반영해서 보내겠습니다.