Search code examples
androidandroid-viewpagerandroid-tabs

ViewPager & tabs: Delay after clicking tab


i wrote a FragmentActivity with a ViewPager, i did not want to use the actionbar for the tabs (because i did not want the tabs to be positioned over the menu) and also not the PagerTabStrip solution, because i could not customize it as i wanted.

so i wrote an own linearlayout as tabs container:

<LinearLayout
    android:id="@+id/main_tabs"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@color/white"
    android:orientation="horizontal" >
</LinearLayout>

with an View.OnClickListener for each of each tab

OnClickListener onClickListener = new View.OnClickListener() {
        @Override
        public void onClick(final View view) {
            mapTabs.get(lastSelectedTab).setSelected(false);
            view.setSelected(true);

            Runnable runnable = new Runnable() {                    
                @Override
                public void run() {
                    int index = Integer.parseInt(view.getTag().toString());
                    FragmentActivity.setTab(index);
                    lastSelectedTab = index;
                }
            };
            handler.post(runnable);                 
        }
    };
}



public static void setTab(int index) {      
    FragmentActivity.viewPager.setCurrentItem(index, true); // true or false does not make any difference
}

this is the method i wrote to add the single tabs to the tab container (main_tabs):

private void addTab(LayoutInflater inflater, ViewGroup tabs, int imageId, View.OnClickListener onClickListener) {
    inflater.inflate(R.layout.main_tab, tabs);
    int index = tabs.getChildCount() - 1;
    ImageView ivTab = (ImageView) tabs.getChildAt(index);
    ivTab.setTag(String.valueOf(index)); // stored the tab index
    ivTab.setImageResource(imageId); 
    ivTab.setOnClickListener(onClickListener);
    mapTabs.put(index, ivTab); // add an imageview to the tab
}

i used the runnalbe so that i see the highlighting of the tab immediately, and not after the slight delay when the new page appears. i also stored the last selected tab in order to deselect it when the new one gets selected.

i store all tabs in a map in order to access them later for selection.

this is the OnPageChangeListener i wrote (to highlight the associated tab):

viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {

        @Override
        public void onPageSelected(int position) {              
            mapTabs.get(position).setSelected(true); // selected the tag asociated with the current visible page
            mapTabs.get(lastSelectedTab).setSelected(false); // deselectes the last selected tab
            lastSelectedTab = position;
            ListFragment<?> item = FragmentActivity.fragmentAdapter.getItem(position);
            setTitle(item.getTitle());          
        }

        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        }

        @Override
        public void onPageScrollStateChanged(int state) {

        }
    });

everything works fine, i am just not clear about the performance:

when i scroll to the next page, everything goes very fast and smooth. the next page appears immediately without any dealy; only the menu in the action bar (created in the onCreateOptionsMenu(Menu menu, MenuInflater inflater) method of each Fragment) appears with a slight delay (about 500-700 ms).

but when i click on one of the tabs, the selected page appears not immediately but with a slight delay (actually the same time the menu needs to appear as mentioned above: menu and page appear together at the same time). bzw. this happens also when i use the tabstrip solution.

i guess if its possible to achieve a delay-less page change by scrolling, it should be possible somehow to achieve the same performance for the tab clicks.

but what do i do wrong? and is there a possibility to make the menu appear immediately just like the pages when scrolling? can the different menus not be cached just like the pages?


Solution

  • the solution was extremely simple. i just had to keep all my 4 tabs in the ViewPager so that they don't need to get recreated (and therefore don't cause the short delay after each tab-clicki). i just had to add following lines to the onCreate method.

    viewPager = (ViewPager) findViewById(R.id.pager);
    viewPager.setOffscreenPageLimit(4);