
// ModifyContentFragment.kt
// 현재 글 번호를 담을 변수
var contentIdx = 0
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
// fragmentModifyContentBinding = FragmentModifyContentBinding.inflate(inflater)
fragmentModifyContentBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_modify_content, container, false)
modifyContentViewModel = ModifyContentViewModel()
fragmentModifyContentBinding.modifyContentViewModel = modifyContentViewModel
fragmentModifyContentBinding.lifecycleOwner = this
contentActivity = activity as ContentActivity
// 글 번호를 담는다.
contentIdx = arguments?.getInt("contentIdx")!!
settingToolbarModifyContent()
settingCameraLauncher()
settingAlbumLauncher()
settingInputForm()
return fragmentModifyContentBinding.root
}
// ModifyContentViewModel.kt
// 게시판 종류를 받아 MutableLiveData에 설정하는 메서드
fun settingContentType(contentType: Int){
toggleModifyContentType.value = when(contentType){
ContentType.TYPE_ALL.number -> 0
ContentType.TYPE_FREE.number -> R.id.buttonModifyContentType1
ContentType.TYPE_HUMOR.number -> R.id.buttonModifyContentType2
ContentType.TYPE_SOCIETY.number-> R.id.buttonModifyContentType3
ContentType.TYPE_SPORTS.number -> R.id.buttonModifyContentType4
else -> 0
}
}
// ModifyContentFragment.kt
// 입력 요소 초기화
fun settingInputForm(){
// 입력 요소에 띄어쓰기를 넣어준다.
modifyContentViewModel.textFieldModifyContentSubject.value = " "
modifyContentViewModel.textFieldModifyContentText.value = " "
CoroutineScope(Dispatchers.Main).launch {
// 현재 글 번호에 해당하는 글 데이터를 가져온다.
val contentModel = ContentDao.selectContentData(contentIdx)
// 가져온 데이터를 보여준다.
modifyContentViewModel.textFieldModifyContentSubject.value = contentModel?.contentSubject
modifyContentViewModel.settingContentType(contentModel?.contentType!!)
modifyContentViewModel.textFieldModifyContentText.value = contentModel?.contentText
// 이미지 데이터를 불러온다.
if(contentModel?.contentImage != null) {
delay(1000L)
ContentDao.gettingContentImage(contentActivity, contentModel.contentImage!!, fragmentModifyContentBinding.imageViewModifyContent)
}
}
}
// ReadContentFragment.kt
setOnMenuItemClickListener {
// 메뉴의 id로 분기한다.
when(it.itemId){
// 댓글
R.id.menuItemReadContentReply -> {
// 댓글을 보여줄 BottomSheet를 띄운다.
showReplyBottomSheet()
}
// 수정하기
R.id.menuItemReadContentModify -> {
// 수정 화면이 보이게 한다.
val modifyBundle = Bundle()
modifyBundle.putInt("contentIdx",contentIdx)
contentActivity.replaceFragment(ContentFragmentName.MODIFY_CONTENT_FRAGMENT, true, true, modifyBundle)
}


// ModifyContentFragment.kt
// 초기화 메뉴를 누르면 입력요소에 설정할 값을 가지고 있는 데이터
var resetSubject=""
var resetContentType = 0
var resetContentText = ""
var resetImage:Bitmap? = null
// 입력 요소 초기화
fun settingInputForm(){
// 입력 요소에 띄어쓰기를 넣어준다.
modifyContentViewModel.textFieldModifyContentSubject.value = " "
modifyContentViewModel.textFieldModifyContentText.value = " "
CoroutineScope(Dispatchers.Main).launch {
// 현재 글 번호에 해당하는 글 데이터를 가져온다.
val contentModel = ContentDao.selectContentData(contentIdx)
// 가져온 글 정보 중 초기화를 위한 데이터를 프로퍼티에 담아준다.
resetSubject = contentModel?.contentSubject!!
resetContentType = contentModel?.contentType!!
resetContentText = contentModel?.contentText!!
// 가져온 데이터를 보여준다.
modifyContentViewModel.textFieldModifyContentSubject.value = contentModel?.contentSubject
modifyContentViewModel.settingContentType(contentModel?.contentType!!)
modifyContentViewModel.textFieldModifyContentText.value = contentModel?.contentText
// 이미지 데이터를 불러온다.
if(contentModel?.contentImage != null) {
delay(1000L)
ContentDao.gettingContentImage(contentActivity, contentModel.contentImage!!, fragmentModifyContentBinding.imageViewModifyContent)
// 이미지뷰로부터 이미지를 가져와 초기화를 위한 프로퍼티에 담아준다.
val bitmapDrawable = fragmentModifyContentBinding.imageViewModifyContent.drawable as BitmapDrawable
resetImage = bitmapDrawable.bitmap
}
}
}
// ModifyContentFragment.kt
// 메뉴
inflateMenu(R.menu.menu_modify_content)
setOnMenuItemClickListener {
when (it.itemId) {
// 카메라
R.id.menuItemModifyContentCamera -> {
startCameraLauncher()
}
// 앨범
R.id.menuItemModifyContentAlbum -> {
startAlbumLauncher()
}
// 초기화
R.id.menuItemModifyContentReset -> {
resetInputForm()
}
// 입력 요소를 초기화 한다.
fun resetInputForm(){
// 가져온 데이터를 보여준다.
modifyContentViewModel.textFieldModifyContentSubject.value = resetSubject
modifyContentViewModel.settingContentType(resetContentType)
modifyContentViewModel.textFieldModifyContentText.value = resetContentText
// 이미지 데이터를 불러온다.
if(resetImage != null) {
fragmentModifyContentBinding.imageViewModifyContent.setImageBitmap(resetImage)
}
}



실제 삭제가 아니라 기본 이미지로 이미지뷰를 변경해준다.
// ModifyContentFragment.kt
// 이미지 삭제 버튼
fun settingButtonModifyContentImageDelete(){
fragmentModifyContentBinding.buttonModifyContentImageDelete.setOnClickListener {
// 이미지 뷰의 이미지를 변경한다.
fragmentModifyContentBinding.imageViewModifyContent.setImageResource(R.drawable.panorama_24px)
}
}


// ContentDao.kt
// 글 데이터를 수정하는 메서드
suspend fun updateContentData(contentModel: ContentModel, isRemoveImage:Boolean){
val job1 = CoroutineScope(Dispatchers.IO).launch {
// 컬렉션에 접근할 수 있는 객체를 가져온다.
val collectionReference = Firebase.firestore.collection("ContentData")
// 컬렉션이 가지고 있는 문서들 중에 수정한 글 정보를 가져온다.
val query = collectionReference.whereEqualTo("contentIdx", contentModel.contentIdx).get().await()
// 저장할 데이터를 담을 HashMap을 만들어준다.
val map = mutableMapOf<String, Any?>()
map["contentSubject"] = contentModel.contentSubject
map["contentText"] = contentModel.contentText
map["contentType"] = contentModel.contentType
if(contentModel.contentImage != null){
map["contentImage"] = contentModel.contentImage!!
}
// 사용자가 이미지를 삭제했다면
if(isRemoveImage == true){
map["contentImage"] = null
}
// 저장한다.
// 가져온 문서 중 첫 번째 문서에 접근하여 데이터를 수정한다.
query.documents[0].reference.update(map)
}
job1.join()
}
// ModifyContentFragment.kt
// 사용자에 의해서 이미지가 변경되었는지..
var isChangeImage = false
// 사용자가 이미지를 삭제했는지
var isRemoveImage = false
// 입력 요소를 초기화 한다.
fun resetInputForm(){
// 가져온 데이터를 보여준다.
modifyContentViewModel.textFieldModifyContentSubject.value = resetSubject
modifyContentViewModel.settingContentType(resetContentType)
modifyContentViewModel.textFieldModifyContentText.value = resetContentText
// 이미지 데이터를 불러온다.
if(resetImage != null) {
fragmentModifyContentBinding.imageViewModifyContent.setImageBitmap(resetImage)
}
// 사용자가 이미지를 변경했는지의 값을 초기화한다.
isChangeImage = false
isRemoveImage = false
}
// 카메라 런처 설정
fun settingCameraLauncher(){
val contract1 = ActivityResultContracts.StartActivityForResult()
cameraLauncher = registerForActivityResult(contract1){
// 사진을 사용하겠다고 한 다음에 돌아왔을 경우
if(it.resultCode == AppCompatActivity.RESULT_OK){
// 사진 객체를 생성한다.
val bitmap = BitmapFactory.decodeFile(contentUri.path)
// 회전 각도값을 구한다.
val degree = Tools.getDegree(contentActivity, contentUri)
// 회전된 이미지를 구한다.
val bitmap2 = Tools.rotateBitmap(bitmap, degree.toFloat())
// 크기를 조정한 이미지를 구한다.
val bitmap3 = Tools.resizeBitmap(bitmap2, 1024)
fragmentModifyContentBinding.imageViewModifyContent.setImageBitmap(bitmap3)
isChangeImage = true
// 사진 파일을 삭제한다.
val file = File(contentUri.path)
file.delete()
}
}
}
// 앨범 런처 설정
fun settingAlbumLauncher() {
// 앨범 실행을 위한 런처
val contract2 = ActivityResultContracts.StartActivityForResult()
albumLauncher = registerForActivityResult(contract2){
// 사진 선택을 완료한 후 돌아왔다면
if(it.resultCode == AppCompatActivity.RESULT_OK){
// 선택한 이미지의 경로 데이터를 관리하는 Uri 객체를 추출한다.
val uri = it.data?.data
if(uri != null){
// 안드로이드 Q(10) 이상이라면
val bitmap = if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q){
// 이미지를 생성할 수 있는 객체를 생성한다.
val source = ImageDecoder.createSource(contentActivity.contentResolver, uri)
// Bitmap을 생성한다.
ImageDecoder.decodeBitmap(source)
} else {
// 컨텐츠 프로바이더를 통해 이미지 데이터에 접근한다.
val cursor = contentActivity.contentResolver.query(uri, null, null, null, null)
if(cursor != null){
cursor.moveToNext()
// 이미지의 경로를 가져온다.
val idx = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
val source = cursor.getString(idx)
// 이미지를 생성한다
BitmapFactory.decodeFile(source)
} else {
null
}
}
// 회전 각도값을 가져온다.
val degree = Tools.getDegree(contentActivity, uri)
// 회전 이미지를 가져온다
val bitmap2 = Tools.rotateBitmap(bitmap!!, degree.toFloat())
// 크기를 줄인 이미지를 가져온다.
val bitmap3 = Tools.resizeBitmap(bitmap2, 1024)
fragmentModifyContentBinding.imageViewModifyContent.setImageBitmap(bitmap3)
isChangeImage = true
}
}
}
}
// 이미지 삭제 버튼
fun settingButtonModifyContentImageDelete(){
fragmentModifyContentBinding.buttonModifyContentImageDelete.setOnClickListener {
// 이미지 뷰의 이미지를 변경한다.
fragmentModifyContentBinding.imageViewModifyContent.setImageResource(R.drawable.panorama_24px)
isChangeImage = true
isRemoveImage = true
}
}
// ModifyContentViewModel.kt
// 게시판의 타입을 반환하는 메서드를 만들어준다.
fun gettingContentType() = when(toggleModifyContentType.value){
R.id.buttonModifyContentType1 -> ContentType.TYPE_FREE.number
R.id.buttonModifyContentType2 -> ContentType.TYPE_HUMOR.number
R.id.buttonModifyContentType3 -> ContentType.TYPE_SOCIETY.number
R.id.buttonModifyContentType4 -> ContentType.TYPE_SPORTS.number
else -> 0
}
// ModifyContentFragment.kt
// 메뉴
inflateMenu(R.menu.menu_modify_content)
setOnMenuItemClickListener {
when (it.itemId) {
// 카메라
R.id.menuItemModifyContentCamera -> {
startCameraLauncher()
}
// 앨범
R.id.menuItemModifyContentAlbum -> {
startAlbumLauncher()
}
// 초기화
R.id.menuItemModifyContentReset -> {
resetInputForm()
}
// 완료
R.id.menuItemModifyContentDone -> {
// 입력 요소 검사
val chk = checkInputForm()
if(chk == true){
updateContentData()
}
}
}
// 글 정보를 업로드하는 메서드
fun updateContentData(){
CoroutineScope(Dispatchers.Main).launch {
// 서버에서의 첨부 이미지 파일 이름
var serverFileName:String? = null
// 사용자가 이미지를 변경하였다면(삭제 X)
if(isChangeImage == true && isRemoveImage == false) {
// 이미지의 뷰의 이미지 데이터를 파일로 저장한다.
Tools.saveImageViewData(contentActivity, fragmentModifyContentBinding.imageViewModifyContent, "uploadTemp.jpg")
// 서버에서의 파일 이름
serverFileName = "image_${System.currentTimeMillis()}.jpg"
// 서버로 업로드한다.
ContentDao.uploadImage(contentActivity, "uploadTemp.jpg", serverFileName)
}
// 업로드할 정보를 담아준다.
val contentSubject = modifyContentViewModel.textFieldModifyContentSubject.value!!
val contentType = modifyContentViewModel.gettingContentType()
val contentText = modifyContentViewModel.textFieldModifyContentText.value!!
// 객체에 담아준다.
val contentModel = ContentModel(contentIdx, contentSubject, contentType, contentText, null, 0, "", 0)
// 업로드된 이미지가 있다면
if(serverFileName != null){
contentModel.contentImage = serverFileName
}
// 업로드한다.
ContentDao.updateContentData(contentModel, isRemoveImage)
// 이전으로 돌아간다.
contentActivity.removeFragment(ContentFragmentName.MODIFY_CONTENT_FRAGMENT)
}
}