wnsdudSoftkim / Learning-Android

study Android based on Kotlin
2 stars 0 forks source link

2일차 (Context , Fragment 동적으로 붙이기 , Tablayout , ViewPager , Recyclerview)) #7

Open wnsdudSoftkim opened 4 years ago

wnsdudSoftkim commented 4 years ago

image

Fragment 를 동적으로 가져온다는건 xml 부분에서 fragment 태그를 쓰지않고 kt 에서 바로 fragment 를 붙인다는 뜻 . 대표적인게 Tablayout , viewPager image 여기서 Tablayout 을 보면 Tablayout 만을 구현했을때 탭을 눌렀을때 화면 이동이 되는 것을 볼 수 있다 . 하지만 여러 앱들의 기능을 보면 슬라이드를 했을때도 탭이 이동하게 끔 하기 위해서 Tablayout 과 슬라이드를 위한 Viewpager 을 같이 연동해서 구현한다,

wnsdudSoftkim commented 4 years ago

.activity_sample5_1_customtab.xml

<?xml version="1.0" encoding="utf-8"?>
<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:orientation="vertical"
    android:layout_height="match_parent"
    tools:context=".sample5_1_customtab">
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout3"
        android:layout_width="match_parent"
        android:layout_height="50dp"/>
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager3"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

.sample5_1customtab.kt

package com.example.myapplication

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.widget.ImageView
import android.widget.TextView
import kotlinx.android.synthetic.main.activity_sample5_1_customtab.*
import kotlinx.android.synthetic.main.custom_tab.view.*

class sample5_1_customtab : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample5_1_customtab)
        initView()

    }
    //여기서 반환값을 View를 명시해줌.
    fun createView(tabName:String): View {
        val tabView  = LayoutInflater.from(this).inflate(R.layout.custom_tab,null)
        tabView.text_custom.text = tabName
        when(tabName) {
            "홈" -> {
                tabView.image_custom.setImageResource(R.drawable.ic_baseline_home_24)
            }
            "정보" -> {
                tabView.image_custom.setImageResource(R.drawable.ic_baseline_person_24)
            }
            else -> {
                return tabView
            }
        }
        return tabView
    }
    fun initView() {
        val fragment1 = sample4fragment()
        val fragment2 = sample4fragmenttwo()
        val adapter = pagerAdapter(supportFragmentManager)
        adapter.addItems(fragment1)
        adapter.addItems(fragment2)
        viewPager3.adapter = adapter
        tabLayout3.setupWithViewPager(viewPager3)
        tabLayout3.getTabAt(0)?.setCustomView(createView("홈"))
        tabLayout3.getTabAt(1)?.setCustomView(createView("정보"))
    }

}
class pagerAdapter(fragmentmanager :FragmentManager):FragmentStatePagerAdapter(fragmentmanager) {
   private val fragments : ArrayList<Fragment> = ArrayList()
    override fun getItem(position: Int): Fragment {
        return fragments[position]
    }

    override fun getCount(): Int {
        return fragments.size
    }
    fun addItems(item:Fragment){
        fragments.add(item)
    }
}

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:orientation="vertical" android:layout_height="match_parent">

<ImageView
    android:id="@+id/image_custom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:src="@drawable/ic_baseline_home_24"/>
<TextView
    android:id="@+id/text_custom"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Home"
    android:layout_gravity="center_horizontal"/>

package com.example.myapplication

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentStatePagerAdapter
import kotlinx.android.synthetic.main.activity_sample5_view_pager.*
import kotlinx.android.synthetic.main.activity_sample5_view_pager.view.*

class sample5_viewPager : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample5_view_pager)

        //sample4 Fragment를 불러와서 사용
        val fragmentOne = sample4fragment()
        val adapters = pagerAdapter(supportFragmentManager)
        //넣어주고
        adapters.addItems(fragmentOne)
        //adapter에 연동시켜줌
        viewPager.adapter = adapters
        //탭 레이아웃에도 연동시켜줌
        tabLayout.setupWithViewPager(viewPager)
        //Tab의 0번째 인덱스를 가져와서 aa 라는 이름을 지어줌
        tabLayout.getTabAt(0)?.setText("aa")
        //응용해서 setCostomView로 할수 있음

    }
    //PagerAdapter 구현
    //fragment를 하나씩 리스트에 넣어줌.
    private inner class pagerAdapter(fragmentmanager :FragmentManager):FragmentStatePagerAdapter(fragmentmanager) {
       private val fragments : ArrayList<Fragment> = ArrayList()
        override fun getItem(position: Int): Fragment {
            return fragments[position]
        }

        override fun getCount(): Int {
            return fragments.size
        }
        fun addItems(item:Fragment){
            fragments.add(item)
        }
    }

}

//tablayout implementation 'com.google.android.material:material:1.1.0'

wnsdudSoftkim commented 4 years ago

image

wnsdudSoftkim commented 4 years ago
  1. RecyclerView를 쓰기위해 외부 라이브러리 가져온다
//RecyclerView
  implementation 'com.android.support:recyclerview-v7:28.0.0'
  1. RycylerView 또한 Adapter 를 통해 각 아이템에 대한 접근을 해준다.
class RecyclerAdapter(
    val itemList: ArrayList<sample6data>,
    val inflater: LayoutInflater
    //반환하는건 ViewHolder 객체라고 알고있자.
) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
    //여기서 viewHolder는 필수 구현요소임.
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        //여기엔 아이템 객체가 들어있음 !
        val title =view.findViewById<TextView>(R.id.text_title)
        val description = view.findViewById<TextView>(R.id.text_description)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        //여기서 아이템 뷰를 불러와서 뷰 홀더에 넣어줌.
        return ViewHolder(inflater.inflate(R.layout.sample6item, parent, false))

    }

    override fun getItemCount(): Int {
        //총 아이템 크기
        return itemList.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        //아이템 하나에 대한 접근
        holder.title.setText(itemList[position].title)
        holder.description.setText(itemList[position].description)
    }
}
  1. onCreate 메소드 안에서 xml 과 adapter를 연동시켜준다

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample6_recycler_view)
        //1부터 10까지 들어있는 데이터 를 만들어줌.
        for (i in 0 until 10) {
            val sampledata = sample6data("" + i, "" + i)
            data.add(sampledata)
         }
        //adapter 로 데이터와 Recylcer뷰를 연동시켜줌
        val adapter = RecyclerAdapter(viewModel.data, LayoutInflater.from(this))
        recycler_view.adapter = adapter
        recycler_view.layoutManager = LinearLayoutManager(this)
    
    }
wnsdudSoftkim commented 4 years ago

ViewModel과 LiveData에 관하여 image

1.ViewModel 을 쓰기 위해 외부 라이브러리 가져옴

 implementation "androidx.fragment:fragment-ktx:1.2.4"

 kotlinOptions {
        jvmTarget = "1.8"
      }

.MyViewModel.kt

package com.example.myapplication

import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel

class MyViewModel: ViewModel() {
    //데이터와 Livedata 선언
    val data =ArrayList<sample6data>()
    val Livedata = MutableLiveData<ArrayList<sample6data>>()

    fun mydata() {
        data.clear()
        for (i in 0 until 10) {
            val sampledata = sample6data("" + i, "" + i)
            data.add(sampledata)
        }
        Livedata.value = data

    }
}

ViewModel 을 씀으로써 RecyclerView에서의 데이터 관련부분은 ViewModel 로 보낸다.

package com.example.myapplication

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.activity.viewModels
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import kotlinx.android.synthetic.main.activity_sample6_recycler_view.*

class sample6RecyclerView : AppCompatActivity() {
    //뷰모델을 가져옴
    val viewModel : MyViewModel by viewModels()
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_sample6_recycler_view)
        //여기서 viewModel 의 mydata를 가져온 이유는 이 데이터를
        // 가져와야지만 RecyclerView 안에 데이터가 들어가니까 맨 위에 선언해줌.

        viewModel.mydata()
        //1부터 10까지 들어있는 데이터 를 만들어줌.
//        for (i in 0 until 10) {
//            val sampledata = sample6data("" + i, "" + i)
//            data.add(sampledata)
        //adapter 로 데이터와 Recylcer뷰를 연동시켜줌
        val adapter = RecyclerAdapter(viewModel.data, LayoutInflater.from(this))
        recycler_view.adapter = adapter
        recycler_view.layoutManager = LinearLayoutManager(this)
        viewModel.Livedata.observe(this, Observer {
            //여기에 수시로 업데이트 할 데이터 넣어줌
        })
    }
}

class RecyclerAdapter(
    val itemList: ArrayList<sample6data>,
    val inflater: LayoutInflater
    //반환하는건 ViewHolder 객체라고 알고있자.
) : RecyclerView.Adapter<RecyclerAdapter.ViewHolder>() {
    //여기서 viewHolder는 필수 구현요소임.
    inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        //여기엔 아이템 객체가 들어있음 !
        val title =view.findViewById<TextView>(R.id.text_title)
        val description = view.findViewById<TextView>(R.id.text_description)
    }

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        //여기서 아이템 뷰를 불러와서 뷰 홀더에 넣어줌.
        return ViewHolder(inflater.inflate(R.layout.sample6item, parent, false))

    }

    override fun getItemCount(): Int {
        //총 아이템 크기
        return itemList.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        //아이템 하나에 대한 접근
        holder.title.setText(itemList[position].title)
        holder.description.setText(itemList[position].description)
    }
}

여기서 질문 = 아이템 하나에 대한 삭제 메소드를 구현 하고 싶을때 그 삭제 메소드는 어디에 구현을 해야하는가 ????

hufsicehwang commented 4 years ago

정말 좋은 자료에요!!b

jun80808 commented 4 years ago

wow!