이제 자취톡 부분에 게시판 기능을 만들어볼것이다
일단 fragment_talk.xml로 가서 게시물작성버튼을 추가로 디자인해준다
<ImageView
android:id="@+id/writeBtn"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/btnwrite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginBottom="90dp"
android:layout_marginRight="20dp"/>
fragment_talk.xml
그리고 게시물작성 버튼을 누르면 이동할 엑티비티인 BoardWriteActivity와 xml파일을 만들어주고,
TalkFragment로 가서 게시물 작성버튼을 눌렀을때 BoardWriteActivity로 이동하는 코드를 짜준다
// 게시물 작성버튼 눌렀을때
binding.writeBtn.setOnClickListener {
val intent = Intent(context, BoardWriteActivity::class.java)
startActivity(intent)
}
TalkFragment.kt
그런다음 activity_board_write.xml 레이아웃파일을 디자인해주겠다
<?xml version="1.0" encoding="utf-8"?>
<layout>
<LinearLayout
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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".board.BoardWriteActivity"
android:orientation="vertical">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="60dp">
<TextView
android:text="글쓰기 페이지"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="@color/black"
android:gravity="center"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#000000"/>
<EditText
android:id="@+id/titleArea"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:background="@android:color/transparent"
android:hint="제목을 입력해주세요"
android:layout_height="60dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#000000"/>
<EditText
android:id="@+id/contentArea"
android:layout_margin="20dp"
android:layout_width="match_parent"
android:hint="내용을 입력해주세요"
android:background="@android:color/transparent"
android:layout_height="60dp"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="#000000"/>
<ImageView
android:id="@+id/imageArea"
android:src="@drawable/plusbtn"
android:layout_marginTop="20dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/writeBtn"
android:text="입력"
android:layout_width="match_parent"
android:background="@drawable/background_radius_yellow"
android:layout_marginTop="50dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:layout_height="wrap_content"/>
</LinearLayout>
</ScrollView>
</LinearLayout>
</layout>
activity_board_write.xml
여기까지하면 게시물작성버튼을 클릭하면 BoardWriteActivity화면으로 이동하는것을 확인할수있다
이제 입력버튼을 눌렀을때 파이어베이스 데이터베이스에 데이터를 올리는 작업을 해야될것이다
파이어베이스 리얼타임 데이터베이스에 board를 새로 추가시켜서 게시글이 저장되도록 만들어보고싶기때문에
FBRef.kt파일로가서 getReference를 사용해서 board를 추가해준다
// 파이어베이스에 board 추가
val boardRef = database.getReference("board")
FBRef.kt
그리고 BoardWriteActivity로 가서 데이터바인딩을 해준뒤, 입력버튼을 눌렀을때 titleArea(제목)과 contentArea(내용)에 해당하는 부분을 받아온다. 제목과 내용이 잘 받아왔는지 로그를 찍어서 확인해보면 내가 입력한 제목,내용값이 로그에 잘 찍히는것을 확인할수있다
이제 데이터를 집어넣는 작업을 해줄것이다
파이어베이스에 들어갈 데이터구조를 아래와같이 짜줄것이다. boardModel은 title, content, uid, time을 넣어서 직접 데이터모델을 생성해줄것이다
<데이터구조>
-board
- key (임의의값)
- boardModel (title, content, uid, time)
근데 아직 boardModel이 없기때문에 먼저 생성해준다
package com.example.mysololife.board
data class BoardModel(
val title : String = "", // 제목
val content : String = "", // 내용
val uid : String = "", // uid
val time : String = "" // 현재시간
)
boardModel.kt
package com.example.mysololife.board
class BoardWriteActivity : AppCompatActivity() {
private lateinit var binding : ActivityBoardWriteBinding
private val TAG = BoardWriteActivity::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_board_write)
binding.writeBtn.setOnClickListener {
// titleArea,contentArea 값을 받아옴
val title = binding.titleArea.text.toString()
val content = binding.contentArea.text.toString()
Log.d(TAG, title)
Log.d(TAG, content)
// 데이터 집어넣기
FBRef.boardRef
.push()
.setValue(BoardModel(title,content,"uid","time"))
}
}
}
BoardWriteActivity.kt
이렇게하고 글을작성하고, 파이어베이스를 보면 board안에 내가 쓴 글이 잘 등록이 되어있는걸 볼수있다
근데 아직 uid값과 시간에 해당하는 값은 들어가지 않았기 때문에 알맞은값이 들어갈수있도록 수정해준다
uid값은 이미 FBAuth.kt에 만들어놨기때문에 그걸 가져와서 사용해주고, 시간에 해당하는값은 아래와같이 추가를 해준다
// 시간가져오는 함수
fun getTime() : String{
val currentDateTime = Calendar.getInstance().time
val dateFormat = SimpleDateFormat("yyyy.MM.dd HH:mm:ss", Locale.KOREA).format(currentDateTime)
return dateFormat
}
FBAuth.kt
package com.example.mysololife.board
class BoardWriteActivity : AppCompatActivity() {
private lateinit var binding : ActivityBoardWriteBinding
private val TAG = BoardWriteActivity::class.java.simpleName
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = DataBindingUtil.setContentView(this, R.layout.activity_board_write)
binding.writeBtn.setOnClickListener {
// titleArea,contentArea 값을 받아옴
val title = binding.titleArea.text.toString()
val content = binding.contentArea.text.toString()
// uid값 가져오기
val uid = FBAuth.getUid()
// tiem값 가져오기
val time = FBAuth.getTime()
Log.d(TAG, title)
Log.d(TAG, content)
// 데이터 집어넣기
FBRef.boardRef
.push()
.setValue(BoardModel(title,content,uid,time))
Toast.makeText(this, "게시글 입력완료", Toast.LENGTH_SHORT).show()
// 엑티비티 사라짐
finish()
}
}
}
BoardWriteActivity.kt
BoardWriteActivity도 이렇게 수정해주고 파이어베이스를 확인해보면 uid값과 시간값도 잘 들어간걸 확인할수있다
이제 파이어베이스에 등록되어있는 데이터들을 불러오는 작업을 해볼것이다
게시글을 올리면 보이는부분을 리스트뷰를 이용해서 나타내줄것이기때문에
fragment_talk.xml로가서 리스트뷰를 추가해준다. (리스트뷰 만들기- 리스트뷰추가,아이템레이아웃 생성,어뎁터와 연결)
그리고 board_list_item.xml을 생성해서 아이템 레이아웃을 만들어준다
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:orientation="vertical">
<TextView
android:id="@+id/titleArea"
android:text="제목"
android:textSize="20sp"
android:layout_margin="15dp"
android:textStyle="bold"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/contentArea"
android:text="내용"
android:textSize="15sp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:textColor="@color/black"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/timeArea"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="5dp"
android:text="시간"
android:textColor="#999999"
android:textSize="10sp" />
</LinearLayout>
board_list_item.xml
제목,내용,시간에 관련된 내용만 리스트뷰에 보여지게 할것이기때문에 이렇게 디자인해줬다
이제 어뎁터도 생성해준다
package com.example.mysololife.board
// BoardModel 데이터모델을 받아옴
class BoadListLVAdapter(val boardList: MutableList<BoardModel>) : BaseAdapter() {
override fun getCount(): Int {
// boardList의 사이즈만큼 리턴
return boardList
.size
}
override fun getItem(position: Int): Any {
// boardList를 클릭한값 리턴
return boardList[position]
}
override fun getItemId(position: Int): Long {
return position.toLong()
}
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
// 아이템뷰를 가져와서 연결
var view = convertView
if (view == null){
view = LayoutInflater.from(parent?.context).inflate(R.layout.board_list_item, parent,false)
}
return view!!
}
}
BoardListLVAdapter.kt
이제 방금만든 이 어뎁터를 TalkFragment에 연결해주면 된다
그리고 BoardModle의 리스트를 만들어주고, 값을 임의로 추가해준다
package com.example.mysololife.fragments
class TalkFragment : Fragment() {
private lateinit var binding : FragmentTalkBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater,R.layout.fragment_talk,container,false)
val boardList = mutableListOf<BoardModel>()
boardList.add(BoardModel("a","b","c","d"))
// 어뎁터와 ListView 연결
val BoardRVadapter = BoadListLVAdapter(boardList)
binding.boardListView.adapter = BoardRVadapter
...
}
TalkFragment.kt
여기까지 작성해주고 앱을 실행시켜주면 리스트뷰 한개가 잘 나오고 있는것을 확인할수있다
지금은 a,b,c,d로 샘플데이터를 넣었지만, 실제로 파이어베이스에 등록되어있는 데이터들을 가져와서 넣어줘야한다
TalkFramgment에서 게시글 데이터를 가져오고, 데이터를 받아와서 하나하나씩 넣어주는 작업을 해준다
그리고 이 데이터들을 어뎁터와 연결해준다
package com.example.mysololife.fragments
class TalkFragment : Fragment() {
private lateinit var binding : FragmentTalkBinding
private val TAG = TalkFragment::class.java.simpleName
private val boardDataList = mutableListOf<BoardModel>()
private lateinit var boardRVAdapter : BoadListLVAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = DataBindingUtil.inflate(inflater,R.layout.fragment_talk,container,false)
// val boardList = mutableListOf<BoardModel>()
// boardList.add(BoardModel("a","b","c","d"))
// 어뎁터와 ListView 연결
boardRVAdapter = BoadListLVAdapter(boardDataList)
binding.boardListView.adapter = boardRVAdapter
...
// 게시글 데이터 가져오는 함수
private fun getFBBoardData(){
// 데이터 가져오기
val postListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
for (dataModel in dataSnapshot.children){
Log.d(TAG, dataModel.toString())
// 데이터 받아오기
val item = dataModel.getValue(BoardModel::class.java)
boardDataList.add(item!!) // BoardModel에 데이터 하나씩 넣어줌
}
//동기화
boardRVAdapter.notifyDataSetChanged()
Log.d(TAG, boardDataList.toString())
}
override fun onCancelled(databaseError: DatabaseError) {
// Getting Post failed, log a message
Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
}
}
FBRef.boardRef.addValueEventListener(postListener)
}
}
TalkFramgment.kt
여기까지하면 이런식으로 결과가 나오는것을 볼수있다
등록은 되는데 내가 쓴 글의 내용들은 반영이 안되기때문에 반영을 해주도록 하겠다
그리고 처음에 게시글내용이 2배로 등록되는 오류도 수정해보도록 하겠다
BoardListLVAdapter에서 아래와같이 코드를 써주면 내가 작성한 값들이 리스트뷰에 잘 보여지는것을 확인할수있다
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
...
// 내가 작성한 title값이 titleArea1에 적용되게
val title = view?.findViewById<TextView>(R.id.titleArea1)
title!!.text = boardList[position].title
// 내가 작성한 content값이 contentArea1에 적용되게
val content = view?.findViewById<TextView>(R.id.contentArea1)
content!!.text = boardList[position].content
// 내가 작성한 time값이 timeArea1에 적용되게
val time = view?.findViewById<TextView>(R.id.timeArea1)
time!!.text = boardList[position].time
return view!!
}
BoardListLVAdapter.kt
보통은 순서를 아래와같이 써주는것같지만 나는 위에처럼 쓰는게 편해서 저렇게 써주었다
override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View {
...
val title = view?.findViewById<TextView>(R.id.titleArea1)
val content = view?.findViewById<TextView>(R.id.contentArea1)
val time = view?.findViewById<TextView>(R.id.timeArea1)
title!!.text = boardList[position].title
content!!.text = boardList[position].content
time!!.text = boardList[position].time
return view!!
}
BoardListLVAdapter.kt
이제 데이터가 겹쳐서 출력되는현상을 해결해줄것이다.
데이터가 변경이 되면 한번 더 실행이 되는게 파이어베이스의 특징이라고 할수있다
그래서 데이터를 초기화시켜줘서 겹쳐서 출력되는 현상을 방지시켜준다
// 게시글 데이터 가져오는 함수
private fun getFBBoardData(){
// 데이터 가져오기
val postListener = object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
// 겹쳐서 출력되는 현상 방지 (데이터 초기화)
boardDataList.clear()
for (dataModel in dataSnapshot.children){
Log.d(TAG, dataModel.toString())
// 데이터 받아오기
val item = dataModel.getValue(BoardModel::class.java)
boardDataList.add(item!!) // BoardModel에 데이터 하나씩 넣어줌
}
//동기화
boardRVAdapter.notifyDataSetChanged()
Log.d(TAG, boardDataList.toString())
}
TalkFramgment.kt
여기까지하면 내가 입력한 데이터가 리스트뷰에 잘 반영이되는것을 볼수있다
'Android Project' 카테고리의 다른 글
[Android/Kotlin] 커뮤니티앱(9) - 게시글 이미지 업로드 (0) | 2024.01.28 |
---|---|
[Android/Kotlin] 커뮤니티앱(8) - 게시글 클릭 (0) | 2024.01.28 |
[Android/Kotlin] 커뮤니티앱(6) - 북마크탭 만들기 (0) | 2024.01.28 |
[Android/Kotlin] 커뮤니티앱(5) - 북마크 만들기 (0) | 2024.01.28 |
[Android/Kotlin] 커뮤니티앱(4) - 꿀팁 페이지 만들기 (0) | 2024.01.28 |