Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ViewPager with fixed width childs

I need to design a ViewPager which able to pass childs with fixed width (e.g childs with 700dp width), Unfortunately the current version of ViewPager will automatically makes all childrens width to MATCH_PARENT, is there any way to add this functionality to ViewPager?

My ViewPager layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <android.support.v4.view.ViewPager
        android:id="@+id/some_id"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:overScrollMode="never" />

</LinearLayout>

ViewPager childs layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/banner_main_layout_container"
    android:layout_width="700dp"
    android:layout_height="match_parent"
    android:background="#fff"
    android:gravity="center"
    android:orientation="vertical" >

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:src="some images"/>

</LinearLayout>

Thanks in Advance...

like image 587
NullPointer Avatar asked Apr 24 '14 22:04

NullPointer


People also ask

What the difference between ViewPager and ViewPager2?

ViewPager2 is an improved version of the ViewPager library that offers enhanced functionality and addresses common difficulties with using ViewPager . If your app already uses ViewPager , read this page to learn more about migrating to ViewPager2 .

How to set ViewPager in android?

Android ViewPager widget is found in the support library and it allows the user to swipe left or right to see an entirely new screen. Today we're implementing a ViewPager by using Views and PagerAdapter. Though we can implement the same using Fragments too, but we'll discuss that in a later tutorial.

What is the use of ViewPager?

Layout manager that allows the user to flip left and right through pages of data. You supply an implementation of a PagerAdapter to generate the pages that the view shows. ViewPager is most often used in conjunction with android.


3 Answers

It is possible to scale the pages within the ViewPager with FragmentPagerAdapter.getPageWidth. You will need a custom FragmentPagerAdapter. If you return a number between 0 and 1, the pages are scaled down, width > 1 scales pages up accordingly. But this is not really good, because you can't scroll the image within the up-scaled page.

If you wrap the ImageView in a HorizontalScrollView, things are a bit better, you can scroll the images within pages, but the swipe gesture between pages is caught by the HorizontalScrollView if you are not very fast. See this video.

So the solution is truly to use a custom HorizontalScrollView (see InterceptingHorizontalScrollView) which disallows intercepting the onTouch event, but also allows it when the User scrolls to the end (See overidden onOverScrolled). See this video or the image below for the difference.

EDIT You don't need to override onInterceptTouchEvent, because HorizontalScrollView intercepts them by default (so scrolling the image has higher priority than paging.)

Finally, here's all the code:

MainActivity.java

public class MainActivity extends Activity {

    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // Set up the ViewPager
        mViewPager = (ViewPager) findViewById(R.id.pager);
        mViewPager.setPageMargin(30);
        mViewPager.setAdapter(new ImagePagerAdapter(getFragmentManager()));
    }

    private class ImagePagerAdapter extends FragmentPagerAdapter {

        public ImagePagerAdapter(FragmentManager fm) {
            super(fm);
        }
        @Override
        public Fragment getItem(int i) {
            switch(i) {
                case 0:
                    return ImageFragment.newInstance(R.drawable.forest1);
                case 1:
                    return ImageFragment.newInstance(R.drawable.forest2);
                case 2:
                    return ImageFragment.newInstance(R.drawable.forest3);
                default:
                    return ImageFragment.newInstance(R.drawable.ic_launcher);
            }
        }
        @Override
        public int getCount() {
            return 3;
        }
        @Override
        public float getPageWidth(int position)
        {
            // Here it is possible to scale page width
            return super.getPageWidth(position);
        }
    }
}

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

ImageFragment.java

public class ImageFragment extends Fragment {
    private static final String ARG_PARAM1 = "image_resid";
    private int mImageResId;

    public static ImageFragment newInstance(int image_resid) {
        ImageFragment fragment = new ImageFragment();
        Bundle args = new Bundle();
        args.putInt(ARG_PARAM1, image_resid);
        fragment.setArguments(args);
        return fragment;
    }
    public ImageFragment() {
        // Required empty public constructor
    }
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mImageResId = getArguments().getInt(ARG_PARAM1);
        }
    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_image, container, false);
        ImageView imageView = (ImageView)v.findViewById(R.id.imageView);
        imageView.setImageResource(mImageResId);
        return v;
    }
}

fragment_image.xml

<com.gyebro.viewpagertest.InterceptingHorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="600dp"
    android:layout_height="match_parent"
    tools:context="com.gyebro.viewpagertest.ImageFragment">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:adjustViewBounds="true"
            android:id="@+id/imageView"
            android:src="@drawable/forest1" />
</com.gyebro.viewpagertest.InterceptingHorizontalScrollView>

InterceptingHorizontalScrollView.java

public class InterceptingHorizontalScrollView extends HorizontalScrollView {

    public InterceptingHorizontalScrollView(Context context) {
        super(context);
    }
    public InterceptingHorizontalScrollView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    public InterceptingHorizontalScrollView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    /*@Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        if (getParent() != null) {
            switch (ev.getAction()) {
                case MotionEvent.ACTION_MOVE:
                    getParent().requestDisallowInterceptTouchEvent(true);
                    break;
                case MotionEvent.ACTION_UP:
                case MotionEvent.ACTION_CANCEL:
                    getParent().requestDisallowInterceptTouchEvent(false);
                    break;
            }
        }
        return super.onInterceptTouchEvent(ev);
    }*/

    @Override
    protected void onOverScrolled (int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
        super.onOverScrolled(scrollX,scrollY,clampedX,clampedY);
        // if clampedX == true, we've reached the end of the HorizontalScrollView so
        // allow parent to intercept
        if(clampedX) {
            Log.d("InterceptingHorizontalScrollView", "Reached the end, allowing interception");
            getParent().requestDisallowInterceptTouchEvent(false);
        }
    }
}
like image 95
Gyebro Avatar answered Oct 07 '22 21:10

Gyebro


What you really want here is a HorizontalScrollView inside of a ViewPager. This requires custom touch handling, so you'll want to use something like this class: InterceptingHorizontalScrollView

To make InterceptingHorizontalScrollView work in a ViewPager, you'll have to override onOverScrolled:

@Override
protected void onOverScrolled (int scrollX, int scrollY, boolean clampedX, boolean clampedY) {
    super.onOverScrolled(scrollX,scrollY,clampedX,clampedY);
    if(clampedX) {
        getParent().requestDisallowInterceptTouchEvent(false);
    }
}

Thanks to Gyebro for this tip.^

Your ViewPager child layout would look like this:

<com.tumblr.widget.InterceptingHorizontalScrollView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <LinearLayout
        android:id="@+id/banner_main_layout_container"
        android:layout_width="700dp"
        android:layout_height="match_parent"
        android:background="#fff"
        android:gravity="center"
        android:orientation="vertical" >

        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="some images"/>

    </LinearLayout>
</com.tumblr.widget.InterceptingHorizontalScrollView>
like image 43
Paul Burke Avatar answered Oct 07 '22 19:10

Paul Burke


You can either override PagerAdapter´s getWidth method and if this does not help, look at this: http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html

and most importantly try this example, it works great! Just go along the whole example.

like image 27
vandus Avatar answered Oct 07 '22 20:10

vandus