Hi I have an activity A with a button that sends to Activity B with ActionBar and up button enabled, this activity has tabs with fragments and a button that send to a new fragment C not related with the tabs. By clicking the back button, it is supposed to return to the tabs. The back button works and shows the tabs but not the contain. What I'm doing wrong? Here's some code.
Thanks in advance.
Activity B
public class BackActivity extends AppCompatActivity {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_back);
// get fragment manager
myChildToolbar =(Toolbar)findViewById(R.id.my_child_toolbar2);
setSupportActionBar(myChildToolbar);
// Get a support ActionBar corresponding to this toolbar
ActionBar ab = getSupportActionBar();
// Enable the Up button
ab.setDisplayHomeAsUpEnabled(true);
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
myChildToolbar.setTitle(R.string.menu_ver_lista);
Bundle bundle=new Bundle();
bundle.putInt(NuevoinformeFragment.INFORMESEL,datosRecuperados.getInt(NuevoinformeFragment.INFORMESEL));
bundle.putString(TabsFragment.ARG_MUESTRA,"true");
TabsFragment detailFragment = new TabsFragment();
detailFragment.setArguments(bundle);
ft.add(R.id.back_fragment, detailFragment);
ft.commit();
}
#Override
public boolean onSupportNavigateUp() {
onBackPressed();
return false;
}
}
Tabs fragment
TabLayout tabs;
ViewPager viewPager;
private ListaDetalleViewModel mViewModel;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_lista_tabs, container, false);
mViewModel = new ViewModelProvider(requireActivity()).get(ListaDetalleViewModel.class);
return root;
}
#Override
public void onViewCreated(#NonNull View view, #Nullable Bundle savedInstanceState) {
Bundle bundle = getArguments();
viewPager = view.findViewById(R.id.view_pager);
tabs = view.findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
mViewModel.cargarPestaƱas(ciudadNombre).observe(getViewLifecycleOwner(), words -> {
configureTabLayout();
});
}
private void configureTabLayout() {
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter( getFragmentManager(),clientes, mViewModel,clientesplan);
viewPager.setAdapter(sectionsPagerAdapter);
viewPager.addOnPageChangeListener(new
TabLayout.TabLayoutOnPageChangeListener(tabs));
tabs.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) {
}
});
}
}
You're using the wrong FragmentManager when creating your SectionsPagerAdapter, you should be using getChildFragmentManager() here:
SectionsPagerAdapter sectionsPagerAdapter = new SectionsPagerAdapter(
getFragmentManager(), // This is the problem
clientes, mViewModel,clientesplan
);
getFragmentManager() actually refers to the FragmentManager that your TabsFragment has been added to - that's why that method was deprecated and replaced with getParentFragmentManager(), which is more explicit on what that FragmentManager means.
Whenever the fragment you create is fully contained in the layout of another fragment, it needs to be a child fragment by being added to the getChildFragmentManager(). This ensures that it moves through lifecycle states properly (such as getting its Views recreated when its parent has its Views recreated) and to ensure that the state of the fragments are saved and restored properly.
I have two Tab in my Home Fragment using viewpager.I am calling my Home Fragment when ActivityTwo is open.In Home Fragment I have one FloatingButton which when click I go to Information Fragment.When button is clicked in Information Fragment I am coming to Home Fragment and I need to open Second Tab.How to achieve this ?
This is code for setting TabView
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v=inflater.inflate(R.layout.choose_tab, container, false);
//-----------------------------------------------------------------------------------
tabLayout=(TabLayout)v.findViewById(R.id.simpleTabLayout);
viewPager=(ViewPager)v.findViewById(R.id.simpleViewPager);
viewPager.setOffscreenPageLimit(2);
tabLayout.addTab(tabLayout.newTab().setText("One"));
tabLayout.addTab(tabLayout.newTab().setText("Two"));
PagerAdapter adapter=new PagerAdapter(getActivity().getSupportFragmentManager(),tabLayout.getTabCount());
//PagerAdapter adapter=new PagerAdapter(getChildFragmentManager(),tabLayout.getTabCount());
viewPager.setAdapter(adapter);
tabLayout.addOnTabSelectedListener(this);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
return v;
}
#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.setCurrentItem(tab.getPosition());
}
This is code for replacing the Home Fragment
freeTable.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle("Confirmation.");
builder.setMessage("Are you sure to Free this Person?");
builder.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
alertDialog.dismiss();
freeSinglePerson();
alertMsg.successMessage(infoTable,"Person Free Successfully.");
Home home=new Home();
tx = fm.beginTransaction();
tx.replace(R.id.frame,home);
vp.setCurrentItem(1);
tx.commitAllowingStateLoss();
}
});
When my Home Fragment is replaced I want to set the Second Tab.How to achieve this ?
Try following code to get tab layout from Activity
public TabLayout yourPublicMethodToGetTabLayout(){ // inside activity
return tabLayout;
}
TabLayout tabview= ((YourActivityClassName)getActivity()).yourPublicMethodToGetTabLayout(); //inside fragment
Then set tab position
new Handler().postDelayed(
new Runnable(){
#Override
public void run() {
tabview.getTabAt(yourTabIndex).select();
}
}, 100);
I'm populating fragments in a tablayout. I have a method in one of my fragments, and i want to call it from an activity. But when i tried to have reference of the fragment by doing like this Fragment myFragment = (Fragment ) getSupportFragmentManager().findFragmentById(R.id.my_fragment), myFragment is null. I'm new to android. (Sorry for the bad english)
My code so far.
public class DashboardActivity extends AppCompatActivity {
private ViewPager pager;
private TabLayout tabLayout;
private Toolbar dashboardToolbar;
public static int position;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard_activity);
HomeFragment myFragment = new HomeFragment ();
if(getSupportFragmentManager().findFragmentById(R.id.homeFragment) == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.homeFragment, myFragment).commit();
}
pager = (ViewPager) findViewById(R.id.view_pager);
setupViewPager(pager);
tabLayout = (TabLayout) findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager);
pager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
#Override
public void onTabSelected(TabLayout.Tab tab) {
// Toast.makeText(DashboardActivity.this, "tabSelected: " + tab.getText()+" "+ tab.getPosition(), Toast.LENGTH_SHORT).show();
// no where in the code it is defined what will happen when tab is tapped/selected by the user
// this is why the following line is necessary
// we need to manually set the correct fragment when a tab is selected/tapped
// and this is the problem in your code
pager.setCurrentItem(tab.getPosition());
position = tab.getPosition();
}
#Override
public void onTabUnselected(TabLayout.Tab tab) {
}
#Override
public void onTabReselected(TabLayout.Tab tab) {
// Toast.makeText(DashboardActivity.this, "tabReSelected: " + tab.getText(), Toast.LENGTH_SHORT).show();
position = tab.getPosition();
// Reload your recyclerView here
}
});
}
private void setupViewPager(ViewPager viewPager) {
ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager());
adapter.addFragment(new HomeFragment(), "FOR YOU");
adapter.addFragment(new NotificationFragment(), "NOTIF");
adapter.addFragment(new ChatFragment(), "CHAT");
adapter.addFragment(new ProfileFragment(), "PROFILE");
viewPager.setAdapter(adapter);
}
}
Fragment
public class HomeFragment extends Fragment {
// Objects Declaration
public HomeFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.homeFragment, container, false);
}
public void myMethod(){ //method to be called
//do something
}
}
Activity
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_activity_filter);
HomeFragment myFragment= (HomeFragment ) getSupportFragmentManager().findFragmentById(R.id.homeFragment);
if(myFragment!= null) {
Toast.makeText(ActivityFilter.this, "Not null.", Toast.LENGTH_SHORT).show();
home.myMethod(); // this line is not accessed since myFragment is null
}else{
Toast.makeText(ActivityFilter.this, "Null fragment.", Toast.LENGTH_SHORT).show();
}
}
}
You should use a Callback.
Create a public interface in your fragment.
public interface iCommunicateListener{
void communicate(String msg);
}
You also have to make the activity your listener.
(You can have many listeners, but fragments are supposed to be reusable, so if you have many listeners it will not be as reusable as it could and should be)
private iCommunicateListener listener;
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
listener = (iCommunicateListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement iCommunicateListener");
}
}
Now you have active listener.
In your onClicks or whenever you want send information to your activity, you have to call listener.communicate("doSomething");
Your Activity must implement the iCommunicateListener.
After implementation of the method communicate you can choose your logic for the different Strings or whatever you want to send through the callback.
There are many other ways for communication between Activities and Fragments, but since you are just beggining learn this one. After you implement it and you see the result you can take a look at this library which will definately help you in your android development. EventBus
With EventBus you will not have to use the callbacks which will make your fragments even more reusable and flexible, but first learn the normal Callbacks. It is a basic pattern and you will use it in many different situations.
More on Fragments: Fragments
Hope this helps!
Can anyone kindly help me implement the opening of a new activity upon clicking of an ImageView. I have a code snippet displayed below.
public class TabFan extends Fragment {
//Overriden method onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
return inflater.inflate(R.layout.tab_fan, container, false);
// Onclick Listening
ImageView image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(this);
}
public void onClick(View v) {
// Launching new Activity on hitting the image
Intent j = new Intent(getApplicationContext(), Activity2.class);
startActivity(j);
// End intent
}
}
Ok I have a code with three tabs, the following controls my tabs which is working right.
public class Fans extends AppCompatActivity implements TabLayout.OnTabSelectedListener{
//This is our tablayout
private TabLayout tabLayout;
//This is our viewPager
private ViewPager viewPager;
ImageView image;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fans);
//Adding toolbar to the activity
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//Initializing the tablayout
tabLayout = (TabLayout) findViewById(R.id.tabLayout);
//Adding the tabs using addTab() method
tabLayout.addTab(tabLayout.newTab().setText("Fans"));
tabLayout.addTab(tabLayout.newTab().setText("Jersey"));
tabLayout.addTab(tabLayout.newTab().setText("Team"));
tabLayout.setTabGravity(TabLayout.GRAVITY_FILL);
//Initializing viewPager
viewPager = (ViewPager) findViewById(R.id.pager);
//Creating our pager adapter
Pager adapter = new Pager(getSupportFragmentManager(), tabLayout.getTabCount());
//Adding adapter to pager
viewPager.setAdapter(adapter);
viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
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) {
}
});
}
#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) {
}
}
I have another class pager
public class Pager extends FragmentStatePagerAdapter {
//integer to count number of tabs
int tabCount;
//Constructor to the class
public Pager(FragmentManager fm, int tabCount) {
super(fm);
//Initializing tab count
this.tabCount= tabCount;
}
//Overriding method getItem
#Override
public Fragment getItem(int position) {
//Returning the current tabs
switch (position) {
case 0:
TabFan tab1 = new TabFan();
return tab1;
case 1:
TabJersey tab2 = new TabJersey();
return tab2;
case 2:
TabTeam tab3 = new TabTeam();
return tab3;
default:
return null;
}
}
//Overriden method getCount to get the number of tabs
#Override
public int getCount() {
return tabCount;
}
}
Finally the interested raw class TabFan, now where exactly should that listener be implemented. I have tried the class Fans but apparently am getting some crush, TabFan seem not to work with the events too. Any help please.
public class TabFan extends Fragment {
//Overriden method onCreateView
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//Returning the layout file after inflating
//Change R.layout.tab1 in you classes
return inflater.inflate(R.layout.tab_fan, container, false);
// Onclick Listener
}
}
With the code that you have provided, you will need to do two things to properly link the image object to the onClick() method that you have written.
First, the Fragment class needs to implement the View.OnClickListener interface. This is what makes the onClick(View v)actually activate on a click when using setOnClickListener(this). Replace your class declaration line with:
public class TabFan extends Fragment implements View.OnClickListener {
Second, if you are going to add any more clickable objects to TabFan with setOnClickListener(this), then onClick(View v) needs to verify that it is dealing with the expected View:
#Override
public void onClick(View v) {
if (v.getId() == R.id.image) {
// Launching new Activity on hitting the image
Intent j = new Intent(getActivity().getApplicationContext(), Activity2.class);
startActivity(j);
// End intent
}
}
If you click Ctrl + Space keys, Android Studio will show you suggestion window and generate overriding methods like onClick for you.
image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent j = new Intent(getActivity(), Activity2.class);
startActivity(j);
}
});
Doesn't matter where you are, in Fragment or in Activity. ImageView just needs View.OnClickListener. for detecting click events override onClick method.
And another point when you need any context in fragment use getActivity() or getActivity().getApplicationContext()
What I like to do is setting up the onClick in the XML already like this:
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="yourMethod"
android:src="#drawable/yourpicture"/>
Then in your Fragment or Activity just implement yourMethod to open the new Activity:
public void yourMethod(View v) {
Intent intent = new Intent(this, ToOpenAcitivy.class);
startActivity(intent);
}
Also this site helped me a lot when learning about stuff like this.
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()