I am trying to create a tab layout for my program.
There are two tabs. If I try to switch to Tab2 instead of staying on Tab2, it changes back to Tab1. I have 0 clue what is causing this problem.
Here is my code
MainActivity:
tabLayout = findViewById(R.id.tablayout);
viewPager2 = findViewById(R.id.viewpager);
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentAdapter = new CustomAdapter(fragmentManager, getLifecycle());
viewPager2.setAdapter(fragmentAdapter);
tabLayout.addTab(tabLayout.newTab().setText("Tab1"));
tabLayout.addTab(tabLayout.newTab().setText("Tab2"));
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
viewPager2.setCurrentItem(tab.getPosition());
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageScrollStateChanged(int state) {
tabLayout.selectTab(tabLayout.getTabAt(state));
}
});
CustomAdapter:
public class CustomAdapter extends FragmentStateAdapter {
public CustomAdapter(#NonNull FragmentManager fragmentManager, #NonNull Lifecycle lifecycle) {
super(fragmentManager, lifecycle);
}
#NonNull
#Override
public Fragment createFragment(int position) {
if(position == 1) return new BlankFragment1();
return new BlankFragment2();
}
#Override
public int getItemCount() {
return 2;
}
Following the official docs here you can use a TabLayoutMediator to link the tab layout and pager instead of doing it with your own listeners.
However, the root of the problem you observed is that state in onPageScrollStateChanged is not the position that it scrolled to - it is an integer representing the scroll state. Since SCROLL_STATE_IDLE is 0, and SCROLL_STATE_DRAGGING is 1, as soon as you stopped dragging it would snap back to tab 0.
Using TabLayoutMediator (recommended)
To use the TabLayoutMediator replace your addOnTabSelectedListener, registerOnPageChangeCallback, and manually setting the tabs (addTab) with this, which links the tabs to the view pager and provides a method to set the tab titles
// remove the "addTab" calls, "addOnTabSelectedListener",
// and "registerOnPageChangeCallback"
new TabLayoutMediator(tabLayout, viewPager2,
(tab, position) -> tab.setText("Tab" + (position + 1))
).attach();
Using your own listeners
It is still possible to use your own listeners, but you have to change the view pager listener to use onPageSelected instead of onPageScrollStateChanged, like this:
viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
#Override
public void onPageSelected(int position) {
tabLayout.selectTab(tabLayout.getTabAt(position));
}
});
Note: The positions are 0-based, so you are showing "BlankFragment2" in position 0 and "BlankFragment1" in position 1 (not sure if that is what you intended).
I'm using TabLayout with ViewPager for showing data as requested.
In tab layout, my requirement is, I've to set a different font for the selected item and a different one for others. I write the following code for this.
But I'm facing one issue. Suppose I've 4 items "One", "Two", "Three" and "Four". Initially "One" is default selected with Bold font, and others are with normal font. But when I click "Two" tab "One" tab disappears. When I click on "Three" tab "Two" tab disappears and "One" tab visible with normal font.
private void setupViewPager(CustomViewPager viewPager, TabLayout tabLayout, ArrayList<TipsInfo> mListTips) {
adapter = new ViewPagerAdapter(getChildFragmentManager());
for (int i = 0; i < mListTips.size(); i++) {
if (!TextUtils.isEmpty(mListTips.get(i).getValue()))
adapter.addFragment(TipsDetailFragment.newInstance(mListTips.get(i).getValue()), mListTips.get(i).getLabel());
}
viewPager.setAdapter(adapter);
tabLayout.setupWithViewPager(viewPager);
View tabContent = LayoutInflater.from(requireContext()).inflate(R.layout.item_tips_tablayout_selected, null);
TextView selected = tabContent.findViewById(R.id.tv_tips_selected_tab);
View tabContent1 = LayoutInflater.from(requireContext()).inflate(R.layout.item_tips_tablayout_unselected, null);
TextView unselected = tabContent1.findViewById(R.id.tv_tips_unselected_tab);
tabLayout.addOnTabSelectedListener(
new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
selected.setText(tab.getText());
tab.setCustomView(selected);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
unselected.setText(tab.getText());
tab.setCustomView(unselected);
//
// for(int i=0; i<tabLayout.getTabCount(); i++){
// if(i != tabLayout.getSelectedTabPosition()){
// unselected.setText(tabLayout.getTabAt(i).getText());
// tabLayout.getTabAt(i).setCustomView(unselected);
// }
// }
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
onTabSelected(tab);
}
}
);
}
My ViewPaerAdapter is extended with FragmentStatePagerAdapter and its object is created with getChildFragmentManager. My XML code look's like this:
<com.google.android.material.tabs.TabLayout
android:id="#+id/tl_tips"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorWhite"
android:elevation="#dimen/v1dp"
android:visibility="invisible"
app:tabGravity="fill"
android:gravity="start"
app:tabMinWidth="#dimen/v100dp"
android:textAlignment="viewStart"
app:tabIndicatorFullWidth="false"
app:tabIndicatorColor="#color/colorBannerNewDotSelected"
app:tabMode="scrollable"
android:layout_gravity="start"
app:tabIndicatorHeight="#dimen/v3dp"
app:tabSelectedTextColor="#color/colorBlackDark"
app:tabTextAppearance="#style/MyTabLayoutTextAppearance"
app:tabTextColor="#color/colorServiceCount"
/>
item_tips_tablayout_selected and item_tips_tablayout_unselected contains only TextView with different fonts applied to it.
Screenshots:
Initial
When clicked on "Benefits", the font applied to it but "How to use" disappeared.
When clicked on "Product Use", the font applied to it, "How to use" appeared with normal font, and "Benefits" tab disappeared.
It basically does what you wrote in your code.
tabLayout.addOnTabSelectedListener(
new TabLayout.OnTabSelectedListener() {
#Override
//as tab 2 selected it set text to tab 2
public void onTabSelected(TabLayout.Tab tab) {
selected.setText(tab.getText());
tab.setCustomView(selected);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
//as tab 1 unselected it set NO text to tab 1 in it
unselected.setText(tab.getText());
tab.setCustomView(unselected);
Why to set CustomView every time when you just need to change the typeface?
I have an Kotlin code that was converted to JAVA code, it looks like shit in JAVA, but it works:
private void setTypefaceToTab(Context context, TabLayout tabLayout, TabLayout.Tab tab, int stylem) {
if (tab != null && context != null) {
try {
View var10000 = ((ViewGroup)tabLayout.getChildAt(0)).getChildAt(tab.getPosition());
LinearLayout layout = (LinearLayout)var10000;
var10000 = layout.getChildAt(1);
TextView tabTextView = (TextView)var10000;
tabTextView.setTextSize (***Text Size***);
tabTextView.setTypeface(Typeface.create("sans-serif-condensed",stylem));
} catch (Exception var7) {
Log.d ("EXC",var7.toString ());
}
}
}
Then just use it at tabselectedlistener and in onCreate to set typeface for the first selected tab:
protected void onCreate(Bundle savedInstanceState) {
...
setTypefaceToTab(context,tablayout, tablayout.getTabAt (tablayout.getSelectedTabPosition ()),Typeface.BOLD_ITALIC);
...
}
and in tabListener:
private void tabListener(){
tablayout.addOnTabSelectedListener (new TabLayout.OnTabSelectedListener () {
#Override
public void onTabSelected(TabLayout.Tab tab) {
setTypefaceToTab(context,tablayout,tab,Typeface.BOLD_ITALIC);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
setTypefaceToTab(context,tablayout,tab,Typeface.NORMAL);
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
}
Hope it is what you wanted
I have created a sign-up form with tab layout which includes three tabs(three fragments). I have successfully ended up in navigating to the next fragment after clicking on 'Next' in my previous fragment. However my problem is that I am unable to highlight my current tab, which should be highlighted(as if it is selected) when I click 'Next' in my previous fragment.
The following is my first fragment(Account info):
#Override
public void onClick(View v) {
emailid = email.getText().toString();
if (!isValidEmail(emailid)) {
email.setError("Invalid Email");
}
pass = password.getText().toString();
if (!isValidPassword(pass)) {
password.setError("Password cannot be empty");
}
confirmPass = confirmPassword.getText().toString();
if (!isValidPassword(confirmPass)) {
confirmPassword.setError("Password cannot be empty");
}
I am navigating to the next fragment using the below code, could anyone suggest how to highlight the title of the next tab(fragment) after navigating to it?
if (isValidEmail(emailid) && isValidPassword(pass)) {
viewPager = (ViewPager) getActivity().findViewById(R.id.pager);
viewPager.setCurrentItem(1);
}
}
below is my activity code, how do i disable touch or click events on tabs?
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.addTab(tabLayout.newTab().setText("Account Info"));
tabLayout.addTab(tabLayout.newTab().setText("Personal Info"));
tabLayout.addTab(tabLayout.newTab().setText("Confirmation"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
viewPager = (ViewPager) findViewById(R.id.pager);
viewPagerAdapter = new ViewPagerAdapter(getSupportFragmentManager());
viewPager.setAdapter(viewPagerAdapter);
viewPager.setOnTouchListener(new View.OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event)
{
return true;
}
});
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
// This method will be invoked when a new page becomes selected.
#Override
public void onPageSelected(int position) {
Toast.makeText(SignupActivity.this, "Selected page position: " + position, Toast.LENGTH_SHORT).show();
tabLayout.tabP(true);
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
for this approach you have to implement this method
viewPager.addOnPageChangeListener
and in onPageSelected method you have to re-write the tab name as per condition
you can implement a method like this
private void initTabsName() {
for (int i = 0; i < tabLayout.getTabCount(); i++) {
TabLayout.Tab tab = tabLayout.getTabAt(i);
RelativeLayout relativeLayout = (RelativeLayout) LayoutInflater.from(this).inflate(R.layout.subcat_custom_tab, tabLayout, false);
// do something to make tab selected using if else statements
/* // for example
if (i == 0) {
}
*/
tab.setCustomView(relativeLayout);
}
}
Adding the below code solved my question:
if (isValidEmail(emailid) && isValidPassword(pass)) {
viewPager = (ViewPager) getActivity().findViewById(R.id.pager);
viewPager.setCurrentItem(1);
tabLayout = (TabLayout) getActivity().findViewById(R.id.tabLayout);
tabLayout.getTabAt(1).select();
}
I have initiated my tabLayout if my condition is true and called the method getTabAt() which is responsible to highlight the tabs in a Tab Layout. I have literally specified the tab position "1"(not 0, since 0 is still the first tab) in getTabAt(1) which I required to highlight under successful condition.
How should I select a tab in TabLayout programmatically?
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
If you know the index of the tab you want to select, you can do it like so:
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
tab.select();
This technique works even if you're using the TabLayout by itself without a ViewPager (which is atypical, and probably bad practice, but I've seen it done).
This is how I solved it:
void selectPage(int pageIndex){
tabLayout.setScrollPosition(pageIndex,0f,true);
viewPager.setCurrentItem(pageIndex);
}
Use this:
tabs.getTabAt(index).select();
Keep in mind that, if currentTabIndex and index are same then this sends your flow to onTabReselected and not onTabSelected.
Use this:
<android.support.design.widget.TabLayout
android:id="#+id/patienthomescreen_tabs"
android:layout_width="match_parent"
android:layout_height="72sp"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabIndicatorColor="#android:color/white"
app:tabSelectedTextColor="#color/green"/>
After in OnClickListener:
TabLayout tabLayout = (TabLayout) findViewById(R.id.patienthomescreen_tabs);
TabLayout.Tab tab = tabLayout.getTabAt(someIndex);
tab.select();
Keep in mind that, if currentTabIndex and index are same then this sends your flow to onTabReselected and not onTabSelected.
This is probably not the ultimate solution, and it requires that you use the TabLayout together with a ViewPager, but this is how I solved it:
void selectPage(int pageIndex)
{
viewPager.setCurrentItem(pageIndex);
tabLayout.setupWithViewPager(viewPager);
}
I tested how big the performance impact of using this code is by first looking at the CPU- and memory monitors in Android Studio while running the method, then comparing it to the load that was put on the CPU and memory when I navigated between the pages myself (using swipe gestures), and the difference isn't significantly big, so at least it's not a horrible solution...
Hope this helps someone!
Just set viewPager.setCurrentItem(index) and the associated TabLayout would select the respective tab.
With the TabLayout provided by the Material Components Library just use the selectTab method:
TabLayout tabLayout = findViewById(R.id.tab_layout);
tabLayout.selectTab(tabLayout.getTabAt(index));
It requires version 1.1.0.
If you can't use tab.select() and you don't want to use a ViewPager, you can still programmatically select a tab. If you're using a custom view through TabLayout.Tab setCustomView(android.view.View view) it is simpler. Here's how to do it both ways.
// if you've set a custom view
void updateTabSelection(int position) {
// get the position of the currently selected tab and set selected to false
mTabLayout.getTabAt(mTabLayout.getSelectedTabPosition()).getCustomView().setSelected(false);
// set selected to true on the desired tab
mTabLayout.getTabAt(position).getCustomView().setSelected(true);
// move the selection indicator
mTabLayout.setScrollPosition(position, 0, true);
// ... your logic to swap out your fragments
}
If you aren't using a custom view then you can do it like this
// if you are not using a custom view
void updateTabSelection(int position) {
// get a reference to the tabs container view
LinearLayout ll = (LinearLayout) mTabLayout.getChildAt(0);
// get the child view at the position of the currently selected tab and set selected to false
ll.getChildAt(mTabLayout.getSelectedTabPosition()).setSelected(false);
// get the child view at the new selected position and set selected to true
ll.getChildAt(position).setSelected(true);
// move the selection indicator
mTabLayout.setScrollPosition(position, 0, true);
// ... your logic to swap out your fragments
}
Use a StateListDrawable to toggle between selected and unselected drawables or something similar to do what you want with colors and/or drawables.
A bit late but might be a useful solution.
I am using my TabLayout directly in my Fragment and trying to select a tab quite early in the Fragment's Lifecycle.
What worked for me was to wait until the TabLayout finished drawing its child views by using android.view.View#post method. i.e:
int myPosition = 0;
myFilterTabLayout.post(() -> { filterTabLayout.getTabAt(myPosition).select(); });
You can try solving it with this:
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);
tabLayout.setupWithViewPager(mViewPager);
TabLayout.Tab tab = tabLayout.getTabAt(pos);
if (tab != null) {
tab.select();
}
Newest simple solution worked for me:
binding.tablayout.selectTab(binding.tablayout.getTabAt(tabPosisiton))
or
with(binding.tablayout) {
selectTab(getTabAt(tabPosisiton))
}
and tabPosition start from 0
try this
new Handler().postDelayed(
new Runnable(){
#Override
public void run() {
if (i == 1){
tabLayout.getTabAt(0).select();
} else if (i == 2){
tabLayout.getTabAt(1).select();
}
}
}, 100);
Kotlin Users:
Handler(Looper.getMainLooper()).postDelayed(
{ tabLayout.getTabAt(position).select() }, 100
)
This will also scroll your tab layout in case if it needs to scroll.
you should use a viewPager to use viewPager.setCurrentItem()
viewPager.setCurrentItem(n);
tabLayout.setOnTabSelectedListener(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) {
}
});
A combined solution from different answers is:
new Handler().postDelayed(() -> {
myViewPager.setCurrentItem(position, true);
myTabLayout.setScrollPosition(position, 0f, true);
},
100);
I am using TabLayout to switch fragments. It works for the most part, except whenever I tried to select a tab programmatically using tab.select(), my TabLayout.OnTabSelectedListener would trigger the onTabSelected(TabLayout.Tab tab), which would cause me much grief. I was looking for a way to do programmatic selection without triggering the listener.
So I adapted #kenodoggy 's answer to my use. I was further facing a problem where some of the internal objects would return null (because they weren't created yet, because I was answering onActivityResult() from my fragment, which occurs before onCreate() in the case the activity is singleTask or singleInstance) so I wrote up a detailed if/else sequence which would report the error and fall through without the NullPointerException that would otherwise trigger. I use Timber for logging, if you're not using that substitute with Log.e().
void updateSelectedTabTo(int position) {
if (tabLayout != null){
int selected = tabLayout.getSelectedTabPosition();
if (selected != -1){
TabLayout.Tab oldTab = tabLayout.getTabAt(0);
if (oldTab != null){
View view = oldTab.getCustomView();
if (view != null){
view.setSelected(false);
}
else {
Timber.e("oldTab customView is null");
}
}
else {
Timber.e("oldTab is null");
}
}
else {
Timber.e("selected is -1");
}
TabLayout.Tab newTab = tabLayout.getTabAt(position);
if (newTab != null){
View view = newTab.getCustomView();
if (view != null){
view.setSelected(false);
}
else {
Timber.e("newTab customView is null");
}
}
else {
Timber.e("newTab is null");
}
}
else {
Timber.e("tablayout is null");
}
}
Here, tabLayout is my memory variable bound to the TabLayout object in my XML. And I don't use the scrolling tab feature so I removed that as well.
If you are using TabLayout with viewPager then this helps you. You set the TabLayout with ViewPager in addOnpagelistener.
if you want to set the TabLayout position directly(not click on the Tab individual) try below code tabLayout.getTabAt(position_you_want_to_set).select()
/* will be invoked whenever the page changes or is incrementally scrolled*/
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
tabLayout.getTabAt(position).select();
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
This won't work for app that has ViewPager2 Implemented, For that, you need to use
viewPager2.setCurrentItem(position);
inside onConfigureTab, onConfigureTab if found when we use TabLayoutMediator
i.e
TabLayoutMediator tabLayoutMediator = new TabLayoutMediator(
tabLayout, viewPager2, new TabLayoutMediator.TabConfigurationStrategy() {
#Override
public void onConfigureTab(#NonNull TabLayout.Tab tab, int position) {
switch (position){
case 0 : tab.setIcon(getResources().getDrawable(R.drawable.camera));
break;
case 1 : tab.setText("CHAT");
viewPager2.setCurrentItem(position); // when app starts this will be the selected tab
break;
case 2 : tab.setText("STATUS");
break;
case 3 : tab.setText("CALL");
break;
}
}
}
);
tabLayoutMediator.attach();
add for your viewpager:
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageSelected(int position) {
array.clear();
switch (position) {
case 1:
//like a example
setViewPagerByIndex(0);
break;
}
}
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
//on handler to prevent crash outofmemory
private void setViewPagerByIndex(final int index){
Application.getInstance().getHandler().post(new Runnable() {
#Override
public void run() {
viewPager.setCurrentItem(index);
}
});
}
By default if you select a tab it will be highlighted. If you want to select Explicitly means use the given commented code under onTabSelected(TabLayout.Tab tab) with your specified tab index position. This code will explains about change fragment on tab selected position using viewpager.
public class GalleryFragment extends Fragment implements TabLayout.OnTabSelectedListener
{
private ViewPager viewPager;public ViewPagerAdapter adapter;private TabLayout tabLayout;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_gallery, container, false);
viewPager = (ViewPager) rootView.findViewById(R.id.viewpager);
adapter = new ViewPagerAdapter(getChildFragmentManager());
adapter.addFragment(new PaymentCardFragment(), "PAYMENT CARDS");
adapter.addFragment(new LoyaltyCardFragment(), "LOYALTY CARDS");
viewPager.setAdapter(adapter);
tabLayout = (TabLayout) rootView.findViewById(R.id.tabs);
tabLayout.setupWithViewPager(viewPager);
tabLayout.setOnTabSelectedListener(this);
}
#Override
public void onTabSelected(TabLayout.Tab tab) {
//This will be called 2nd when you select a tab or swipe using viewpager
final int position = tab.getPosition();
Log.i("card", "Tablayout pos: " + position);
//TabLayout.Tab tabdata=tabLayout.getTabAt(position);
//tabdata.select();
tabLayout.post(new Runnable() {
#Override
public void run() {
if (position == 0) {
PaymentCardFragment paymentCardFragment = getPaymentCardFragment();
if (paymentCardFragment != null) {
VerticalViewpager vp = paymentCardFragment.mypager;
if(vp!=null)
{
//vp.setCurrentItem(position,true);
vp.setCurrentItem(vp.getAdapter().getCount()-1,true);
}
}
}
if (position == 1) {
LoyaltyCardFragment loyaltyCardFragment = getLoyaltyCardFragment();
if (loyaltyCardFragment != null) {
VerticalViewpager vp = loyaltyCardFragment.mypager;
if(vp!=null)
{
vp.setCurrentItem(position);
}
}
}
}
});
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
//This will be called 1st when you select a tab or swipe using viewpager
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
//This will be called only when you select the already selected tab(Ex: selecting 3rd tab again and again)
}
private PaymentCardFragment getLoyaltyCardFragment() {
Fragment f = adapter.mFragmentList.get(viewPager.getCurrentItem());
if(f instanceof PaymentCardFragment)
{
return (PaymentCardFragment) f;
}
return null;
}
private LoyaltyCardFragment getPaymentCardFragment() {
Fragment f = adapter.mFragmentList.get(viewPager.getCurrentItem());
if(f instanceof LoyaltyCardFragment)
{
return (LoyaltyCardFragment) f;
}
return null;
}
class ViewPagerAdapter extends FragmentPagerAdapter {
public List<Fragment> mFragmentList = new ArrayList<>();
private final List<String> mFragmentTitleList = new ArrayList<>();
public void addFragment(Fragment fragment, String title) {
mFragmentList.add(fragment);
mFragmentTitleList.add(title);
}
}
}
This can help too
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
#Override
public void onPageScrolled(int i, float v, int i1) {
}
#Override
public void onPageSelected(int i) {
tablayout.getTabAt(i).select();
}
#Override
public void onPageScrollStateChanged(int i) {
}
});
You can set TabLayout position using following functions
public void setTab(){
tabLayout.setScrollPosition(YOUR_SCROLL_INDEX,0,true);
tabLayout.setSelected(true);
}
If it so happens that your default tab is the first one(0) and you happen to switch to a fragment, then you must manually replace the fragment for the first time. This is because the tab is selected before the listener gets registered.
private TabLayout mTabLayout;
...
#Override
public View onCreateView(#NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_tablayout, container, false);
mTabLayout = view.findViewById(R.id.sliding_tabs);
mTabLayout.addOnTabSelectedListener(mOnTabSelectedListener);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.tabContent, MyFirstFragment.newInstance()).commit();
return view;
}
Alternatively, you can consider calling getTabAt(0).select() and overriding onTabReselected like so:
#Override
public void onTabReselected(TabLayout.Tab tab) {
// Replace the corresponding tab fragment.
}
This would work because you are essentially replacing the fragment on every tab reselect.
If you have trouble understanding, this code can help you
private void MyTabLayout(){
TabLayout.Tab myTab = myTabLayout.newTab(); // create a new tab
myTabLayout.addTab(myTab); // add my new tab to myTabLayout
myTab.setText("new tab");
myTab.select(); // select the new tab
}
You can also add this to your code:
myTabLayout.setTabTextColors(getColor(R.color.colorNormalTab),getColor(R.color.colorSelectedTab));
Try this way.
tabLayout.setTabTextColors(getResources().getColor(R.color.colorHintTextLight),
getResources().getColor(R.color.colorPrimaryTextLight));
if u are using TabLayout without viewPager this helps
mTitles = getResources().getStringArray(R.array.tabItems);
mIcons = getResources().obtainTypedArray(R.array.tabIcons);
for (int i = 0; i < mTitles.length; i++) {
tabs.addTab(tabs.newTab().setText(mTitles[i]).setIcon(mIcons.getDrawable(i)));
if (i == 0) {
/*For setting selected position 0 at start*/
Objects.requireNonNull(Objects.requireNonNull(tabs.getTabAt(i)).getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
}
}
tabs.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
Objects.requireNonNull(tab.getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary), PorterDuff.Mode.SRC_IN);
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
Objects.requireNonNull(tab.getIcon()).setColorFilter(ContextCompat.getColor(getApplicationContext(), R.color.white), PorterDuff.Mode.SRC_IN);
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
Kotlin fix
viewPager.currentItem = 0
tabs.setupWithViewPager(viewPager)
TabLayout jobTabs = v.findViewById(R.id.jobTabs);
ViewPager jobFrame = v.findViewById(R.id.jobPager);
jobFrame.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(jobTabs));
this will select tab as view pager swipe page
With Viewpager2, Kotlin none of the other answers helped, only this worked below. position is from fragment result listener in my case:
TabLayoutMediator(binding.tabLayout, binding.viewPager2) { _, _ ->
binding.viewPager2 = position
}.attach()
I am scracthing my head for past 1 day but unable to find the solution.
In mine application there are two tabs under the toolbar
First tab is USER-TAB
the second one is ADMIN-TAB
In both the tabs there are the listView. When a ListItem on the USER-TAB is clicked a dialog appears and user take some action.
Now after this when the ADMIN-TAB is Selected the Admin should get refreshed with new sets of data. But It's not. On selecting the ADMIN-TAB the onResume() method and everyting is getting called but it is not able to update the list.
I wont be able to write the Whole code, I am giving some snippet.
Basically I have taken the code from this link
https://github.com/codepath/android_guides/wiki/Sliding-Tabs-with-PagerSlidingTabStrip
In My Main Activity I have written the OpPageChangeListener.
public class MaterialTab extends FragmentActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.material_main_sample);
// Get the ViewPager and set it's PagerAdapter so that it can display items
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new SampleFragmentPagerAdapter(getSupportFragmentManager()));
// Give the PagerSlidingTabStrip the ViewPager
PagerSlidingTabStrip tabsStrip = (PagerSlidingTabStrip) findViewById(R.id.tabs);
// Attach the view pager to the tab strip
tabsStrip.setViewPager(viewPager);
tabsStrip.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
#Override
public void onPageSelected(int position) {
if(position == 0){
MileUserFragment userFragment = new MileUserFragment();
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(userFragment);
ft.attach(userFragment);
ft.commit();
} if(position == 1){
MileAdminFragment adminFragment = new MileAdminFragment();
final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.detach(adminFragment);
ft.attach(adminFragment);
ft.commit();
}
}
#Override
public void onPageScrollStateChanged(int state) {
}
});
}
}
OnPageSelected You can see I am detaching and reattaching the fragment.Everything is working fine. Both Fragments OnResume() are getting called but the List is not getting changed. I don't undrstand why
For additional assistance i am adding snippet one Fragment. Hope this will give some Idea where i might be going wrong
public class MileUserFragment extends Fragment {
#Override
public void onResume() {
super.onResume();
new GetAdminDbTask().execute();
if(!internetUtil.isConnectedToInternet(getActivity())){
mSwipeRefreshLayout.setRefreshing(false);
mSwipeRefreshLayout.setEnabled(false);
}
}
public class GetAdminDbTask extends AsyncTask<Admin, Void, String> {
#Override
protected String doInBackground(Admin... parmas) {
_adminList = shipmentDbHandler.getAllAdmin();
return "";
}
#Override
protected void onPostExecute(String str) {
mAdminAdapter = new AdminAdapter(getActivity(), _adminList);
adminListView.setAdapter(mAdminAdapter);
mAdminAdapter.notifyDataSetChanged();
// Set the refresh Listener to false after the list has been loaded with new set of data
if (mSwipeRefreshLayout.isRefreshing()) {
mSwipeRefreshLayout.setRefreshing(false);
}
if(_adminList.size() > 0 ){
mAdminAdapter = new AdminAdapter(getActivity(), _adminList);
adminListView.setAdapter(mAdminAdapter);
mAdminAdapter.notifyDataSetChanged();
}
}
}
}
public class SampleFragmentPagerAdapter extends FragmentPagerAdapter {
final int PAGE_COUNT = 2;
private String tabTitles[] = new String[] { "Tab1", "Tab2" };
private FragmentManager fragmentManager;
public SampleFragmentPagerAdapter(FragmentManager fm) {
super(fm);
this.fragmentManager = fm;
}
#Override
public int getCount() {
return PAGE_COUNT;
}
#Override
public Fragment getItem(int position) {
FragmentTransaction ft = null;
if(position == 0){
MileUserFragment userFragment = new MileUserFragment();
return userFragment;
}
if(position == 1){
MileAdminFragment adminFragment = new MileAdminFragment();
return archiveFragment;
}
}
#Override
public CharSequence getPageTitle(int position) {
// Generate title based on item position
return tabTitles[position];
}
}
Haah.. Finally i got an answer to after an heck of losing almost 1 and half days. It might be not completely good answer but atleast it is one of the closest I got.
First of all MainActivity.java looks like:
tabs.setOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {
int scrollPosition = 0;
#Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
if(position == 0){
scrollPosition = 0;
}
if(position == 1){
scrollPosition = 1;
}
}
#Override
public void onPageSelected(int position) {
}
#Override
public void onPageScrollStateChanged(int state) {
if(state == pager.SCROLL_STATE_IDLE){
if(scrollPosition == 0 && application.isActiveAction()){
viewPagerAdapter.notifyDataSetChanged();
application.setActiveAction(false);
}
if(scrollPosition == 1 && application.isArchiveAction()){
viewPagerAdapter.notifyDataSetChanged();
application.setArchiveAction(false);
}
}
}
});
Now what I have done here is I have set OnPageChangeListener and in this I am keeping track of the position whenever the tabs are changing. For my needs what i have done is i have created two boolean variables and setting it when any content on those tab are changing in Application scope. Now when the contents on one tab has been changed or some Action are done I am calling
viewPagerAdapter.notifyDataSetChanged() // Now this is the real gem
after invoking this it will make a call to the ViewPagerAdapter function
#Override
public int getItemPosition(Object object) {
return PagerAdapter.POSITION_NONE; // This will get invoke as soon as you call notifyDataSetChanged on viewPagerAdapter.
}
Also the Point is your ViewPagerAdapter should extend FragmentStatePageAdapter. Now the Point is
PagerAdapter.POSITION_NONE
will not cache the fragment and reload a new fragment for that tab position.
Basic idea is we should not make or retutn PagerAdapter.POSITION_NONE everytime on sliding of tab since it destroys the cached element and reload the fragment which affects UI performance.
So finally the basic thing is always check that whether on calling viewPagerAdapter.notifyDataSetChanged() the function getItemPosition() should also gets invoked. Hope it will help somebody. For better perfomance you can make changes according to your requirement.
I got the needed breakthrough and understanding from this post : #Louth Answer
Remove Fragment Page from ViewPager in Android
Just put
viewPager.setCurrentItem(tab.getPosition());
in your onTabSelected method like:
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) {
}
});