[1] Menu
1. 메뉴 생성 예제
1) menu resource 생성
menu_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_drawer_1"
android:icon="@android:drawable/ic_menu_directions"
android:title="내가 본 레시피"/>
<item
android:id="@+id/menu_drawer_2"
android:icon="@android:drawable/ic_menu_myplaces"
android:title="스크랩한 레시피"/>
<item
android:id="@+id/menu_drawer_3"
android:icon="@android:drawable/ic_menu_camera"
android:title="리뷰한 레시피"/>
<item
android:id="@+id/menu_drawer_4"
android:icon="@android:drawable/ic_menu_help"
android:title="레시피노트"/>
<item
android:id="@+id/menu_drawer_5"
android:icon="@android:drawable/ic_menu_today"
android:title="레시피 공유"/>
</menu>
2) Drawer Layout 생성 (메인 화면)
activity_drawer_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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:id="@+id/root_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".drawer.DrawerTest">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/drawertxt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Navigation View Test"
android:textSize="30sp"
android:textStyle="bold"/>
</LinearLayout>
<com.google.android.material.navigation.NavigationView
android:id="@+id/main_drawer_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:headerLayout="@layout/navigation_header"
app:menu="@menu/menu_drawer"
android:layout_gravity="start"/>
</androidx.drawerlayout.widget.DrawerLayout>
navigation_header.xml
(activity_drawer_test.xml 의 NavigationView의 속성 중 app:headerLayout에 들어가는 레이아웃)
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="250dp"
android:background="@drawable/lee"
android:gravity="bottom"
android:paddingLeft="16dp"
android:paddingBottom="16dp"
android:text="Hello Android"
android:textColor="@android:color/black"
android:textSize="20dp"
android:textStyle="bold" />
3) themes.xml 리소스파일에 item 추가
themes.xml
4) 메뉴에 액션 추가
DrawerTest.kt
package com.example.fragment.drawer
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.MenuItem
import android.widget.Toast
import androidx.appcompat.app.ActionBarDrawerToggle
import androidx.drawerlayout.widget.DrawerLayout
import com.example.fragment.R
import kotlinx.android.synthetic.main.activity_drawer_test.*
class DrawerTest : AppCompatActivity() {
var drawerLayout:DrawerLayout? = null
var actionBarDrawerToggle:ActionBarDrawerToggle? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_drawer_test)
// 액션바에 출력되는 타이틀을 출력되지 않도록 정의
supportActionBar?.setDisplayShowTitleEnabled(false)
//root_drawer
// 문자열은 화면에 출력할 문자열과 관련없이 drawer가 열린 상태, 닫힌 상태냐를 표현하기 위한 문자열
actionBarDrawerToggle = ActionBarDrawerToggle(this, root_drawer, R.string.drawer_open, R.string.drawer_close)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
actionBarDrawerToggle?.syncState()
main_drawer_view.setNavigationItemSelectedListener { item ->
val id = item.itemId
if(id == R.id.menu_drawer_1){
showToast("내가 본 레시피 메뉴가 선택됨")
}
false
}
}
// 실제로 NavigationView가 열리거나 닫히도록 하려면 onOptionsItemSelected 메소드를 반드시 오버라이딩 해야한다.
// 이 함수를 사용하는 이유는 ActionBarDrawerToggle 아이콘 클릭하는 것이 메뉴 이벤트로 처리되기 때문에
// 이벤트 로직에 벗어나도록 코드 구현
override fun onOptionsItemSelected(item: MenuItem): Boolean {
if(actionBarDrawerToggle?.onOptionsItemSelected(item)==true){
showToast("눌림")
return false // 일반 메뉴처리를 계속 하려면 false를 반환하고 사용하려면 true 반환
}
return super.onOptionsItemSelected(item)
}
fun showToast(msg:String){
Toast.makeText(this, msg, Toast.LENGTH_SHORT).show()
}
}
[2] Tab
1. Tab 생성 예제
activity_tab_test.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable">
<com.google.android.material.tabs.TabItem
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="가입" />
<com.google.android.material.tabs.TabItem
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="로그인" />
<com.google.android.material.tabs.TabItem
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="마이페이지" />
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:id="@+id/linear1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"/>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
TabTest.kt
package com.example.fragment.tab
import android.graphics.Color
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import com.example.fragment.R
import com.example.fragment.fragment.LoginFragment
import com.example.fragment.fragment.MyPageFragment
import com.example.fragment.fragment.RegisterFragment
import com.google.android.material.tabs.TabLayout
import kotlinx.android.synthetic.main.activity_tab_test.*
class TabTest : AppCompatActivity() {
var view1 = RegisterFragment()
var view2 = LoginFragment()
var view3 = MyPageFragment()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tab_test)
// 탭 추가
tabs.addTab(tabs.newTab().setText("설정"))
//tabs.setTabTextColors(Color.RED,Color.BLUE) // 탭 텍스트 색 변경
// 처음 실행할 때 보여줄 프레그먼트 지정
supportFragmentManager.beginTransaction().replace(R.id.linear1,view1).commit()
// 탭에 이벤트 연결
tabs.addOnTabSelectedListener(object:TabLayout.OnTabSelectedListener{
// 탭이 선택될 때 호출되는 메소드
override fun onTabSelected(tab: TabLayout.Tab?) {
val position = tab?.position // 탭의 순서를 받아오기
var fragment: Fragment? = null
when(position){
0 -> fragment = view1
1 -> fragment = view2
2 -> fragment = view3
}
// 탭을 선택할 때 정의된 프레그먼트 객체가 show되도록 연결
supportFragmentManager.beginTransaction().replace(R.id.linear1,fragment!!).commit()
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
}
override fun onTabReselected(tab: TabLayout.Tab?) {
}
})
}
}
- 나머지 코드는 파일로 대체
[3] View Pager
1. ViewPager 구버전(?) 사용 예제
activity_view_pager_test.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:layout_height="match_parent"
android:orientation="vertical"
tools:context=".viewpager.ViewPagerTestActivity">
<TextView
android:id="@+id/pager_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<view
android:id="@+id/pager1"
class="androidx.viewpager.widget.ViewPager"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
ViewPagerTest.kt
package com.example.fragment.viewpager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
import androidx.viewpager.widget.PagerAdapter
import androidx.viewpager.widget.ViewPager
import com.example.fragment.R
import kotlinx.android.synthetic.main.activity_view_pager_test.*
/*
화면 전환을 위해서 ViewPager를 사용하는 경우(ListView와 동일)
1. ViewPager에 담을 View를 데이터(ViewPager에 담을 View객체 - View, Fragment)를 정의
2. Adapter 커스터마이징 - ViewPager에 보여주는 방식이나 ViewPager에 담을 뷰들이 달라지고 각각 동작할 수 있도록 해야 하므로 Adapter를 상속 받아서 작업
=> PagerAdapter
3. ViewPager에 Adapter 연결
*/
class ViewPagerTestActivity : AppCompatActivity() {
val viewlist = ArrayList<View>() // ViewPager에 담을 뷰들을 보관할 자료구조
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_pager_test)
// 1. ViewPager에 담을 View객체를 생성
// => root를 레이아웃을 지정하면 그 레이아웃에 가서 추가된다.
val view1 = layoutInflater.inflate(R.layout.register, null)
val view2 = layoutInflater.inflate(R.layout.login, null)
val view3 = layoutInflater.inflate(R.layout.mypage, null)
viewlist.add(view1)
viewlist.add(view2)
viewlist.add(view3)
// 2. Adapter를 커스터마이징(Adapter를 상속받아서 구현) - 익명으로 구현
val my_viewpager_adapter = object:PagerAdapter(){
// ViewPager를 통해 보여줄 뷰의 갯수를 리턴
override fun getCount(): Int {
return viewlist.size
}
// ViewPager에 보여줄 뷰를 등록 - 뷰페이저에서 뷰가 전환될 때마다 보여줄 뷰를 만들어서 리턴
override fun instantiateItem(container: ViewGroup, position: Int): Any {
pager1.addView(viewlist[position])
return viewlist[position]
}
// instantiateItem에서 만든 뷰를 실제 사용할 것인지 여부를 결정 - 매개변수로 전달된 뷰들끼리 비교
// 첫번째 매개변수로 전달된 뷰객체와 instantiateItem 메소드를 호출한 후 리턴되는 객체를 비교
// `object` => 코틀린에서 키워드를 식별자로 사용할 때 ``로 묶어준다.
override fun isViewFromObject(view: View, `object`: Any): Boolean {
return view == `object`
}
// ViewPager에서 View가 사라질 때 뷰를 제거하는 작업을 수행
override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {
pager1.removeView(`object` as View)
}
}// end Adapter
// 3. ViewPager에 어댑터 연결
pager1.adapter = my_viewpager_adapter
// ViewPager에 이벤트 연결하기
val listener1 = object: ViewPager.OnPageChangeListener{
// 페이지 스크롤이 끝났을 때 호출되는 메소드
override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) {
pager_text.text = "${position}번재 뷰가 선택됨"
}
// 페이지를 선택했을 때 호출되는 메소드
override fun onPageSelected(position: Int) {
}
// 페이지 상태가 변경되었을 때 호출되는 메소드
override fun onPageScrollStateChanged(state: Int) {
}
}
pager1.addOnPageChangeListener(listener1)
}
}
2. ViewPager2 사용 예제
- ViewPager 보다 간단하게 작성 가능 - 동작은 동일
activity_view_pager2_test.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:layout_height="match_parent"
android:orientation="vertical"
tools:context=".viewpager.ViewPager2TestActivity">
<TextView
android:id="@+id/pager_text2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Info"
android:textAppearance="@style/TextAppearance.AppCompat.Medium" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/pager2"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
ViewPager2TestActivity.kt
package com.example.fragment.viewpager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.fragment.R
import com.example.fragment.fragment.LoginFragment
import com.example.fragment.fragment.MyPageFragment
import com.example.fragment.fragment.RegisterFragment
import kotlinx.android.synthetic.main.activity_view_pager2_test.*
// ViewPager2를 이용할 때 FragmentActivity를 상속받아 작업하기
class ViewPager2TestActivity : FragmentActivity() {
var view1 = RegisterFragment()
var view2 = LoginFragment()
var view3 = MyPageFragment()
val fragmentlist = ArrayList<Fragment>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_view_pager2_test)
// 1. ViewPager2에 연결될 프레그먼트 준비
fragmentlist.add(view1)
fragmentlist.add(view2)
fragmentlist.add(view3)
// 2. ViewPager2도 어댑터가 있어야 한다. - FragmentStateAdapter
// FragmentStateAdapter가 커스터마이징될 때 FragmentActivity를 요구하기 때문에 액티비티는 FragmentActivity 하위로 작업
val my_viewpager2_adapter = object:FragmentStateAdapter(this){
// viewpager2를 통해 보여줄 프레그먼트 갯수
override fun getItemCount(): Int {
return fragmentlist.size
}
// 보여줄 프레그먼트만 리턴
override fun createFragment(position: Int): Fragment {
return fragmentlist[position]
}
}
// 3. 뷰페이저2에 어댑터 연결
pager2.adapter = my_viewpager2_adapter
}
}
[4] View Pager와 Tab 연결
1. ViewPager2와 Tab 연결 예제
1) Fragment
subfragment_view.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/subfragment_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="fragment"
android:textAppearance="@style/TextAppearance.AppCompat.Large"/>
</LinearLayout>
SubFragment.kt
package com.example.fragment.tab
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.fragment.R
import kotlinx.android.synthetic.main.subfragment_view.*
class SubFragment: Fragment {
lateinit var title:String // title 변수를 선언하고 바로 초기화하지 않고 뒤에서 초기화하겠다는 의미
constructor(title:String){
this.title = title
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.subfragment_view,null,false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
subfragment_txt.text = title
}
}
2) 메인 Activity
activity_tab_test2.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/appbar"
android:layout_height="wrap_content"
android:layout_width="match_parent">
<androidx.appcompat.widget.Toolbar
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"/>
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:tabMode="scrollable">
</com.google.android.material.tabs.TabLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/tab_viewpager2"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
TabTest2.kt
package com.example.fragment.tab
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.viewpager2.adapter.FragmentStateAdapter
import com.example.fragment.R
import com.google.android.material.tabs.TabLayoutMediator
import kotlinx.android.synthetic.main.activity_tab_test2.*
class TabTest2 : FragmentActivity() {
var fragmentlist = ArrayList<Fragment>()
// 탭 문자열을 담을 ArrayList
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_tab_test2)
// 동일한 프레그먼트를 만들어서 작업하는 거라면 만들어질 프레그먼트를 담을 프레그먼트 객체를 준비하고 작업
for(i in 0..9){
val sub = SubFragment("${i}번째 프레그먼트")
fragmentlist.add(sub)
}
val myadapter = object:FragmentStateAdapter(this){
override fun getItemCount(): Int {
return fragmentlist.size
}
override fun createFragment(position: Int): Fragment {
return fragmentlist[position]
}
}
tab_viewpager2.adapter = myadapter
// 탭과 뷰페이저를 연결 - 연결할 탭과 뷰페이저를 이용해서 TabLayoutMediator 객체를 정의
TabLayoutMediator(tabs2, tab_viewpager2){tab, position->
tab.text = "탭$position" // 탭의 이름
}.attach()
}
}
- 끝 -
'프로젝트형 IoT 서비스 개발 4회차 > 3. 게이트웨이 디바이스 제어' 카테고리의 다른 글
[Day74] 2022-05-11(수) Android13 - Thread - 김서연 강사님 (5) | 2022.05.11 |
---|---|
[Day72] 2022-05-09(월) Android11 - Fragment2 - 김서연 강사님 (0) | 2022.05.09 |
[Day71] 2022-05-07(토) Android10 - Fragment1 - 김서연 강사님 (0) | 2022.05.09 |
[Day71] 2022-05-07(토) Android9 - Intent2(Activity2 - Launcher) - 김서연 강사님 (0) | 2022.05.07 |
[Day70] 2022-05-06(금) Android8 - Intent1(Activity1) - 김서연 강사님 (0) | 2022.05.06 |