ViewPager具有固定宽度的子项

时间:2014-04-24 22:01:19

标签: android android-viewpager

我需要设计一个ViewPager能够传递固定宽度的孩子(例如宽度为700dp的孩子),不幸的是当前版本的ViewPager会自动使所有孩子的宽度达到MATCH_PARENT有没有办法将此功能添加到ViewPager

我的ViewPager布局:

<?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孩子布局:

<?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>

提前致谢...

6 个答案:

答案 0 :(得分:6)

可以使用FragmentPagerAdapter.getPageWidth缩放ViewPager中的页面。您将需要一个自定义FragmentPagerAdapter。如果返回0到1之间的数字,则缩小页面宽度&gt; 1相应地缩放页面。但这并不是很好,因为你不能在升级的页面中滚动图像。

如果将ImageView包装在HorizontalScrollView中,事情会好一些,您可以在页面中滚动图像,但如果您不是很快,则可以通过Horizo​​ntalScrollView捕获页面之间的滑动手势。请参阅this video

因此,解决方案是真正使用自定义Horizo​​ntalScrollView(请参阅InterceptingHorizontalScrollView),它不允许拦截onTouch事件,但在用户滚动到最后时也允许它(请参阅覆盖onOverScrolled)。有关差异,请参阅this video或下图

编辑您不需要覆盖onInterceptTouchEvent,因为Horizo​​ntalScrollView默认拦截它们(因此滚动图像的优先级高于分页。)

最后,这是所有代码:

<强> 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>

InterceptingHorizo​​ntalScrollView.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);
        }
    }
}

答案 1 :(得分:1)

您真正想要的是HorizontalScrollView内的ViewPager。这需要自定义触摸处理,因此您希望使用类似此类的内容:InterceptingHorizontalScrollView

要使InterceptingHorizontalScrollView ViewPager工作,您必须覆盖onOverScrolled

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

感谢Gyebro的提示。^

您的ViewPager子布局如下所示:

<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>

答案 2 :(得分:1)

你可以覆盖PagerAdapter的getWidth方法,如果这没有帮助,请看看: http://commonsware.com/blog/2012/08/20/multiple-view-viewpager-options.html

最重要的是尝试this example,效果很好! 只是沿着整个例子。

答案 3 :(得分:-1)

  • ViewPager子项将/应始终匹配它的父宽度。
  • 此外,使用700dp宽度ImageView听起来不错。在肖像模式下会是什么样子?

如果您不想让ViewPager本身变小,即您希望从屏幕的绝对侧滑动ImageViews,则必须使项目出现小。

可以通过创建另外两个LinearLayouts作为间隔符来完成模仿。然后看起来好像你的物品有特定的宽度。

这是一个示例(使用TextView):

<LinearLayout 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"
    android:orientation="horizontal">
    <LinearLayout
        android:background="#FFF"
        android:layout_weight="3"
        android:layout_width="0dp"
        android:layout_height="match_parent"/>

    <TextView
        android:layout_weight="10"
        android:background="#333"
        android:textColor="#FFF"
        android:textSize="50sp"
        android:gravity="center"
        android:text="HELLO"
        android:layout_width="0dp"
        android:layout_height="match_parent" />

    <LinearLayout
        android:background="#FFF"
        android:layout_weight="3"
        android:layout_width="0dp"
        android:layout_height="match_parent"/>
</LinearLayout>

这看起来像这样: ViewPager preview

答案 4 :(得分:-1)

将视图寻呼机的页边距设置为负值。这将强制页面进入视图寻呼机。请注意,它也会导致重叠,因此您将在视图寻呼机中看到下一个/上一个元素的一部分。

答案 5 :(得分:-1)

ViewPager通过 getPageWidth 方法查询每个页面宽度的给定适配器。所以你可以返回所需的宽度。这就是支持库v13的实现方式:

public class AdapterFragment extends FragmentPagerAdapter
{

    // other methods

    @Override
    public float getPageWidth(int position)
    {
        return 700f; // this is 700px, you can convert from DP or SP using TypedValues
    }
}

您还可以根据位置为不同的页面返回不同的宽度。