0

I am beginner to android application development. I have implemented a Tablayout in my HomeActivity Layout along with a Viewpager and title to display selected fragment in TextView. The I have placed three Tabitems inside the layout. I was implementing updating Activity title to display on toolbar on clicking a tab button and found a solution this link

activity_home.xml

android.support.design.widget.TabLayout
    android:id="@+id/tabLayout"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="1.0"
    app:layout_constraintStart_toStartOf="parent"
    app:tabSelectedTextColor="@color/clinividPink"
    app:tabTextAppearance="@style/MineCustomTabText">

    <android.support.design.widget.TabItem
        android:id="@+id/contactsTabButton"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:icon="@drawable/contacts_tab_state"
        android:text="@string/contacts_tab_name" />

    <android.support.design.widget.TabItem
        android:id="@+id/casesTabButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:icon="@drawable/cases_tab_state"
        android:text="@string/cases_tab_name" />

    <android.support.design.widget.TabItem
        android:id="@+id/profileTabButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:icon="@drawable/profile_tab_state"
        android:text="@string/profile_tab_name" />
</android.support.design.widget.TabLayout>

<android.support.v4.view.ViewPager
    android:id="@+id/contactsVIew"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toTopOf="@+id/tabLayout"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/toolbar2" />

<TextView
    android:id="@+id/home_activity_title"
    android:layout_width="wrap_content"
    android:layout_height="0dp"
    android:layout_marginStart="8dp"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="12dp"
    android:layout_marginBottom="12dp"
    android:text="Contacts"
    android:textSize="18sp"
    android:textStyle="bold"
    app:layout_constraintBottom_toBottomOf="@+id/toolbar2"
    app:layout_constraintEnd_toEndOf="@+id/toolbar2"
    app:layout_constraintStart_toStartOf="@+id/toolbar2"
    app:layout_constraintTop_toTopOf="@+id/toolbar2" />

The viewpager is filled with the Fragment adapter conditionally with 3 different fragments.

HomeTabLayoutAdapter.java

public class HomeTabLayoutAdapter extends FragmentPagerAdapter {

private Context myContext;
int totalTabs;

private static final String LOG_TAG = HomeTabLayoutAdapter.class.getSimpleName();

public HomeTabLayoutAdapter(FragmentManager fm, Context myContext, int totalTabs) {
    super(fm);
    this.myContext = myContext;
    this.totalTabs = totalTabs;
}

@Override
public Fragment getItem(int position) {
    switch (position) {
        case 0: {
            Log.d(LOG_TAG, "\nFragment: 0 - Contacts");


            ContactsFragment contactsFragment = new ContactsFragment();
            return contactsFragment;
        }
        case 1: {
            Log.d(LOG_TAG, "\nFragment: 1 - Cases ");
            CasesFragment casesFragment = new CasesFragment();
            return casesFragment;
        }
        case 2: {
            Log.d(LOG_TAG, "\nFragment: 2 - Profile");
            ProfileFragment profileFragment = new ProfileFragment();
            return profileFragment;
        }
        default: {
            Log.d(LOG_TAG, "\nFragment: default");
            return new Fragment();
        }

    }
}

@Override
public int getCount() {
    return totalTabs;
}
}

My fragments look something like this

SampleFragment.java

public class CasesFragment extends Fragment {
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";

private static final String LOG_TAG = CasesFragment.class.getSimpleName();


// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;

private OnFragmentInteractionListener mListener;

public CasesFragment() {
    // Required empty public constructor
}

public static CasesFragment newInstance(String param1, String param2) 
{
        CasesFragment fragment = new CasesFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
        // Inflate the layout for this fragment

        View casesFragmentView = inflater.inflate(R.layout.fragment_cases, container, false);

        Log.d(LOG_TAG, "\nCASES listener: " + mListener);

        if (mListener != null) {
            mListener.onFragmentInteraction("Cases");
        }
        return casesFragmentView;
    }

    // TODO: Rename method, update argument and hook method into UI event
    public void onButtonPressed(Uri uri) {
        if (mListener != null) {
            mListener.onFragmentInteraction(uri);
        }
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        if (context instanceof OnFragmentInteractionListener) {
            mListener = (OnFragmentInteractionListener) context;
        } else {
            throw new RuntimeException(context.toString()
                + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        // TODO: Update argument type and name
        void onFragmentInteraction(Uri uri);
        String onHomeAndFragment1Listener(String title); // increment number in name for each fragment interface

    }
}

In my HomeActivity.java implements the OnFragmentInteractionListener for all three fragments like this

public class HomeActivity
    extends AppCompatActivity
    implements ContactsFragment.OnFragmentInteractionListener,
               ProfileFragment.OnFragmentInteractionListener,
               CasesFragment.OnFragmentInteractionListener
{

TabLayout tabLayout;
ViewPager viewPager;
TextView homeActivityTitleView;

private static final String LOG_TAG = HomeActivity.class.getSimpleName();


@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_home);

    tabLayout=(TabLayout)findViewById(R.id.tabLayout);
    viewPager=(ViewPager)findViewById(R.id.contactsVIew);
    homeActivityTitleView=(TextView) findViewById(R.id.home_activity_title);

    final HomeTabLayoutAdapter adapter = new HomeTabLayoutAdapter(getSupportFragmentManager(), this, tabLayout.getTabCount());
    viewPager.setAdapter(adapter);

    viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            Log.d(LOG_TAG, "\nSELECTED tab: " + tab.getPosition());
            viewPager.setCurrentItem(tab.getPosition());
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            Log.d(LOG_TAG, "\nUNSELECTED tab: " + tab.getPosition());
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
            Log.d(LOG_TAG, "\nRESELECTED tab: " + tab.getPosition());
        }
    });
    viewPager.setCurrentItem(1);
}


@Override
public String onHomeAndCasesInteraction(String title) {
    Log.d(LOG_TAG, "\nUpdate title: " + title);

    homeActivityTitleView.setText(title);
    return title;
}

@Override
public String onHomeAndContactsInteraction(String title) {;
    Log.d(LOG_TAG, "\nUpdate title: " + title);

    homeActivityTitleView.setText(title);
    return title;
}

@Override
public String onHomeAndProfileInteraction(String title) {
    Log.d(LOG_TAG, "\nUpdate title: " + title);

    homeActivityTitleView.setText(title);
    return title;
}

@Override
public void onFragmentInteraction(Uri uri) {
}

}

The tablayout UI is working fine but the activity title in my activity_home.xml does not work as expected when I click on the middle tab. it either display the text of the left or right tab depending on the case which was previous tab selected. I have tried to add as much formatting as possible for time being but if you guys need more info, tell me in the comments and I will update.

P.S I have tried experiment with adding a 4th tab and another fragment and the results are even more unpredictable than with 3 tabs. Please someone help me.

UPDATE answer:

Abhisheik's answer works and I changed my tabLayout.addOnTabSelectedListener in my HomeActivity.java as following and removed calls to update title from onCreateView of each fragment.

tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            Log.d(LOG_TAG, "\nSELECTED tab: " + tab.getPosition());
            viewPager.setCurrentItem(tab.getPosition());
            switch (tab.getPosition()) {
                case 0: onHomeAndContactsInteraction("Contacts"); return;
                case 1: onHomeAndCasesInteraction("Cases"); return;
                case 2: onHomeAndProfileInteraction("Profile"); return;
                default: onHomeAndCasesInteraction("Cases"); return;
            }
        }

        @Override
        public void onTabUnselected(TabLayout.Tab tab) {
            Log.d(LOG_TAG, "\nUNSELECTED tab: " + tab.getPosition());
        }

        @Override
        public void onTabReselected(TabLayout.Tab tab) {
            Log.d(LOG_TAG, "\nRESELECTED tab: " + tab.getPosition());
        }
    });
Savitoj Cheema
  • 460
  • 2
  • 9
  • 22

1 Answers1

0

When fragments are used with Tabs, some of the initial tab's fragments are instantiated parallelly. So invoking the interactionListener's method in onCreateView of fragments won't help.

If you need to know which tab is selected, you can add a listener on tabLayout of your activity

    tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
        @Override
        public void onTabSelected(TabLayout.Tab tab) {
            //do stuff here
        }

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

        }

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

        }
    });  
  • My question is so when should I use the onCreateView of a fragment, if they are all running in parallel – Savitoj Cheema Mar 25 '19 at 14:08
  • @XavitojCheema onCreateView is called to have the fragment instantiate its user interface view. One can do all the view initialisation related stuff here and return the view of the fragment layout. In your case tabLayout is part of activity's layout not the fragment's layout. – Abhishek Gupta Mar 26 '19 at 04:58