이 포스팅은 아래 구글 코드랩을 개인 학습용으로 정리한 글입니다.
ScrollView:
RecyclerView:
Instead of creating a View for each item that may or may not be visible on the screen,
RecyclerView creates a limited number of list items and reuses them for visible content.
➕ 이 코드랩에서는 Basic Activity 템플릿을 이용해 새 프로젝트를 시작하였지만,
안드로이드 스튜디오의 새로 업데이트된 Basic Activity 템플릿은 코드랩과 상이함
-> 따라서 Empty Activity로 진행하였음
class MainActivity : AppCompatActivity() {
private val mWordList : MutableList<String> = mutableListOf()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
for(i in 0 until 20){
mWordList.add("Word $i")
}
}
}
➕ activity_main.xml에 floating action button 추가
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
need data to display
-> mWordList
need a recyclerView
-> the scrolling list that contains the list items
need a Layout for one item of data
need a layout manager
-> RecyclerView.LayoutManager
-> handles the hierarchy and layout of View elements
RecyclerView requires an explicit layout manager
-> to manage the arrangement of list items contained within it.
-> layout could be vertical, horizontal, or a grid
need A ViewHolder inside your adapter
-> contains the View information
need an adapter
-> RecyclerView.Adapter
-> connects your data to the RecyclerView
-> prepares the data in a RecyclerView.ViewHolder
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent">
</androidx.recyclerview.widget.RecyclerView>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="6dp">
<TextView
android:id="@+id/word"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="24sp"
android:textStyle="bold"/>
</LinearLayout>
You can use styles to allow elements to share groups of display attributes
TextView 우클릭 Refactor > Extract > Style
-> Extract Android Style dialog appears
-> Name your style
-> leave all other options selected
-> Select the Launch ‘Use Style Where Possible' option
-> click OK.
When prompted, apply the style to the Whole Project
<TextView
android:id="@+id/word"
style="@style/word_title" />
<resources>
<style name="word_title">
<item name="android:layout_width">match_parent</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:textSize">24sp</item>
<item name="android:textStyle">bold</item>
</style>
</resources>
Android uses adapters to connect data with View items in a list.
To connect data with View items, the adapter needs to know about the View items
-> The adapter uses a ViewHolder that describes a View item and its position within the RecyclerView
class WordListAdapter() : RecyclerView.Adapter<WordListAdapter.WordViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder {
TODO("Not yet implemented")
}
override fun getItemCount(): Int {
TODO("Not yet implemented")
}
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
TODO("Not yet implemented")
}
class WordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
lateinit var wordItemView : TextView
lateinit var mAdapter : WordListAdapter
init{
wordItemView = itemView.findViewById(R.id.word)
}
constructor(itemView: View, adapter: WordListAdapter) : this(itemView){
this.mAdapter = adapter
}
}
}
class WordListAdapter() : RecyclerView.Adapter<WordListAdapter.WordViewHolder>() {
lateinit var mWordList : MutableList<String>
lateinit var mInflater: LayoutInflater
constructor(context : Context, wordList: MutableList<String>) : this() {
mWordList = wordList
mInflater = LayoutInflater.from(context)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): WordViewHolder {
val mItemView = mInflater.inflate(R.layout.wordlist_item, parent, false)
return WordViewHolder(mItemView, this)
}
override fun getItemCount(): Int {
return mWordList.size
}
override fun onBindViewHolder(holder: WordViewHolder, position: Int) {
val mCurrentWord : String = mWordList[position]
holder.wordItemView.text = mCurrentWord
}
...
}
class MainActivity : AppCompatActivity() {
private val mWordList : MutableList<String> = mutableListOf()
lateinit var mRecyclerView: RecyclerView
lateinit var mAdapter: WordListAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
...
mRecyclerView = findViewById(R.id.recyclerview)
mAdapter = WordListAdapter(this, mWordList)
mRecyclerView.adapter = mAdapter
mRecyclerView.layoutManager = LinearLayoutManager(this)
}
}
inner class WordViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
lateinit var wordItemView : TextView
lateinit var mAdapter : WordListAdapter
constructor(itemView: View, adapter: WordListAdapter) : this(itemView){
wordItemView = itemView.findViewById(R.id.word)
this.mAdapter = adapter
//Connect the onClickListener with the View
itemView.setOnClickListener(this)
}
override fun onClick(p0: View?) {
val mPosition = layoutPosition
val element : String = mWordList[mPosition]
mWordList[mPosition] = "CLicked $element"
// Notify the adapter that the data has changed so it can
// update the RecyclerView to display the data.
mAdapter.notifyDataSetChanged()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
...
mRecyclerView = findViewById(R.id.recyclerview)
mAdapter = WordListAdapter(this, mWordList)
mRecyclerView.adapter = mAdapter
mRecyclerView.layoutManager = LinearLayoutManager(this)
val fab = findViewById<FloatingActionButton>(R.id.fab)
fab.apply{
setImageResource(R.drawable.ic_add_for_fab)
setOnClickListener {
val wordListSize : Int = mWordList.size
mWordList.add("+ Word $wordListSize")
(mRecyclerView.adapter as WordListAdapter).notifyItemInserted(wordListSize)
mRecyclerView.smoothScrollToPosition(wordListSize)
}
}
}