탭을 누를 때마다 아래 화면이 마치 페이지가 넘어가듯이 변하는 것을 ViewPager 를 이용해 구현이 가능하다.
예전에 사용하던 방식에서 계속 새로운 기능으로 개선이 되면서 ViewPager를 이용한 TabLayout 을 연동하는 것이 가장 좋은 방법이다.
material Design에서 제공하는 tabLayout 을 이용하는 방법으로 된 예제다.
https://www.youtube.com/watch?v=YWjyAfEacT8 유투브 동영상 강의 보고 테스트한 걸 적어두었다. (2020.3.27)
그런데 제대로 된 코드가 아니라서 새롭게 수정 구현하고 적어둔다.(Upated 2020.4.26)
앱 gradle 에 라이브러리 추가하기
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'com.google.android.material:material:1.1.0' }
|
TabLayout 사용하기
검색창에서 tab 을 입력하면 tabLayout 이 나온다. 마우스로 끌어다가 1번과 같이 놓는다.
material Design 에서 제공하는 tabLayout 이 추가된다.
하는 방법은 https://www.youtube.com/watch?v=YWjyAfEacT8 을 참조하면 된다.
ConstraintLayout 작성하는 방법에 대한 설명이라고 보면 된다.
https://stackoverflow.com/questions/31640563/how-do-i-change-a-tab-background-color-when-using-tablayout
에서 선택된 아이템 배경색을 지정하는 걸 참조해서 구현한다.
android:layout_marginTop="40dp" 으로 해줘야만 공간이 제대로 나오는 버그(?)가 있어서
LinearLayout 으로 변경해서 해결했다.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout 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=".MainActivity">
<com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="40dp" app:tabTextColor="@color/colorDarkGray" app:tabSelectedTextColor="@color/colorWhite" app:layout_collapseMode="pin" app:tabGravity="fill" app:tabBackground="@drawable/tab_color_selector" app:layout_constraintBottom_toTopOf="@+id/vp_layout" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Monday" />
<com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tuesday" />
<com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Wednesday" /> </com.google.android.material.tabs.TabLayout>
<androidx.constraintlayout.widget.ConstraintLayout android:id="@+id/vp_layout" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tab_layout">
<androidx.viewpager.widget.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
|
최근에는 ViewPager2 를 사용하라고 나오는 거 같은데 이건 나중에 테스트해볼 예정이다.
ViewPager 영역에 표시될 Fragment Layout 파일을 추가한다. 3개, 5개는 정하기 나름이다.
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="프레그먼트1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout> |
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="프레그먼트2" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
|
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent">
<TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="프레그먼트3" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
|
Fragment1.java 파일
- Activity 에서 전달받은 데이터를 Fragment 에서 받아서 처리하는 코드를 추가했다.
import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup;
import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment;
public class Fragment1 extends Fragment { private View view; private String parameter;
public static Fragment1 newInstance(String parameter){ Fragment1 fragment1 = new Fragment1(); Bundle args = new Bundle(); //Use bundle to pass data args.putString("parameter", parameter); instance.setArguments(args); //Finally set argument bundle to fragment return instance; }
@Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (getArguments() != null) { parameter = getArguments().getString("parameter"); Log.e("FragParameter", parameter); } }
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_1,container,false); return view; }
@Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); } }
|
public class Fragment2 extends Fragment { private View view;
public static Fragment2 newInstance(){ Fragment2 fragment2 = new Fragment2(); return fragment2; }
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_2,container,false); return view; } } |
public class Fragment3 extends Fragment { private View view;
public static Fragment3 newInstance(){ Fragment3 fragment3 = new Fragment3(); return fragment3; }
@Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.fragment_3,container,false); return view; } } |
ViewPagerAdapter.java
import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter;
import java.util.ArrayList; import java.util.List;
class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> mFragmentList = new ArrayList<>(); private final List<String> mFragTitleList = new ArrayList<>();
public ViewPagerAdapter(FragmentManager manager) { super(manager); }
@Override public Fragment getItem(int position) { return mFragmentList.get(position); }
@Override public int getCount() { return mFragmentList.size(); }
public void addFrag(Fragment fragment, String title) { mFragmentList.add(fragment); mFragTitleList.add(title); }
@Override public CharSequence getPageTitle(int position) { return mFragTitleList.get(position); } }
|
MainActivity.java
import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.FragmentPagerAdapter; import androidx.viewpager.widget.ViewPager;
import android.os.Bundle;
import com.google.android.material.tabs.TabLayout;
public class MainActivity extends AppCompatActivity { private ViewPager viewPager; private ViewPagerAdapter adapter; private TabLayout tabLayout;
String code;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
code = getIntent().getExtras().getString("code"); Log.e("MainActivityCode",code);
Fragment frag1 = new Fragment1().newInstance(code);
viewPager = findViewById(R.id.viewPager); tabLayout = findViewById(R.id.tab_layout); adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFrag(frag1, "Web"); adapter.addFrag(new Fragment2(), "사랑"); adapter.addFrag(new Fragment3(), "우정"); viewPager.setAdapter(adapter); tabLayout.setupWithViewPager(viewPager); } }
|
여기까지 하면 잘 동작할 것이다.
참고하면 좋을 자료
출처 : https://guides.codepath.com/android/viewpager-with-fragmentpageradapter
public class FirstFragment extends Fragment { // Store instance variables private String title; private int page;
// newInstance constructor for creating fragment with arguments public static FirstFragment newInstance(int page, String title) { FirstFragment fragmentFirst = new FirstFragment(); Bundle args = new Bundle(); args.putInt("someInt", page); args.putString("someTitle", title); fragmentFirst.setArguments(args); return fragmentFirst; }
// Store instance variables based on arguments passed @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); page = getArguments().getInt("someInt", 0); title = getArguments().getString("someTitle"); }
// Inflate the view for the fragment based on layout XML @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_first, container, false); TextView tvLabel = (TextView) view.findViewById(R.id.tvLabel); tvLabel.setText(page + " -- " + title); return view; } } |