How to Use Tablayout with Viewpager2 in Android

How to use TabLayout with ViewPager2 in Android

You have to use this TabLayoutMediator that mimics tabLayout.setupWithViewPager() and sets up the ViewPager2 with Tablayout. Otherwise, you will have to write your own adapter that will combine both parties.

Its code will look like this in Kotlin

TabLayoutMediator(tabLayout, viewPager) { tab, position ->
tab.text = tabTitles[position]
}.attach()

How to use ViewPager2 with tabs in Kotlin?

The same thing which you are asking i apply in my project its also work for you

<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:id="@+id/root_layout_home_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent">

<com.google.android.material.tabs.TabLayout
android:id="@+id/home_fragment_tabs"
android:layout_width="match_parent"
android:layout_height="?android:attr/actionBarSize"
android:background="@drawable/gradianttoolbarbottom"
app:itemTextColor="@drawable/custom_menue_bar_color"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"

app:layout_constraintTop_toBottomOf="@+id/constraintLayout3"
app:tabGravity="fill"
app:tabIndicatorColor="@color/Orange"
app:tabMode="scrollable"
app:tabSelectedTextColor="@color/white"
app:tabTextColor="@color/gray_400_dark" />

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_fragment_viewPager"
android:layout_width="match_parent"
android:layout_height="0dp"
android:animateLayoutChanges="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/home_fragment_tabs" />

</androidx.constraintlayout.widget.ConstraintLayout>

this is Kotlin class

 class Home_Fragment : Fragment() {
private lateinit var homeViewModel: HomeFragmentViewModel
private var myContext: FragmentActivity? = null

override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
homeViewModel = ViewModelProvider(this).get(HomeFragmentViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
myContext=activity
val viewpagger: ViewPager2 =root.findViewById<ViewPager2>(R.id.home_fragment_viewPager)
viewpagger.isSaveEnabled=false
val tabs: TabLayout = root.findViewById<TabLayout>(R.id.home_fragment_tabs)
val adapter =MyViewPagerAdapter(childFragmentManager,lifecycle)
adapter.addFragment(Fragment1(), getString(R.string.text_Fragment1))
adapter.addFragment(Fragment2(), getString(R.string.text_Fragment2))
adapter.addFragment(Fragment3(), getString(R.string.text_Fragment3))
adapter.addFragment(Fragment4(),getString(R.string.text_Fragment4))
adapter.addFragment(Fragment5(), getString(R.string.text_Fragment5))
adapter.notifyDataSetChanged()
viewpagger.adapter =adapter
TabLayoutMediator(tabs, viewpagger) { tab, position ->
tab.text = adapter.getPageTitle(position)
viewpagger.setCurrentItem(tab.position, true)
}.attach()
return root
}

class MyViewPagerAdapter(manager: FragmentManager, lifecycle: Lifecycle) : FragmentStateAdapter(manager,lifecycle ){
private val fragmentList : MutableList<Fragment> =ArrayList()
private val titleList : MutableList<String> =ArrayList()
override fun getItemCount(): Int {
return fragmentList.size
}

override fun createFragment(position: Int): Fragment {
return fragmentList[position]
}

fun addFragment(fragment: Fragment, title: String){
fragmentList.add(fragment)
titleList.add(title)
}

fun getPageTitle(position: Int): CharSequence? {
return titleList[position]
}
}
}

implementation of viewPager2

yes that link helped . I changed these lines of codes:

 tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){

@Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager.setCurrentItem(tab.getPosition());
}

@Override
public void onTabUnselected(TabLayout.Tab tab) {
}

@Override
public void onTabReselected(TabLayout.Tab tab) {

}
});

viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});

ViewPager2 with custom tablayout

I found a temporary and good solution.

1-Use RecyclerView for the tabs and handle it manually.

2-Use ViewPager2 for fragments.

public class ViewPagerHelper extends ViewPager2.OnPageChangeCallback implements TabSelectInterface {
private Activity activity;
private byte from;
private RecyclerView recyclerViewTabs;
private ViewPager2 viewPager2;
private List<Fragment> fragmentList;
private List<String> tabList;
private ViewPagerTabsAdapter viewPagerTabsAdapter;
private FragmentManager fragmentManager;
private boolean isLive;
private LinearLayoutManager linearLayoutManagerTabs;

public ViewPagerHelper(FragmentManager fragmentManager, Activity activity, byte from, List<Fragment> fragmentList, List<String> tabList, boolean isLive) {
this.fragmentManager = fragmentManager;
this.activity = activity;
this.from = from;
this.fragmentList = fragmentList;
this.tabList = tabList;
this.isLive = isLive;
setupViewPager();

}

private void setupViewPager() {
recyclerViewTabs = activity.findViewById(R.id.recycle_tabs);
viewPager2 = activity.findViewById(R.id.viewpager);

linearLayoutManagerTabs = new LinearLayoutManager(activity, RecyclerView.HORIZONTAL, false);

recyclerViewTabs.setLayoutManager(linearLayoutManagerTabs);

setTabsAdapter();
setFragmentsAdapter();

viewPager2.registerOnPageChangeCallback(this);

// viewPager2.setUserInputEnabled(false);
}

private void setTabsAdapter() {
viewPagerTabsAdapter = new ViewPagerTabsAdapter(activity, tabList, isLive, this);
recyclerViewTabs.setAdapter(viewPagerTabsAdapter);
}

private void setFragmentsAdapter() {
ViewPagerFragmentAdapter viewPagerFragmentAdapter = new ViewPagerFragmentAdapter(fragmentManager, fragmentList);
viewPager2.setAdapter(viewPagerFragmentAdapter);
}

@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
System.out.println("onPageScrolled1: " + position);
System.out.println("onPageScrolled2: " + positionOffset);
System.out.println("onPageScrolled3: " + positionOffsetPixels);
super.onPageScrolled(position, positionOffset, positionOffsetPixels);
}

@Override
public void onPageSelected(int position) {
super.onPageSelected(position);

Log.e("Selected_Page", String.valueOf(position));
viewPagerTabsAdapter.setSelectedTab(position);
linearLayoutManagerTabs.scrollToPositionWithOffset(position, 0);
}

@Override
public void onPageScrollStateChanged(int state) {
super.onPageScrollStateChanged(state);
}

@Override
public void onTabSelected(int position) {
viewPager2.setCurrentItem(position, true);
}

public void animateFirstTab(){
viewPagerTabsAdapter.animateFirstTab();
}

And the viewpager2 adapter class

public class ViewPagerFragmentAdapter extends FragmentStateAdapter {

private List<Fragment> arrayList;

ViewPagerFragmentAdapter(@NonNull FragmentManager fragmentManager, List<Fragment> arrayList) {
super(fragmentManager);
this.arrayList = arrayList;
}

@NonNull
@Override
public Fragment getItem(int position) {
return arrayList.get(position);
}

@Override
public int getItemCount() {
return arrayList.size();
}

}

The recyclerview tab adapter

public class ViewPagerTabsAdapter extends RecyclerView.Adapter<ViewPagerTabsAdapter.OrderHolder> {
private Context context;
private List<String> list;
private int selectedTab = 0;
private TabSelectInterface tabSelectInterface;
private boolean isLive = false;

private List<Integer> tabsWidth = new ArrayList<>();
int numberToSpliteWidth = 0;
private boolean animateFirstTab=false;
ViewPagerTabsAdapter(Context context, List<String> list, boolean isLive, TabSelectInterface tabSelectInterface) {
this.context = context;
this.list = list;
this.isLive = isLive;
this.tabSelectInterface = tabSelectInterface;
}

@NonNull
@Override
public OrderHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View rowView = LayoutInflater.from(context).inflate(R.layout.custom_tab, parent, false);
// final RecyclerView.ViewHolder holder = new RecyclerView.ViewHolder(rowView);

// if (!tabsWidth.isEmpty()) {
// int sumWidths = 0;
// for (Integer w : tabsWidth) {
// sumWidths += w;
// }
//
// //no scroll needed, split the width
// if (sumWidths < parent.getWidth()) {
//
// System.out.println("THEWIDTHIS: " + viewType);
// int newWidth = parent.getWidth() / list.size();
// if (newWidth > viewType) {
// rowView.getLayoutParams().width = newWidth;
// }
//
//
// }
//
// }

if (!tabsWidth.isEmpty()) {

DisplayMetrics displayMetrics = context.getResources().getDisplayMetrics();
int newTabMinWidth = displayMetrics.widthPixels / list.size();
System.out.println("THEtabMinWidth: " + newTabMinWidth);
if (list.size() <= 4) {
// rowView.setMinimumWidth(tabMinWidth - 25);
if (newTabMinWidth > viewType) {
rowView.getLayoutParams().width = newTabMinWidth;
}
} else {
// rowView.setMinimumWidth(tabMinWidth + 32);
if (newTabMinWidth > viewType) {
rowView.getLayoutParams().width = (int) (newTabMinWidth + context.getResources().getDimension(R.dimen._9sdp));
}
}
}
return new OrderHolder(rowView);
}

@Override
public void onBindViewHolder(@NonNull OrderHolder holder, int position) {
holder.name.setText(list.get(position));
if (selectedTab == position) {
holder.name.setTextColor(ContextCompat.getColor(context, R.color.yellow));
holder.selectedView.setVisibility(View.VISIBLE);
} else {
holder.name.setTextColor(ContextCompat.getColor(context, R.color.font2));
holder.selectedView.setVisibility(View.INVISIBLE);
}

if (holder.name.getText().toString().equals("الفيديو")) {
//
if (isLive) {
Glide.with(context).asGif().load(R.drawable.live).into(holder.imageView);
holder.imgframe.setVisibility(View.VISIBLE);
} else {
holder.imgframe.setVisibility(View.GONE);

}
} else {
holder.imgframe.setVisibility(View.GONE);

}

if (animateFirstTab){

Animation a = AnimationUtils.loadAnimation(context, R.anim.scale);
a.reset();
holder.name.clearAnimation();
holder.name.startAnimation(a);
animateFirstTab=false;

}

holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
tabSelectInterface.onTabSelected(holder.getAdapterPosition());
}
});

if (tabsWidth.isEmpty()) {

final ViewTreeObserver observer = holder.itemView.getViewTreeObserver();
observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
holder.itemView.getViewTreeObserver().removeOnGlobalLayoutListener(this);

// int containerWidth = holder.itemView.getWidth();
// int containerHeight = holder.itemView.getHeight();
// float x = containerWidth - Float.parseFloat(model.getXpoints(o)) / 100 * containerWidth;
// float y = containerHeight - Float.parseFloat(model.getYpoints(o)) / 100 * containerHeight;
// Log.e("measuredWidth", "" + containerHeight + "" + containerWidth);
// Log.e("getPointX", "" + model.getXpoints(o) + "" + model.getYpoints(o));
// Log.e("x", "x" + x + "y" + y);
//
// h.tag.setX(x);
// h.tag.setY(y);
// h.tag.requestLayout();
System.out.println("THEWIDTHIS2: " + holder.itemView.getWidth());
tabsWidth.add(holder.itemView.getWidth());
if (position == list.size() - 1) {
System.out.println("notifiNOW");
notifyDataSetChanged();
}
}
});

}

}

@Override
public int getItemViewType(int position) {

try {
return tabsWidth.get(position);

} catch (Exception e) {
// return super.getItemViewType(position);
return 0;
}

}

@Override
public int getItemCount() {
return list.size();
}

void setSelectedTab(int selectedTab) {
int currentSelectedTab = this.selectedTab;

if (currentSelectedTab != selectedTab) {
this.selectedTab = selectedTab;
notifyItemChanged(currentSelectedTab);
notifyItemChanged(selectedTab);
}

}

void animateFirstTab() {
animateFirstTab=true;
notifyItemChanged(0);

}

public class OrderHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private TextView name;
private View selectedView;
private FrameLayout imgframe;
private ImageView imageView;

OrderHolder(View itemView) {
super(itemView);
name = itemView.findViewById(R.id.textview);
selectedView = itemView.findViewById(R.id.selected_view);

imgframe = (FrameLayout) itemView.findViewById(R.id.imgframe);
imageView = (ImageView) itemView.findViewById(R.id.imageView);

}

@Override
public void onClick(View view) {

}
}

Use this in XML

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycle_tabs"
android:layout_width="match_parent"
android:layout_height="52dp"
android:layout_gravity="center_horizontal"
ads:layout_constraintBottom_toBottomOf="parent"
ads:layout_constraintEnd_toEndOf="parent"
ads:layout_constraintStart_toStartOf="parent" />

<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/container"
android:layout_marginBottom="50dp" />

And to use it. you just need to use this code

  List<Fragment> fragmentList = new ArrayList<>();
List<String> tabtList = new ArrayList<>();

tabtList.add(tab_index,"tab_name" );
fragmentList.add(tab_index, new TabFragment());

new ViewPagerHelper(getSupportFragmentManager(), MatchProfileActivity.this, VIEWPAGER_TYPE_FROM_MATCHES, fragmentList, tabtList,
false);

Hint: not all code needed I put all my code.

How to use custom tab item in TabLayout with ViewPager2 in Android , TabLayoutMediator not showing custom TabItem

tab mode scrollable solved my issue .

app:tabMode="scrollable"



Related Topics



Leave a reply



Submit