dudeldidadum
dudeldidadum

Reputation: 1281

Horizontal scrollable ViewPager

I want to create a horizontal scrollable ViewPager. My ViewPager contains Fragments. Each Fragment's width is larger than the screen so scrolling has to be enabled.

I use following layout for my fragment item:

<HorizontalScrollView
        android:id="@+id/view_horizontal_scroll"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:isScrollContainer="true" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:orientation="horizontal" >

            <View
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:background="#AABBCC" />

            <View
                android:id="@+id/test"
                android:layout_width="1500dp"
                android:layout_height="fill_parent" />

            <View
                android:layout_width="100dp"
                android:layout_height="fill_parent"
                android:background="#ccBBaa" />
        </LinearLayout>
    </HorizontalScrollView>

I also created a custom ViewPager which allows horizontal scrolling:

public class ScrollableViewPager extends ViewPager {

    private GestureDetector mGestureDetector;

    public ScrollableViewPager(Context context, AttributeSet attrs) {
        super(context, attrs);
        mGestureDetector = new GestureDetector(getContext(),
                new YScrollDetector());
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        // Tell our parent to stop intercepting our events!
        getParent().requestDisallowInterceptTouchEvent(true);

        return super.onInterceptTouchEvent(ev)
                && mGestureDetector.onTouchEvent(ev);
    }
}

The YScrollDetector only overwrites the onScrollMethod. So far so good. Horizontal Scrolling works fine.

But now I have a problem:

Let's say I have a ViewPager with 5 Fragments, ([0], [1], [2], [3], [4]) in it and want to start with item [2]. When I siwpe backwards I want that the scroll position of the previous item [1] is at right maximum and not 0.

My Framgents look like this:

public class AbstractFragment extends Fragment {

    private static final String _ID = "ID";
    private int _id;
    private ScrollableViewPager mPager;

    public AbstractFragment() {

    }

    public AbstractFragment(int id, int colorId) {
        this._id = id;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.d(getClass().getSimpleName(), "[" + _id + "]: onCreate");
        super.onCreate(savedInstanceState);

        if (savedInstanceState != null) {
            _id = savedInstanceState.getInt(_ID);
        }
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {

        View fragmentView = inflater.inflate(R.layout.fragment_menu_container,
                container, false);

        setUpScrollView(fragmentView);

        return fragmentView;
    }

    @Override
    public void onResume() {
        Log.d(getClass().getSimpleName(), "[" + _id + "]: onResume");
        setUpScrollView(getView());
        super.onResume();
    }

    private void setUpScrollView(View fragmentView) {
        if (fragmentView == null) {
            return;
        }
        HorizontalScrollView scrollView = (HorizontalScrollView) fragmentView
                .findViewById(R.id.view_horizontal_scroll);

        if (scrollView != null) {
            int currentItem = getCurrentPagerItem();
            if (_id < currentItem) {
                // previous Item : X Scroll: width of content
                View content = scrollView.getChildAt(0);
                int width = content.getRight();
                width = width - scrollView.getRight();
                scrollView.scrollTo(width, 0);
                Log.d(getClass().getSimpleName(), "[" + _id + "] width: "
                        + width);
                // scrollView.fullScroll(View.FOCUS_RIGHT);
            } else if (_id > currentItem) {
                // next Item - X Scroll: 0
                scrollView.fullScroll(View.FOCUS_LEFT);
            } else {
                // current Item - Nothing to do her
            }

        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);

        if (outState == null) {
            return;
        }

        outState.putInt(_ID, _id);
    }

    private ScrollableViewPager getPager() {
        PagerActivity activity = (PagerActivity) getActivity();
        return activity.getViewPager();
    }

    private int getCurrentPagerItem() {
        if (mPager == null) {
            mPager = getPager();
        }

        return mPager.getCurrentItem();
    }
}

In my fragments I want to set the scroll position of the previous fragment. But this doesn't work, because the width of the ScrollView and the ContentView are both 0.

Does anybody know an answer? Thanks!!!

Upvotes: 1

Views: 2981

Answers (1)

dudeldidadum
dudeldidadum

Reputation: 1281

I found a solution by myself:

private void setUpScrollView(final ViewGroup fragmentView) {
        if (fragmentView == null) {
            return;
        }

        fragmentView.getViewTreeObserver().addOnGlobalLayoutListener(
                new OnGlobalLayoutListener() {
                    @Override
                    public void onGlobalLayout() {
                        HorizontalScrollView scrollView = (HorizontalScrollView) fragmentView
                                .findViewById(R.id.view_horizontal_scroll);

                        if (scrollView != null) {
                            int currentItem = getCurrentPagerItem();
                            if (_id < currentItem) {
                                // previous Item
                                View content = scrollView.getChildAt(0);
                                int width = content.getWidth();
                                width = width - scrollView.getWidth();
                                scrollView.scrollTo(width, 0);
                            } else if (_id > currentItem) {
                                // next Item
                                scrollView.scrollTo(0, 0);
                            } else {
                                // current Item
                            }

                        }
                    }
                });

    }

Upvotes: 2

Related Questions