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...
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 .
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.
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.
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);
}
}
}
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>
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With