转载自:http://blog.csdn.net/tiantianshangcha/article/details/50804954
项目里头需要用到一个在垂直方向滑动页签的效果, 这可难道宝宝了,不过google 还是强大的 , 在stackoverflow 找到了人生的真谛。
具体链接 传送门
特么的里面居然出现了四五种方案,选择困难症啊。。。。。。
实验了其中的两种,效果上均可行,另外两种均是github的项目,没细看,有兴趣的可以去做对比
地址 VerticalViewPager VerticalViewPager2
再详细看下我实验过的两种方案,
方案一:
旋转 viewpager 旋转viewpager的Item (高能~~~~~~~)
- 1、onInstantiateItem() of PagerAdapter, create the view and rotate it by -90:
- view.setrotation(-90f)
- </pre><pre code_snippet_id="1597557" snippet_file_name="blog_20160304_3_7176190" name="code" class="java">If you are using FragmentPagerAdapter, then:
- objFragment.getView().setRoration(-90)
- 2、Rotate ViewPager view by 90 degree:
- objViewPager.setRotation(90)
You can use a ViewPager.PageTransformer to give the illusion of a vertical ViewPager
. To achieve scrolling with a vertical instead of a horizontal drag you will have to override ViewPager
's default touch events and swap the coordinates of MotionEvent
s prior to handling them, e.g.:
- /**
- * Uses a combination of a PageTransformer and swapping X & Y coordinates
- * of touch events to create the illusion of a vertically scrolling ViewPager.
- *
- * Requires API 11+
- *
- */
- public class VerticalViewPager extends ViewPager {
- public VerticalViewPager(Context context) {
- super(context);
- init();
- }
- public VerticalViewPager(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
- private void init() {
- // The majority of the magic happens here
- setPageTransformer(true, new VerticalPageTransformer());
- // The easiest way to get rid of the overscroll drawing that happens on the left and right
- setOverScrollMode(OVER_SCROLL_NEVER);
- }
- private class VerticalPageTransformer implements ViewPager.PageTransformer {
- @Override
- public void transformPage(View view, float position) {
- if (position < -1) { // [-Infinity,-1)
- // This page is way off-screen to the left.
- view.setAlpha(0);
- } else if (position <= 1) { // [-1,1]
- view.setAlpha(1);
- // Counteract the default slide transition
- view.setTranslationX(view.getWidth() * -position);
- //set Y position to swipe in from top
- float yPosition = position * view.getHeight();
- view.setTranslationY(yPosition);
- } else { // (1,+Infinity]
- // This page is way off-screen to the right.
- view.setAlpha(0);
- }
- }
- }
- /**
- * Swaps the X and Y coordinates of your touch event.
- */
- private MotionEvent swapXY(MotionEvent ev) {
- float width = getWidth();
- float height = getHeight();
- float newX = (ev.getY() / height) * width;
- float newY = (ev.getX() / width) * height;
- ev.setLocation(newX, newY);
- return ev;
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev){
- boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
- swapXY(ev); // return touch coordinates to original reference frame for any child views
- return intercepted;
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- return super.onTouchEvent(swapXY(ev));
- }
- }
这两种方法基本效果都OK,接下来是我们举一反三的阶段了,我要封装一个支持横向纵向都可以滑动的ViewPager,基本思路就是自定义一个属性,来选择代码到底走垂直ViewPager代码还是水平ViewPager代码
- package com.xiaowu.banner.demo;
- import android.content.Context;
- import android.content.res.TypedArray;
- import android.support.v4.view.ViewPager;
- import android.util.AttributeSet;
- import android.view.MotionEvent;
- import android.view.View;
- public class HorizonVerticalViewPager extends MyViewPager{
- private boolean isVertical = false;
- public HorizonVerticalViewPager(Context context) {
- super(context);
- init();
- }
- public HorizonVerticalViewPager(Context context, AttributeSet attrs) {
- super(context, attrs);
- initIsVertical(attrs, 0);
- init();
- }
- public HorizonVerticalViewPager(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs);
- initIsVertical(attrs, defStyle);
- init();
- }
- private void initIsVertical(AttributeSet attrs, int defStyle){
- final TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyViewPager, defStyle, 0);
- isVertical = a.getBoolean(R.styleable.MyViewPager_isVertical, false);
- System.out.println("isVertical=>" + isVertical);
- a.recycle();
- }
- private void init() {
- if(isVertical){
- // The majority of the magic happens here
- setPageTransformer(true, new VerticalPageTransformer());
- // The easiest way to get rid of the overscroll drawing that happens on the left and right
- setOverScrollMode(OVER_SCROLL_NEVER);
- }
- }
- private class VerticalPageTransformer implements ViewPager.PageTransformer {
- @Override
- public void transformPage(View view, float position) {
- if (position < -1) { // [-Infinity,-1)
- // This page is way off-screen to the left.
- view.setAlpha(0);
- } else if (position <= 1) { // [-1,1]
- view.setAlpha(1);
- // Counteract the default slide transition
- view.setTranslationX(view.getWidth() * -position);
- //set Y position to swipe in from top
- float yPosition = position * view.getHeight();
- view.setTranslationY(yPosition);
- } else { // (1,+Infinity]
- // This page is way off-screen to the right.
- view.setAlpha(0);
- }
- }
- }
- /**
- * Swaps the X and Y coordinates of your touch event.
- */
- private MotionEvent swapXY(MotionEvent ev) {
- float width = getWidth();
- float height = getHeight();
- float newX = (ev.getY() / height) * width;
- float newY = (ev.getX() / width) * height;
- ev.setLocation(newX, newY);
- return ev;
- }
- @Override
- public boolean onInterceptTouchEvent(MotionEvent ev){
- if (isVertical) {
- boolean intercepted = super.onInterceptTouchEvent(swapXY(ev));
- swapXY(ev); // return touch coordinates to original reference frame for any child views
- return intercepted;
- }else {
- return super.onInterceptTouchEvent(ev);
- }
- }
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (isVertical) {
- return super.onTouchEvent(swapXY(ev));
- }else {
- return super.onTouchEvent(ev);
- }
- }
- }
自定义属性定义在res/values/attr.xml中 , 具体如下:
- <?xml version="1.0" encoding="utf-8"?>
- <resources>
- <declare-styleable name="MyViewPager">
- <attr name="isVertical" format="boolean" />
- </declare-styleable>
- </resources>
使用代码如下
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- <span style="color:#ff0000;">xmlns:app="http://schemas.android.com/apk/res-auto"</span>
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <com.xiaowu.banner.demo.HorizonVerticalViewPager
- android:id="@+id/vp"
- android:layout_width="wrap_content"
- android:layout_height="fill_parent"
- <span style="color:#ff0000;">app:isVertical="false"</span>
- />
- <xxxxx
- />
- </LinearLayout>
看官们估计又要有疑问了,那个MyViewPager是个什么鬼,大概解释一下,这个MyViewPager是为了解决ViewPager不能响应onTouchListener的问题
主要是复写了其中的dispatchTouchEvent函数,然后在分发之前,先自己做点事情,具体代码见传送门。
源码已上传 地址 源码