본문 바로가기

Android Project

[Android/Kotlin] 커뮤니티앱(8) - 게시글 클릭

이제 저번까지 만든 게시판 리스트뷰를 클릭하면 게시판 안쪽으로 들어가서 볼수있게 할것이다

그리고 아직 이미지 업로드는 해주지 않아서 파이어베이스를 통해 이미지 업로드도 해볼것이다

 

게시판을 클릭해서 세부내용을 보는 방법은 두가지로 생각해볼수있다

첫번째 방법은 게시글을 클릭하면 listview에 있는 제목,내용,시간 데이터를 다 다른 엑티비티로 전달해주는 방법이다

두번째 방법은 파이어베이스에서 board데이터 안에 있는 id의 값이 제목,내용,시간,uid를 다 포함하고있기 때문에, 

board데이터 안에 있는 id를 기반으로 데이터를 받아오는 방법이 있다

 

두가지 방법을 다 해볼건데, 사실 두번째 방법이 더 좋은방법이라고 할수있다

 

첫번째 방법부터 실행해볼것이다 

먼저 리스트뷰 아이템을 클릭하면 이동할 엑티비티와 레이아웃을 만들어주고, TalkFragment로 가서 리스트뷰 아이템을 클릭하면 해당 엑티비티로 이동하는 코드를 짜준다

리스트뷰 아이템 클릭이기때문에 setOnitemClickListner를 사용해준다

// 리스트뷰 아이템 클릭시
binding.boardListView.setOnItemClickListener { parent, view, position, id ->

    val intent = Intent(context, BoardInsideActivity::class.java)
    startActivity(intent)
}

TalkFragment.kt

 

이렇게하면 리스트뷰 아이템 클릭시 BoardInsideActivity로 이동하는것을 볼수있다

 

 

# intent 데이터 전달 

이동은 하는데 데이터가 아무것도 안들어가 있기때문에 데이터를 전달해서 넣어줄것이다

TalkFragment에서 클릭한 값의 title,content,time값을 넘겨준다 

// 리스트뷰 아이템 클릭시
binding.boardListView.setOnItemClickListener { parent, view, position, id ->

    val intent = Intent(context, BoardInsideActivity::class.java)

    // 값 전달(넘겨줌)
    intent.putExtra("title", boardDataList[position].title)     // 클릭된값의 title
    intent.putExtra("content",boardDataList[position].content)  // 클릭된값의 content
    intent.putExtra("time",boardDataList[position].time)        // 클릭된값의 time

    startActivity(intent)
}

TalkFragment.kt

 

이제 넘겨준 값을 BoardInsideActivity에서 받아와주겠다

getExtra()를 통해서 넘겨준값을 받아온다음, 데이터가 잘 들어갔는지 로그를 통해 찍어보면 잘 들어간것을 확인할수있다

package com.example.mysololife.board

class BoardInsideActivity : AppCompatActivity() {

    private val TAG = BoardInsideActivity::class.java.simpleName

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_board_inside)

        // TalkFragment에서 넘겨준값 받아오기
        val title = intent.getStringExtra("title").toString()
        val content = intent.getStringExtra("content").toString()
        val time = intent.getStringExtra("time").toString()

        Log.d(TAG, title)
        Log.d(TAG, content)
        Log.d(TAG, time)

    }
}

BoardInsideActivity.kt

로그 결과값

로그를 찍어보면 이렇게 내가 클릭한 아이템의 title,content,time값이 잘 들어가는것을 확인할수있다

 

이제 데이터가 잘 넘어갔으니깐 이 넘어간 데이터가 화면에 보이게 꾸며주기만하면 될것이다

클릭한 리스트아이템 레이아웃 디자인을 해준다

<?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.BoardInsideActivity"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="60dp">

            <TextView
                android:id="@+id/titleArea"
                android:text="title"
                android:textColor="@color/black"
                android:textSize="20sp"
                android:textStyle="bold"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:background="@color/black"
            android:layout_height="0.5dp">

        </LinearLayout>

        <TextView
            android:id="@+id/timeArea"
            android:text="time"
            android:layout_width="match_parent"
            android:gravity="right"
            android:layout_margin="10dp"
            android:layout_height="wrap_content"/>

        <TextView
            android:id="@+id/textArea"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:layout_margin="20dp"
            android:textColor="@color/black"
            android:text="여기는 내용 영역"
            android:background="@drawable/background_radius"
            android:padding="10dp"/>


        <ImageView
            android:id="@+id/getImageArea"
            android:src="@drawable/logo"
            android:layout_margin="30dp"
            android:layout_width="match_parent"
            android:layout_height="300dp"/>

    </LinearLayout>

</layout>

activity_board_inside.xml

 

activity_board_inside.xml

 

 

그다음 BoardInsideActivity로 가서 binding을 사용해서 각각의 레이아웃과 데이터를 연결해준다

package com.example.mysololife.board

class BoardInsideActivity : AppCompatActivity() {

    private val TAG = BoardInsideActivity::class.java.simpleName

    private lateinit var binding : ActivityBoardInsideBinding

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this,R.layout.activity_board_inside )

        // TalkFragment에서 넘겨준값 받아오기
        val title = intent.getStringExtra("title").toString()
        val content = intent.getStringExtra("content").toString()
        val time = intent.getStringExtra("time").toString()

        // 레이아웃과 데이터 연결
        binding.titleArea.text = title
        binding.textArea.text = content
        binding.timeArea.text = time

    }
}

BoardInsideActivity.kt

 

이렇게 해주면 데이터가 잘 나타나는것을 볼수있다

 

 

 

 

그리고 보통 최신글이 맨 위로 가기때문에 뒤집어주는 간단한 코드를 추가해준다

// 데이터 최신순으로
boardDataList.reverse()

TalkFragment.kt

동기화시키기 전에 이 코드를 추가해주면 최신순으로 글이 나오는것을 볼수있다

 

 

 

 

 

 

이렇게 첫번째 방법은 구현해봤고, 이제 두번째 방법으로 구현해볼것이다

파이어베이스에 있는 board에 대한 데이터의 id를 기반으로 데이터를 받아올것이다

 

먼저 파이어베이스에서 값을 받아와야한다. board데이터의 key값을 알면 게시물데이터에 대한  정보를 받아올수있을것이기 때문에 key값을 받아오는 작업을 해보겠다

먼저 TalkFragment에서 키값을 넣어주는 리스트를 생성한뒤, 그 리스트에 키값을 넣어준다

그리고 리스트뷰 아이템 클릭시 BoardInsideActivity로 넘어갈때 key값도 같이 넘겨준다

BoardInsideActivity에서는 방금 넘겨준 데이터를 받아온다

이렇게하고 토스트 메시지를 찍어서 키값을 잘 받아오는지 확인해주었더니 잘 받아오는것을 확인할수있다

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

    // 키값 넣어주는 리스트
    private val boardKeyList = mutableListOf<String>()


    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)


        // 리스트뷰 아이템 클릭시
        binding.boardListView.setOnItemClickListener { parent, view, position, id ->

//            val intent = Intent(context, BoardInsideActivity::class.java)
//            // 값 전달(넘겨줌)
//            intent.putExtra("title", boardDataList[position].title)     // 클릭된값의 title
//            intent.putExtra("content",boardDataList[position].content)  // 클릭된값의 content
//            intent.putExtra("time",boardDataList[position].time)        // 클릭된값의 time


            val intent = Intent(context, BoardInsideActivity::class.java)
            intent.putExtra("key",boardKeyList[position])   // key값 넘겨줌
            startActivity(intent)
        }
    
      ...

    }


    // 게시글 데이터 가져오는 함수
    private fun getFBBoardData(){

        // 데이터 가져오기
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {

                // 겹쳐서 출력되는 현상 방지 (데이터 초기화)
                boardDataList.clear()

                for (dataModel in dataSnapshot.children){

                    Log.d(TAG, dataModel.toString())

//                    // 키값 받아오기
//                    dataModel.key

                    // 데이터 받아오기
                    val item = dataModel.getValue(BoardModel::class.java)
                    boardDataList.add(item!!)   // BoardModel에 데이터 하나씩 넣어줌
                    boardKeyList.add(dataModel.key.toString())// key값 넣어줌
                }

                // 데이터 최신순으로
                boardDataList.reverse()

                //동기화
                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)
    }


}

TalkFragment.kt

 

package com.example.mysololife.board

class BoardInsideActivity : AppCompatActivity() {

    private val TAG = BoardInsideActivity::class.java.simpleName

    private lateinit var binding : ActivityBoardInsideBinding

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this,R.layout.activity_board_inside )

        // TalkFragment에서 보낸 key데이터 받아오기
        val key = intent.getStringExtra("key")

        Toast.makeText(this, key, Toast.LENGTH_SHORT).show()


    }
}

BoardInsideActivity.kt

 

 

이제 이걸 이용해서 데이터를 받아와줄것이다

getBoardData()함수를 만들어서 key값을 바탕으로 데이터를 받아와준다

그동안은 데이터 리스트를 가져왔지만 지금은 board안에있는 key값 한덩어리만 가지고올것이기 때문에 반복문을 사용해줄 필요가 없다. 그래서 반복문을 사용하지않고 데이터를 받아와준다. 

이제 이 데이터를 레이아웃과 연결해줘서 알맞은 위치에 연결해주면된다

package com.example.mysololife.board

class BoardInsideActivity : AppCompatActivity() {

    private val TAG = BoardInsideActivity::class.java.simpleName

    private lateinit var binding : ActivityBoardInsideBinding

    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this,R.layout.activity_board_inside )


        // TalkFragment에서 보낸 key데이터 받아오기
        val key = intent.getStringExtra("key")

        getBoardData(key.toString())

    }


    // board데이터 받아오는 함수
    private fun getBoardData(key : String){

        // 데이터 가져오기
        val postListener = object : ValueEventListener {
            override fun onDataChange(dataSnapshot: DataSnapshot) {

                //데이터 받아오기
                val dataModel = dataSnapshot.getValue(BoardModel::class.java)

                // 레이아읏과 연결
                binding.titleArea.text = dataModel!!.title   // titleArea와 BoardModel 연결
                binding.textArea.text = dataModel!!.content  // textArea와 BoardModel 연결
                binding.timeArea.text = dataModel!!.time     // timeArea와 BoardModel 연결
            }

            override fun onCancelled(databaseError: DatabaseError) {
                // Getting Post failed, log a message
                Log.w(TAG, "loadPost:onCancelled", databaseError.toException())
            }
        }
        // board안에있는 key값을 가져오기
        FBRef.boardRef.child(key).addValueEventListener(postListener)

    }
}

BoardInsideActivity.kt

 

 

그리고 데이터를 거꾸로해서 최신순이 위로가도록 배치했기 때문에, 키순서도 거꾸로해야지 눌렀을때 해당하는 값이 나올수있다

아래 코드를 추가해주자

// 키 순서 최신순
boardKeyList.reverse()

TalkFragment.kt

 

 

이렇게하면 아이템뷰를 클릭했을때 해당 title,content,time이 잘 보여지는것을 확인할수있다

이렇게 두가지 방법으로 코드를 짜봤다