Help to migrate from Actionbar.Tabs to Viewpager because of API 21

Asked

Viewed 216 times

1

From what I understand, the hosting of tabs in actionbar has become obsolete in API 21. I still don’t understand why (if someone explains it better I appreciate it) but what I can do is adapt. I did some research and found some alternatives like Sliding Tabs Google Play with Viewpager, although I never used Viewpager because Actionbar.Tab served me very well.

But I have some problems and doubts in the implementation because this tool seems to be very good for static tabs. The thing is, my app has very dynamic tabs. Because it is a chat app with each conversation being displayed by a Fragment, new tabs appear and are removed at all times.

I couldn’t quite align Viewpager’s strategy with this scenario. I noticed that the way Adapter identifies the selected tab is very different from the actionbar tablistener and I also did not find methods that add or remove tabs in Adapter or Slidingtabs. I thought of storing Fragments in an Arraylist to be used by the Adapter but I don’t know if the Adapter would identify when I remove or add a Fragment from there. Another issue that streamlines tabs is that users' nicknames related to the conversation are displayed on them, and this nick can also change at any time. I’m not sure when the getPageTitle() method is called.

Thinking about these differences I decided to come here to ask for help because maybe there is a better alternative to this case that I do not know yet or some good practice that makes this scenario viable.

Any help is welcome. Thank you very much.

1 answer

2

Hello, first I would like to say about my experience regarding Dynamic Fragments within the Viewpager and I can tell you that is not a good idea. I have no idea what your app looks like but if advice were good (rsrs) I would tell you to think about how most messaging apps work (Hangouts, fb messenger, Whatsapp, Telegram, etc.), where there is a Fragment that lists the conversations and another Fragment/Activity that shows the conversation. I also think about usability, for example: I have 10 Tabs/ Open Conversations and in order to open the 9th I need to scroll the Viewpager until I get there O_o

But clarifying how Viewpager works, you should think about its structure. First xml:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.astuetz.PagerSlidingTabStrip
        android:id="@+id/sliding_tabs"
        android:layout_width="match_parent"
        android:layout_height="?actionBarSize"
        android:layout_gravity="top"
        android:textSize="16sp"
        android:background="@color/color_primary"
        app:pstsIndicatorColor="@color/color_primary_darker"
        app:pstsTextAllCaps="false"
        app:pstsIndicatorHeight="2dp"
        app:pstsPaddingMiddle="false"/>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="0px"
        android:layout_weight="1"
        android:background="@android:color/white"/>

</LinearLayout>

Very simple where you indicate where the Tabs will be (title or any layout you want) and your Viewpager which is where all your Fragments will be added.

Then, in the Fragment/Activity you want to implement Viewpager you must create an Adapter for it and set Viewpager in Slidingtab:

mPager = (ViewPager) v.findViewById(R.id.viewpager);
mPagerTab = (PagerSlidingTabStrip) v.findViewById(R.id.sliding_tabs);
mPager.setAdapter(new ViewPagerAdapter(getActivity().getSupportFragmentManager(), tabtitles, mDrawable));
mPagerTab.setViewPager(mPager);

And a simple example of a Fragmentpageradapter:

public class ViewPagerAdapter extends FragmentPagerAdapter {

    final int PAGE_COUNT = 3;
    private String titles[];

    public ViewPagerAdapter(FragmentManager fm, String[] titles) {
        super(fm);
        titles = titles;
    }

    @Override
    public Fragment getItem(int position) {
        switch (position) {
            case 0:
                return SampleFragment.newInstance();
            case 1:
                return SampleFragment.newInstance();
            case 2:
                return SampleFragment.newInstance();

        }
        return null;
    }

    public CharSequence getPageTitle(int position) {
        return titles[position];
    }

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

}

What determines the amount of Fragments in Viewpager, in this case* is the PAGE_COUNT field;

It is possible yes you keep changing the amount of Fragments in your Adapter for this you need to create it by passing as parameter the amount of Fragments you want and a list with the Fragments you want to use. Or you can also create these methods within the Adapter, modify them and inform the controller by the method notifyDataSetChanged(); of the Adapter.

In this example I used the framework https://github.com/jpardogo/PagerSlidingTabStrip

  • So in my case this PAGE_COUNT could no longer be final, it will vary. And for me to better understand, if I want to add or remove a tab, I certainly have an Arraylist<Fragment> to store the Fragments and if there is any change, I call notifyDataSetChanged()?

  • That’s right. It works the same way you can on a Listview with a Basedapter

  • Looking that way can even get simpler than with actionbar.tabs. That is, if it works.

  • Rafael, how do I know the name of the selected tab?

  • You can use the method getCurrentItem() from Viewpager that returns an integer.

  • Could you tell me what is the difference between this Sliding tabs from jpardogo to that of astuetz and which I should use and pq? Thank you very much Rafael.

  • Basically jpardogo is based on Material Design and astuetz on Holo Theme (standard theme of ICS, JB and KK)

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.