TabLayout with ViewPager2 in Android
Author: Deep Singh | Category: Android, Java, UI Components
Introduction
ViewPager2 is an enhanced version of the classic ViewPager view in Android. It provides improved performance, vertical paging support, RTL (Right-to-Left) layout support, and seamless integration with TabLayout via TabLayoutMediator.
Advantages of ViewPager2
-
Vertical paging support: ViewPager2 supports vertical paging, meaning you can scroll pages in a vertical direction.
To enable vertical paging in XML, use:
android:orientation="vertical" -
Enable vertical paging via Java code:
viewPager.setOrientation(ViewPager2.ORIENTATION_VERTICAL); -
RTL (Right-To-Left) paging support: ViewPager2 supports RTL paging out of the box.
RTL paging is enabled automatically based on locale, but you can also enable it manually:
android:layoutDirection="rtl" -
Enable RTL direction via Java code:
viewPager.setLayoutDirection(LAYOUT_DIRECTION_RTL); -
Fragment collection updates: ViewPager2 supports paging through a modified collection of fragments, calling
notifyDatasetChanged()to update the UI when your fragment collection changes.
Complete Example of ViewPager2 with TabLayout
The following example demonstrates a working implementation of TabLayout + ViewPager2 with three tabs: Login, Register, and Extra.
activity_main.xml
<LinearLayout 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"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="TabLayout with ViewPager2"
app:titleTextColor="@color/white" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tabbed"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" />
</LinearLayout>
extra.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Extra"
android:textSize="30sp" />
</RelativeLayout>
register.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Register"
android:textSize="30sp" />
</RelativeLayout>
login.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="Login"
android:textSize="30sp" />
</RelativeLayout>
MainActivity.java
package com.example.firstapp;
import android.annotation.SuppressLint;
import android.os.Build;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.viewpager2.adapter.FragmentStateAdapter;
import androidx.viewpager2.widget.ViewPager2;
import com.google.android.material.tabs.TabLayout;
import com.google.android.material.tabs.TabLayoutMediator;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
// Create a fragments collection
List<Fragment> fragments = new ArrayList<>();
// Create a titles collection
List<String> titles = new ArrayList<>();
@SuppressLint("WrongConstant")
@RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Add fragments into the fragment collection
fragments.add(new LoginFragment());
fragments.add(new RegisterFragment());
fragments.add(new ExtraFragment());
// Add titles into the title collection
titles.add("Login");
titles.add("Register");
titles.add("Extra");
TabLayout tabLayout = findViewById(R.id.tabbed);
ViewPager2 viewPager = findViewById(R.id.viewpager);
// Optional: enable vertical paging
// viewPager.setOrientation(ViewPager2.ORIENTATION_VERTICAL);
// Optional: enable RTL layout direction
// viewPager.setLayoutDirection(LAYOUT_DIRECTION_RTL);
viewPager.setAdapter(new MyWhatsAppTab(this));
// TabLayoutMediator is a callback interface that must be implemented
// to set the text and styling of newly created tabs.
// It links TabLayout and ViewPager2 together.
// Must be called after ViewPager2 has an adapter set.
new TabLayoutMediator(tabLayout, viewPager,
(tab, position) -> tab.setText(titles.get(position))
).attach();
}
class MyWhatsAppTab extends FragmentStateAdapter {
public MyWhatsAppTab(@NonNull @NotNull FragmentActivity fragmentActivity) {
super(fragmentActivity);
}
@NonNull
@NotNull
@Override
public Fragment createFragment(int position) {
return fragments.get(position);
}
@Override
public int getItemCount() {
return fragments.size();
}
}
}
RegisterFragment.java
package com.example.firstapp;
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;
import org.jetbrains.annotations.NotNull;
public class RegisterFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull @NotNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.register, container, false);
}
}
ExtraFragment.java
package com.example.firstapp;
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;
import org.jetbrains.annotations.NotNull;
public class ExtraFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull @NotNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.extra, container, false);
}
}
LoginFragment.java
package com.example.firstapp;
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;
import org.jetbrains.annotations.NotNull;
public class LoginFragment extends Fragment {
@Nullable
@Override
public View onCreateView(@NonNull @NotNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.login, container, false);
}
}
Conclusion
ViewPager2 is a powerful and modern replacement for the deprecated ViewPager. Combined with TabLayout and TabLayoutMediator, it provides a clean, flexible way to build swipeable tabbed interfaces in Android.
Key takeaways from this tutorial:
- Vertical paging is natively supported via
android:orientation="vertical"orsetOrientation(). - RTL support works automatically based on locale, or can be forced via
android:layoutDirection="rtl". - FragmentStateAdapter is the recommended adapter for fragment-based pages.
- TabLayoutMediator links
TabLayoutandViewPager2seamlessly and must be attached after the adapter is set. - UI updates are handled via
notifyDatasetChanged()when the fragment collection changes.
By following this example, you can easily integrate TabLayout with ViewPager2 into your own Android app to create smooth, modern, swipeable tab interfaces. Try extending the example by adding more fragments, custom tab icons, or combining it with RecyclerView for even richer UI experiences.
1 comment:
Good sir ji
Post a Comment