8

I need to design the following screen, and I need your advice:

enter image description here

Explanation:

The title is static/fixed and I don't need to do anything with it.

Yellow: this is the interesting part, I need to design a ViewPager like screen that has the capability to scroll left/right for Max 4 screens.

Red: In every screen I need to add a Table/Grid that can be scrollable as well if it's not fits screen size.

Green: The page switching can be done using the green buttons in the bottom of the screen or by scrolling the ViewPager.

The Question Is: Can this behavior be achieve using a ViewPager or should I use Fragments? If Fragment is the way to go, then how would I implement the page switching using the sliding gesture? if it's a ViewPager then how to add the inside scrolling and how to control it using the buttons at the bottom?

Any help would be appreciated, Thanks.

Emil Adz
  • 40,709
  • 36
  • 140
  • 187
  • If those tables/grids need to be scrollable on the X axis(filling the entire width) then I don't know how you could implement this as you'll not be able to decide which widget should be allowed to be scrolled. If the tables/grids will be scrollable only vertically than use a `ViewPager`. – user Mar 13 '13 at 13:35
  • actually I have stumbled upon the following link: http://stackoverflow.com/questions/6920137/android-viewpager-and-horizontalscrollview and people say there that it possible, I never tried it so I opened this question to see people opinions, and maybe get an idea of what way would be better. – Emil Adz Mar 13 '13 at 13:41

2 Answers2

7

I think this should be tackled with a Non Swipeable ViewPager. There is no way the view pager and the underlying Fragments should respond to the swiping gesture. The methods to override to disable swiping within the ViewPager are:

  1. onTouchEvent() - returns false.
  2. onInterceptTouchEvent()- returns false.

Refer to this SO question for more information on how to achieve this.

Next up you want to be using Fragments within each of your pager holders. So we're building the following layout:

Within the parent activity a FragmentPagerAdapter is instantiated and your tabs added with a tag:

Activity changes

@Override
protected void onCreate(final Bundle saveInstanceState) {
    final FragmentPagerAdapter myTabAdapter = new MyFragmentPagerAdapter(
            <Your ViewPager View>, <Your activity context, this>);
    myTabAdapter.addTab(getActionBar().newTab(), "YOUR TAG", "Your Title");
    // etc...
}

So this gives us the frame of the diagram above. A hosting activity, containing a ViewPager and the underlying tabs. Next up is getting the Fragments (containing your tables) into each of the respective tabs. This is handled by the FragmentPagerAdapter implementation:

Fragment adapter (inner class to activity):

private class MyFragmentPagerAdapter extends FragmentPagerAdapter implements
        ActionBar.TabListener, ViewPager.OnPageChangeListener {

    /**
     * Constructs a pager adapter to back a {@link ViewPager}.
     * 
     * @param pager
     *            The {@link ViewPager} widget.
     * @param activityContext
     *            The context the widget is being added under.
     */
    public SpotMenuFragmentPagerAdapter(final ViewPager pager,
            final Context activityContext) {
        super(getFragmentManager());
        pager.setAdapter(this);
        this.context = activityContext;
    }

    /**
     * Adds a tab to the hosting activity action bar.
     * 
     * @param newTab
     *            The tab to add.
     * @param tag
     *            The tab tag for id purposes.
     * @param label
     *            The label of the tab displayed to the user.
     */
    public void addTab(final ActionBar.Tab newTab, final String tag,
            final String label) {
        newTab.setTag(tag);
        newTab.setText(label);
        newTab.setTabListener(this);
        getSupportActionBar().addTab(newTab);
    }

    /**
     * This is where you do the work of building the correct fragment based
     * on the tab currently selected.
     * 
     * @see FragmentPagerAdapter#getItem(int)
     */
    @Override
    public Fragment getItem(final int position) {
        final Tab tab = getActionBar().getTabAt(position);
        if ("MY TAG".equals(tab.getTag().toString()) {
            // instantiate the fragment (table) for "MY TAG"
        } else {
            // instantiate something else...
        }
    }

    /**
     * One fragment per tab.
     * 
     * @see android.support.v4.view.PagerAdapter#getCount()
     */
    @Override
    public int getCount() {
        return getSupportActionBar().getTabCount();
    }

    /**
     * @see ViewPager.OnPageChangeListener#onPageScrollStateChanged(int)
     */
    @Override
    public void onPageScrollStateChanged(final int arg0) {
        // No-op.
    }

    /**
     * @see ViewPager.OnPageChangeListener#onPageScrolled(int, float, int)
     */
    @Override
    public void onPageScrolled(final int arg0, final float arg1,
            final int arg2) {
        // No-op.
    }

    /**
     * @see ViewPager.OnPageChangeListener#onPageSelected(int)
     */
    @Override
    public void onPageSelected(final int position) {
        getSupportActionBar().setSelectedNavigationItem(position);
    }

    /**
     * @see TabListener#onTabSelected(app.ActionBar.Tab,
     *      app.FragmentTransaction)
     */
    @Override
    public void onTabSelected(final Tab tab, final FragmentTransaction ft) {
        viewPager.setCurrentItem(tab.getPosition());
    }

    /**
     * @see TabListener#onTabUnselected(ActionBar.Tab,
     *      app.FragmentTransaction)
     */
    @Override
    public void onTabUnselected(final Tab tab, final FragmentTransaction ft) {
        // No-op.
    }

    /**
     * @see TabListener#onTabReselected(ActionBar.Tab,app.FragmentTransaction)
     */
    @Override
    public void onTabReselected(final Tab tab, final FragmentTransaction ft) {
        // No-op.
    }
}

So hopefully by this point we have an activity hosting a 'non-swipeable' view pager and a mechanism for switching tabs in the form of the tab bar underneath the title (or alongside depending on the screen size). From this point I am sure you could customise to replace the tab bar with some navigational arrows.

Note: A lot of that was written from memory but hopefully I've conveyed the gist of where I would go with this.

Update

In response to the updated question: you can set the tab to be any old view. Set the TabSpec accordingly. Apologies I haven't used this myself.

Community
  • 1
  • 1
BrantApps
  • 6,362
  • 2
  • 27
  • 60
  • actually there is a solution for swipe problem you are talking about, look at this post: http://stackoverflow.com/questions/6920137/android-viewpager-and-horizontalscrollview, I have not checked it yet. But if I use a ViewPager, and I don't have an action bar, How do I place my page switching buttons in the bottom of the screen and customize them? – Emil Adz Mar 18 '13 at 20:31
  • @EmilAdz - Here is a [non-action bar example](http://developer.android.com/reference/android/support/v4/app/FragmentStatePagerAdapter.html) – BrantApps Mar 19 '13 at 00:19
  • what is the diffrence between "FragmentStatePagerAdapter" and "FragmentPagerAdapter"? – Emil Adz Mar 19 '13 at 08:39
  • Hey Emil- I could repeat the docs here but the explanations are easy to get at. The ````FragmentStatePagerAdapter```` is kinder to memory when considering many pages at the expense of slower initialisation of the fragment (by virtue of the fact that only the state - not the entire component - is held in memory) – BrantApps Mar 19 '13 at 09:42
  • so for my case (4 fragments at most) it will be better (from point of performance) to use FragmentPagerAdapter? – Emil Adz Mar 19 '13 at 10:03
  • Yes. The two are interchangeable with the underlying implementation transparent to the developer. – BrantApps Mar 19 '13 at 10:19
  • I'm still struggling with the horizontal swap, but the bounty is yours for you informative answer on FragmentViewPager that helped to do a lot of work on this screen. Thank you. – Emil Adz Mar 25 '13 at 14:22
3

You have to use HorizontalScrollView which it'll contain a LinearLayout and the Linear is the one that will contain your individual elements

The XML would see something like this

 <HorizontalScrollView
        android:id="@+id/horizontal_scroll_parent"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="horizontal"
        android:scrollbarStyle="outsideInset">

       <LinearLayout android:id="@+id/content_scroll"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:orientation="horizontal"
                android:gravity="center_vertical" />

</HorizontalScrollView>
  • 1
    Thats the wrong way. Use Fragements and not overloaded Layouts with need 1 sec to load. – Orri May 20 '14 at 06:35