精华内容
下载资源
问答
  • android上下滑动引导页 上下切换页面 手势判断 SurfaceView实现,不使用任何第三方jar包 安卓上下滑动引导页面 一次切换一个页面
  • 一个纵向滑动的也就是上下滑动页面的效果,分享给大家
  • android 上下滑动的引导页面

    热门讨论 2014-10-15 17:27:47
    具体代码是在网上找的,自己小修改了下,能够运行,引导页面上下滑动效果!具体代码是在网上找的,自己小修改了下,能够运行,引导页面上下滑动效果!
  • android 上下滑动

    2015-02-09 15:31:54
    很不错的一个上下带动页面翻页效果,可以做成各种形式
  • android 上下滑动布局

    2018-02-28 03:47:59
    但是又放不下 需要做一个可以上下滑动页面 然后试了scrolview 和系统自带的scroling_active 都是不能放入button.否则就直接闪退.. 我是个做web的 这公司要求做app没辙..现学现卖..大伙帮指条明路..
  • 微信中禁止页面上下滑动 ios android app.vue文件mounted中 document.body.addEventListener('touchmove', function (e) { e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果) }, {passive: false}); /...

    微信中禁止页面上下滑动 ios android

    app.vue文件mounted中

    document.body.addEventListener('touchmove', function (e) {
      e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)
    }, {passive: false}); //passive 参数不能省略,用来兼容ios和android
    

    参考文档

    展开全文
  • Android 实现item或页面上下滑动切换

    千次阅读 2016-08-22 19:30:59
    一、概述做一个上下滑动来切换View,先上图: 其实在很多地方可以用到,例如:密码登录和短信登录,注册流程等需求都可以用这中交互。二、分析要做这样的交互有几个要得到的数据,滑动、动画、切换。 思考流程: ...

    转载请标明出处: 【明明爱的博客】

    一、概述

    做一个上下滑动来切换View,先上图:
    这里写图片描述

    其实在很多地方可以用到,例如:密码登录和短信登录,注册流程等需求都可以用这中交互。

    二、分析

    要做这样的交互有几个要得到的数据,滑动、动画、切换。
    思考流程:
    - 怎样让View可以平滑
    - 怎样得到滑动的View
    - 怎样获取滑动比例

    根据这些疑问我们来一步步解决它。在想做这个之前在想想Android有没有已经提供现成的View可以继承或者直接使用的,目前好像是没有的。但其实这个跟viewPager其实差不多,都是让View可以平滑、得到滑动的View,viewPager有个onPageScrolled(int position, float offset, int offsetPixels)方法是获取滑动比例的(我的上一篇博客有写)。好了,有这想法之后,我们就应该去看看viewpager的源码了。

    1、viewpager:
    我们应该从viewpager哪里看呢?总不能把它所有源码看一边吧,其实也可以viewpager的源码不多,但盲目的看Android不是一个好习惯。
    我们用viewpager的时候有用到一个方法是viewpager.setCurrentItem(0,true);这是设置fragment滑动跳转的方法,我们就可以从这里入手:

        void setCurrentItemInternal(int item, boolean smoothScroll, boolean always, int velocity) {
            if (mAdapter == null || mAdapter.getCount() <= 0) {
                setScrollingCacheEnabled(false);
                return;
            }
            if (!always && mCurItem == item && mItems.size() != 0) {
                setScrollingCacheEnabled(false);
                return;
            }
    
            if (item < 0) {
                item = 0;
            } else if (item >= mAdapter.getCount()) {
                item = mAdapter.getCount() - 1;
            }
            final int pageLimit = mOffscreenPageLimit;
            if (item > (mCurItem + pageLimit) || item < (mCurItem - pageLimit)) {
                // We are doing a jump by more than one page.  To avoid
                // glitches, we want to keep all current pages in the view
                // until the scroll ends.
                for (int i=0; i<mItems.size(); i++) {
                    mItems.get(i).scrolling = true;
                }
            }
            final boolean dispatchSelected = mCurItem != item;
    
            if (mFirstLayout) {
                // We don't have any idea how big we are yet and shouldn't have any pages either.
                // Just set things up and let the pending layout handle things.
                mCurItem = item;
                if (dispatchSelected) {
                    dispatchOnPageSelected(item);
                }
                requestLayout();
            } else {
                populate(item);
                scrollToItem(item, smoothScroll, velocity, dispatchSelected);
            }
        }

    直接看到scrollToItem(item, smoothScroll, velocity, dispatchSelected);这个方法,很明显是滑动的。

        private void scrollToItem(int item, boolean smoothScroll, int velocity,
                boolean dispatchSelected) {
            final ItemInfo curInfo = infoForPosition(item);
            int destX = 0;
            if (curInfo != null) {
                final int width = getClientWidth();
                destX = (int) (width * Math.max(mFirstOffset,
                        Math.min(curInfo.offset, mLastOffset)));
            }
            if (smoothScroll) {
                smoothScrollTo(destX, 0, velocity);
                if (dispatchSelected) {
                    dispatchOnPageSelected(item);
                }
            } else {
                if (dispatchSelected) {
                    dispatchOnPageSelected(item);
                }
                completeScroll(false);
                scrollTo(destX, 0);
                pageScrolled(destX);
            }
        }

    根据名字我们都知到要进completeScroll(false);来看:

        private void completeScroll(boolean postEvents) {
            boolean needPopulate = mScrollState == SCROLL_STATE_SETTLING;
            if (needPopulate) {
                // Done with scroll, no longer want to cache view drawing.
                setScrollingCacheEnabled(false);
                boolean wasScrolling = !mScroller.isFinished();
                if (wasScrolling) {
                    mScroller.abortAnimation();
                    int oldX = getScrollX();
                    int oldY = getScrollY();
                    int x = mScroller.getCurrX();
                    int y = mScroller.getCurrY();
                    if (oldX != x || oldY != y) {
                        scrollTo(x, y);
                        if (x != oldX) {
                            pageScrolled(x);
                        }
                    }
                }
            }
            mPopulatePending = false;
            for (int i=0; i<mItems.size(); i++) {
                ItemInfo ii = mItems.get(i);
                if (ii.scrolling) {
                    needPopulate = true;
                    ii.scrolling = false;
                }
            }
            if (needPopulate) {
                if (postEvents) {
                    ViewCompat.postOnAnimation(this, mEndScrollRunnable);
                } else {
                    mEndScrollRunnable.run();
                }
            }
        }

    在这已经能看出滑动的关键对象了,那就是Scroller对象。原来viewpager也是用到Scroller来滑动的。那么思考点:怎样让View可以平滑,我们是知道了,就用Scroller对象。

    在scrollToItem(int item, boolean smoothScroll, int velocity,boolean dispatchSelected)方法里有个方法pageScrolled(destX);也提到了Scroll,好,我们也进去看看:

        private boolean pageScrolled(int xpos) {
            if (mItems.size() == 0) {
                if (mFirstLayout) {
                    // If we haven't been laid out yet, we probably just haven't been populated yet.
                    // Let's skip this call since it doesn't make sense in this state
                    return false;
                }
                mCalledSuper = false;
                onPageScrolled(0, 0, 0);
                if (!mCalledSuper) {
                    throw new IllegalStateException(
                            "onPageScrolled did not call superclass implementation");
                }
                return false;
            }
            final ItemInfo ii = infoForCurrentScrollPosition();
            final int width = getClientWidth();
            final int widthWithMargin = width + mPageMargin;
            final float marginOffset = (float) mPageMargin / width;
            final int currentPage = ii.position;
            final float pageOffset = (((float) xpos / width) - ii.offset) /
                    (ii.widthFactor + marginOffset);
            final int offsetPixels = (int) (pageOffset * widthWithMargin);
    
            mCalledSuper = false;
            onPageScrolled(currentPage, pageOffset, offsetPixels);
            if (!mCalledSuper) {
                throw new IllegalStateException(
                        "onPageScrolled did not call superclass implementation");
            }
            return true;
        }

    这方法里的onPageScrolled(currentPage, pageOffset, offsetPixels);就是平常我们调用的滑动比例,那么到此,我们两个的思考点都能从viewpager找到答案。

    至于怎样得到滑动的View,因为是我们addview的,所以我们通过getChildAt()可以获得。至此,我们思考的问题点都有了解决方法了。当然,你要看懂viewpager的那些值是怎么来的。

    /**
     * Created by 明明爱
     */
    public class CustomFrameLayout extends FrameLayout {
    
         private Scroller mScroller;
         float scaleY1 = 0;
         float scaleY2 = 0;
         float scaleX = 0.9f;
         private int BringToFrontView;   //在前面显示的View
         private View shouldFrontView;   //滑动之后该在前面显示的View
         private View currentView;   //当前在前面显示的View
         private boolean alreadyToUp = false;   //已经向上滑了
         private float shouldFrontViewScaleX;   //滑动之后该在前面显示的View伸缩的X比例
         private static float MAX_SCROLLY = 450;   //向上移动的距离
         private static float translationYpresent = 0.90f;   //移动的比例
         private static final float moveDown = 25;   //默认的偏移量
         private static final float enlargeScale = 0.3f;   //移动的需要方大的比例
         private float scrollXPresent = 0.05f;   //缩小的比例。默认第一个缩小0.05。
         private List<Integer> heightList = new ArrayList<>();   //保存本身View的height
         private List<View> viewList = new ArrayList<>();   //保存子View的对象
    
         public CustomFrameLayout(Context context) {
              super(context);
         }
    
         public CustomFrameLayout(Context context, AttributeSet attrs) {
              super(context, attrs);
              mScroller = new Scroller(context,new DecelerateInterpolator());
         }
    
         public CustomFrameLayout(Context context, AttributeSet attrs, int defStyleAttr) {
              super(context, attrs, defStyleAttr);
         }
    
         @Override
         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
              super.onMeasure(widthMeasureSpec, heightMeasureSpec);
         }
    
         @Override
         protected void onLayout(boolean changed, int l, int t, int r, int b) {
              super.onLayout(changed, l, t, r, b);
              if (changed) {
                   for (int i = 0; i < getChildCount(); i++){
                        viewList.add(getChildAt(i));
                        heightList.add(getChildAt(i).getMeasuredHeight());
                   }
                   currentView = getChildAt(getChildCount() - 1);
                   BringToFrontView = getChildCount() - 1;
                   initAnamtor();
              }
         }
    
         /**
          * 初始化界面
          */
         private void initAnamtor() {
              int j = 1;   //记录第几个向下移动View
              for (int i = getChildCount()-1; i >= 0; i--){
                   View childView = getChildAt(i);
                   if (currentView != childView){
                        childView.setScaleX(scaleX-(j-1)*scrollXPresent);   //
                        childView.setTranslationY(moveDown*j);
                        j++;
                   }
              }
              updateHeightToFrontView();
         }
    
         public void startAnimation(int BringToFrontView) {
              this.BringToFrontView = BringToFrontView;
              MAX_SCROLLY = heightList.get(0);
              shouldFrontView = viewList.get(BringToFrontView);
              shouldFrontViewScaleX = shouldFrontView.getScaleX();
              updateHeightToFrontView();
              currentView = getChildAt(getChildCount() - 1);
              if (!alreadyToUp) {
                   mScroller.startScroll( 0,  mScroller.getCurrY(), 0, (int) MAX_SCROLLY, 1900);
                   alreadyToUp = true;
              } else {
                   mScroller.startScroll( 0,  mScroller.getCurrY(), 0,  -mScroller.getCurrY(), 1900);
                   alreadyToUp = false;
              }
              invalidate();
    
         }
    
         /**
          * 如果各个View高度不一样,就让他们跟显示在前面的View高度保持一致
          */
         public void updateHeightToFrontView(){
              for (int i = 0; i < getChildCount(); i++){
                   getChildAt(i).getLayoutParams().height = heightList.get(BringToFrontView);
              }
         }
    
         @Override
         public void computeScroll() {
              super.computeScroll();
              if (mScroller.computeScrollOffset()) {
                   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                   float offset = Math.abs((float) mScroller.getCurrY()) / MAX_SCROLLY;
                   int offsetPixels = mScroller.getCurrY();
                   onScrolledChange(offset,offsetPixels);
                   invalidate();
              }
         }
    
         protected void onScrolledChange(float offset, int offsetPixels){
              int j = 2;   //记录第几个向下移动View
              int k = 1;
              for (int i = 0; i <getChildCount(); i++){
                   if (getChildAt(i) == shouldFrontView) {
                        getChildAt(i).setTranslationY(offsetPixels);   //保持滑动之后该在前面显示的View位置不动
                   }else{
                        View childView = getChildAt(i);
                        if (currentView != childView) {
                             childView.setScaleX(scaleX - k * scrollXPresent);   //大小比例微调
                             childView.setTranslationY(offsetPixels+moveDown * j);//保持滑动之后不在前面显示的View位置微调
                             j++;
                        }
                        k++;
                   }
              }
              if (alreadyToUp && offset > translationYpresent) {
                   shouldFrontView.bringToFront();
                   shouldFrontView.setScaleX((1 - shouldFrontViewScaleX) * (offset-shouldFrontViewScaleX)/(1 - shouldFrontViewScaleX) + shouldFrontViewScaleX);
              }else if (!alreadyToUp && offset < 1-translationYpresent){
                   shouldFrontView.bringToFront();
                   shouldFrontView.setScaleX((1 - shouldFrontViewScaleX) * ((1-offset)-shouldFrontViewScaleX)/(1 - shouldFrontViewScaleX) + shouldFrontViewScaleX);
              }
    
              if (alreadyToUp) {
                   if (offset >= translationYpresent) {
                        currentView.setTranslationY((Math.abs(offsetPixels) - (MAX_SCROLLY * translationYpresent)) + (MAX_SCROLLY * translationYpresent) * offset + moveDown * offset);
                        currentView.setScaleX(scaleX);
                   }else{
                        currentView.setScaleX(1+enlargeScale*offset);
                   }
              }
              if (!alreadyToUp){
                   if(offset >= 1-translationYpresent){
                        currentView.setTranslationY((Math.abs(offsetPixels) - (MAX_SCROLLY * translationYpresent))  +(MAX_SCROLLY * translationYpresent) * offset - moveDown * offset);
                        currentView.setScaleX(1+enlargeScale*(1-offset));
                   }else{
                        currentView.setTranslationY(moveDown);
                        currentView.setScaleX(scaleX);
                   }
              }
         }
    }

    在onLayout(boolean changed, int l, int t, int r, int b)方法中获取各个子View,并保存。在startAnimation(int BringToFrontView)方法中调用:

    if (!alreadyToUp) {
         mScroller.startScroll( 0,  mScroller.getCurrY(), 0, (int) MAX_SCROLLY, 1900);
         alreadyToUp = true;
     } else {
         mScroller.startScroll( 0,  mScroller.getCurrY(), 0,  -mScroller.getCurrY(), 1900);
         alreadyToUp = false;
    }
         invalidate();

    这样使View之间平滑。

    @Override
         public void computeScroll() {
              super.computeScroll();
              if (mScroller.computeScrollOffset()) {
                   scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
                   float offset = Math.abs((float) mScroller.getCurrY()) / MAX_SCROLLY;
                   int offsetPixels = mScroller.getCurrY();
                   onScrolledChange(offset,offsetPixels);
                   invalidate();
              }
         }

    在这方法算出了比例offset=0~1,offsetPixels滑动的距离。

    最后在onScrolledChange(float offset, int offsetPixels)处理各中View的滑动和初始化。

    对于滑动,主要还是要理解滑动View的是内容还是实体,根据滑动内容跟实体的相对距离算出要滑动的距离。其他的就是不什么问题了,都是数学算的比例问题。

    有不懂,一起学习。

    展开全文
  • android随着页面上下滑动顶部导航栏由透明变成不透明这个滑动的距离该如何计算,就是类似于qq空间,随着界面的上下滑动,导航栏逐渐变成不透明的,并且固定在屏幕顶部
  • 页面是由导航栏TabLayout,ViewPage2 ,列表RecycleView 组成的时候,RecycleView上下滑动,总是不经意的带动了ViewPage2的左右滑动,ViewPage2太灵敏。 解决问题方法核心:分发事件。 (其实看了一遍并没什么...

    一,问题描述

    当页面是由导航栏TabLayout,ViewPage2 ,列表RecycleView 组成的时候,RecycleView上下滑动,总是不经意的带动了ViewPage2的左右滑动,ViewPage2太灵敏。

    1. 解决问题方法核心:分发事件。 (其实看了一遍并没什么思路)

    2. 思路:从布局开始:ViewPage2+Tablayout+Fragment
      而我们RecycleView是在Fragment中,Fragment又在ViewPage2中。也就是说ViewPage2是RecycleViewd的父布局。

    然而,看了一下ViewPage2并不能被继承。 那我们可以做的就是,在RecycleView 滑动的时候,去影响ViewPage2 ,怎么去影响他呢?这是个问题。

    先看下 子控件 的拦截方法都有啥

    自定义View 继承 RecycleView 实现这个方法

    这是RecycleView的事件分发方法,我们的操作就要在这个里面。

    
    override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
            when (ev!!.action) {
            	//按下
                MotionEvent.ACTION_DOWN -> {
                 	//此时,得到手指坐标 X,Y
                 	
                }
                //移动
                MotionEvent.ACTION_MOVE -> {
                      //移动的距离
                }
                //这里 抬起手指,和取消动作。
                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL ->  {
                }
            }
    
    
            return super.dispatchTouchEvent(ev)
    
        }
    

    怎么操作父布局
    下面这个接口→视图父类。

    Defines the responsibilities for a class that will be a parent of a View.
    This is the API that a view sees when it wants to interact with its parent.
    

    解释:大概意思是,使用这个类,可以得到当前布局(使用这个方法的布局)的父布局。并与之交互。

    
    public interface ViewParent { 
    
    //其他方法略
    ...
    
    	/**
         * 这个方法:如果父元素存在,返回父元素;或者null。
         */
        public ViewParent getParent();
    	/**
    	 * 还有这个:当子View不希望被父View调用时使用,意思就是我自己来,不让父布局管。
    	 *  true:拦截,false:不拦截
    	 */
       public void requestDisallowInterceptTouchEvent(boolean disallowIntercept);
       
    ...
    }
    

    以上就是关键的方法,下面,直接看完整代码

    import android.content.Context
    import android.util.AttributeSet
    import android.util.Log
    import android.view.MotionEvent
    import android.view.ViewConfiguration
    import androidx.recyclerview.widget.RecyclerView
    import kotlin.math.abs
    /**
     *  author : ChenWenJie
     *  email  : 1181620038@qq.com
     *  date   : 2020/7/29
     *  desc   : 滑动冲突。斜着往上滑的时候,会滑动viewpage
     */
    class MyRecyclerView(context: Context, attrs: AttributeSet?) : RecyclerView(context, attrs) {
        private var mTouchSlop = 0
    
        var startX = 0  //手指碰到屏幕时的 X坐标
        var startY = 0 //手机碰到屏幕时的 Y坐标
    
        init {
            val vc = ViewConfiguration.get(context)
            mTouchSlop = vc.scaledTouchSlop
        }
    
        override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
            when (ev!!.action) {
                MotionEvent.ACTION_DOWN -> {
               		 //当手指按下时,得到了X,Y,
                    startX = ev!!.x.toInt()
                    startY = ev!!.y.toInt()
                 	// 
                    parent.requestDisallowInterceptTouchEvent(true)
                }
                MotionEvent.ACTION_MOVE -> {
                //抬起手后得到的坐标,
                    val endX = ev!!.x.toInt()
                    val endY = ev!!.y.toInt()
                    //得到绝对值 。
                    val disX = abs(endX - startX) 
                    val disY = abs(endY - startY)
                    //如果X轴 大于Y 轴,说明实在左右移动 为什么?
                    // 屏幕坐标,X,Y从左上角开始。0,0
                    if (disX > disY) {
                        Log.e("ACTIONdisX > disY:", "$disX")
                        //这个地方,判断了左右滑动的灵敏度,只有当左右滑动距离110 此时父布局才有作用,不拦截。
                        if (disX > 110) { //结束的时候大于
                            //当滑动的距离大于100的时候,才不拦截parent的事件 父控件才会有用。
                            parent.requestDisallowInterceptTouchEvent(false)
                        } 
                    } else {
                        // 说明是上下滑动  //canScrollVertically 检查此视图是否可以按某个方向垂直滚动。 负数表示上下滚动。正数表示左右滚动
                        //return  true如果视图可以按指定的方向滚动,否则为false。
                        //既然是上下滑动,此时,父控件就不能有 事件 true停止
                        parent.requestDisallowInterceptTouchEvent(true)
    
    
                    }
                }
                MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> parent.requestDisallowInterceptTouchEvent(false)
            }
    
    
            return super.dispatchTouchEvent(ev)
    
        }
    }
    
     
    

    看下效果图:在这里插入图片描述
    在这里插入图片描述

    展开全文
  • 目前我们项目有个需求,商品详情页需要仿淘宝 而且下面的页卡可以滑动切换,于是用ViewGroup自定义了一个上下方向的ViewPager,并且需要处理各种事件传递,相信通过自定义ViewGroup我们可以实现很多不一样的页面结构...
    目前我们项目有个需求,商品详情页需要仿淘宝 而且下面的页卡可以滑动切换,于是用ViewGroup自定义了一个上下方向的ViewPager,并且需要处理各种事件传递,相信通过自定义ViewGroup我们可以实现很多不一样的页面结构需求,

    github地址https://github.com/ouyangfeng/CustomerViewGroup.git

    转载请注明:http://blog.csdn.net/ertingkele/article/details/49926187


    以下是自定义的跟布局View源码

    package com.liushengfan.test.customerviewgroup.view;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.support.v4.view.ViewPager;
    import android.util.AttributeSet;
    import android.view.GestureDetector;
    import android.view.LayoutInflater;
    import android.view.MotionEvent;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.ListView;
    import android.widget.ScrollView;
    import android.widget.Scroller;
    
    import com.liushengfan.test.customerviewgroup.R;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.Comparator;
    import java.util.List;
    
    /**
     * @author liushengfan
     * @see android.support.v4.view.ViewPager
     *         <p/>
     *         垂直方向 ViewPager
     */
    public class ViewGroupScrollView extends ViewGroup implements ViewPager.OnPageChangeListener {
    
        private Context mContext;
    
        private View mObservedView;//正在监听的 View
    
        private ViewPager mViewPager;//底部ViewPager
    
        private View mUpView;//第一部分View
        private View mDownView;//第二部分View
    
    
        private boolean viewChang = false;//第一部分与第二部分 是否已经切换  相对于初始位置
    
        private Scroller myScroller;
    
        private boolean isFling = false;
    
        private int boundaryY = 0;
    
        MyGestureListener gestureListener;
    
        public ViewGroupScrollView(Context context) {
            super(context);
        }
    
        public ViewGroupScrollView(Context context, AttributeSet attrs) {
            super(context, attrs);
            mContext = context;
            init();
            /**
             * 获得我们所定义的自定义样式属性
             */
            TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ViewGroupScrollView, 0, 0);
            int downViewLayoutId = a.getResourceId(R.styleable.ViewGroupScrollView_downView, 0);
            int upViewLayoutId = a.getResourceId(R.styleable.ViewGroupScrollView_upView, 0);
            mUpView = LayoutInflater.from(context).inflate(upViewLayoutId, null);
            mDownView = LayoutInflater.from(context).inflate(downViewLayoutId, null);
            a.recycle();
            if (null == mUpView || null == mDownView) {
                throw new RuntimeException("upView or downView can not be null");
            }
            addView(mUpView);
            addView(mDownView);
        }
    
        private void init() {
            myScroller = new Scroller(mContext);
            gestureListener = new MyGestureListener();
            detector = new GestureDetector(mContext, gestureListener);
    
        }
    
        /**
         * 设置下部分View的资源ID
         *
         * @param layoutId
         */
        public void setViewPagerLayoutId(int layoutId) {
            View v = mDownView.findViewById(layoutId);
            if (null == v || !(v instanceof ViewPager)) {
                throw new RuntimeException("can not find ViewPager in the second part of ViewGroupScrollView");
            }
            mViewPager = (ViewPager) v;
            //ViewPager 设置监听器
            mViewPager.addOnPageChangeListener(this);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            MeasureSpec.getSize(widthMeasureSpec);
            MeasureSpec.getMode(widthMeasureSpec);
    
            for (int i = 0; i < getChildCount(); i++) {
                View view = getChildAt(i);
                view.measure(widthMeasureSpec, heightMeasureSpec);
            }
        }
    
        @Override
        protected void onLayout(boolean changed, int l, int t, int r, int b) {
            View viewUp = getChildAt(0);
            View viewDown = getChildAt(1);
            boundaryY = viewUp.getMeasuredHeight();
            viewUp.layout(l, t, r, boundaryY);
            viewDown.layout(l, boundaryY, r, b + boundaryY);
            if (changed) {
                moveToDest();
            }
        }
    
        private GestureDetector detector;
    
        public int curIndex;// 0 top 1 bottom
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
            try {
                return super.dispatchTouchEvent(ev);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return false;
        }
    
        @Override
        public boolean onTouchEvent(MotionEvent event) {
            detector.onTouchEvent(event);
            switch (event.getAction()) {
                case MotionEvent.ACTION_UP:
                    if (!isFling) {
                        moveToDest();
                    }
                    isFling = false;
                    break;
    
                default:
                    break;
            }
            return true;
        }
    
        /**
         * 两部分View自动切换
         */
        private void moveToDest() {
            int destId = (getScrollY() / (boundaryY / 2)) >= 1 ? 1 : 0;
            moveToDest(destId);
        }
    
        /**
         * 两部分切换
         *
         * @param destId
         */
        public void moveToDest(int destId) {
            if (0 == destId || 1 == destId) {
                int distance = destId * boundaryY - getScrollY();
                curIndex = destId;
                myScroller.startScroll(getScrollX(), getScrollY(), 0, distance, Math.abs(distance / 2));
                invalidate();
            }
        }
    
        /**
         * 计算滚动位置
         */
        @Override
        public void computeScroll() {
            if (myScroller.computeScrollOffset()) {
                int curY = myScroller.getCurrY();
                scrollTo(0, curY);
                invalidate();
                if (0 == curY) {
                    viewChang = false;
                    mObservedView = mUpView;
                } else if (boundaryY == curY) {
                    viewChang = true;
                    mObservedView = getCurChild_vp(mViewPager);
                }
            }
        }
    
        private int startY = 0;
        private int startX = 0;
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev) {
            boolean intercept = false;
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    startY = (int) ev.getY();
                    startX = (int) ev.getX();
                    break;
                case MotionEvent.ACTION_UP:
                    startX = 0;
                    startY = 0;
                    intercept = false;
                    break;
                case MotionEvent.ACTION_MOVE:
                    int currentY = (int) ev.getY();
                    int currentX = (int) ev.getX();
                    int distanceY = currentY - startY;
                    int distanceX = currentX - startX;
                    if (Math.abs(distanceY) - Math.abs(distanceX) > 5) {
                        boolean interceptFromChildFeedback = isParentViewShouldInterceptEnvent(viewChang, mObservedView);
                        if (viewChang) {
                            if (interceptFromChildFeedback && distanceY > 0) {
                                intercept = true;
                            } else {
                                intercept = false;
                            }
                        } else {
                            if (interceptFromChildFeedback && distanceY < 0) {
                                intercept = true;
                            } else {
                                intercept = false;
                            }
                        }
                    }
                    startY = currentY;
                    startX = currentX;
                    break;
                default:
                    break;
            }
            gestureListener.setInterrupt(intercept);
            detector.onTouchEvent(ev);
            return intercept;
        }
    
        private class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
            private boolean interrupt = false;
    
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                if (interrupt) {
                    if (0 == getScrollY() && distanceY > 0) {
                        scrollBy(0, (int) distanceY);
                    } else if (getScrollY() > 0 && getScrollY() < (boundaryY)) {
                        scrollBy(0, (int) distanceY);
                    } else if ((boundaryY) == getScrollY() && distanceY < 0) {
                        scrollBy(0, (int) distanceY);
                    }
                }
                // scrollBy(0, (int) distanceY);
                return true;
            }
    
            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                isFling = true;
                if (velocityY > 0) {
                    moveToDest(0);
                } else {
                    moveToDest(1);
                }
                return true;
            }
    
            public void setInterrupt(boolean interrupt) {
                this.interrupt = interrupt;
            }
        }
    
        public boolean isViewChang() {
            return viewChang;
        }
    
        public void setViewChang(boolean viewChang) {
            this.viewChang = viewChang;
        }
    
        /**
         * 是否应该中断事件传输
         *
         * @param viewChang    是否上下两部分布局已经切换
         * @param observedView 被观察的可滚动的View
         * @return
         */
        private boolean isParentViewShouldInterceptEnvent(boolean viewChang, View observedView) {
            boolean intercept = true;
            if (null == observedView) {
                return intercept;
            }
            if (viewChang) {
                if (observedView instanceof ListView) {
                    ListView listView = (ListView) observedView;
                    if (0 != listView.getChildCount()) {
                        if (0 == listView.getFirstVisiblePosition() && 0 == listView.getChildAt(0).getTop()) {
                            intercept = true;
                        } else {
                            intercept = false;
                        }
                    } else {
                        intercept = true;
                    }
                } else if (observedView instanceof ScrollView) {
                    ScrollView scrollView = (ScrollView) observedView;
                    if (scrollView.getScrollY() == 0) {
                        intercept = true;
                    } else {
                        intercept = false;
                    }
                } else {
                    intercept = true;
                }
            } else {
                if (observedView instanceof ListView) {
                    //TODO 支持ListView 判断滑动到底部
                } else if (observedView instanceof ScrollView) {
                    ScrollView scrollView = (ScrollView) observedView;
                    View contentView = scrollView.getChildAt(0);
                    if (contentView != null && contentView.getMeasuredHeight() <= scrollView.getScrollY() + scrollView.getHeight()) {
                        intercept = true;
                    } else {
                        intercept = false;
                    }
                } else {
                    intercept = true;
                }
            }
            return intercept;
        }
    
    
        //ViewPager Listener begin
        @Override
        public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    
        }
    
        @Override
        public void onPageSelected(int position) {
            if (isViewChang()) {
                mObservedView = getCurChild_vp(mViewPager);
            }
        }
    
        @Override
        public void onPageScrollStateChanged(int state) {
    
        }
        //ViewPager Listener end
    
        /**
         * 获取ViewPager当前显示的View
         *
         * @param vp
         * @return
         */
        public static View getCurChild_vp(ViewPager vp) {
    
            int childCnt = vp.getChildCount();
            int totalCnt = vp.getAdapter().getCount();
            int curItem = vp.getCurrentItem();
    
            int targetIndex = 0;
    
            // 若"已加载child未达到应有值",则在边界 、或总数达不到limit
            if (childCnt < vp.getOffscreenPageLimit() * 2 + 1) {
                // 若-项数不足-加载所有至limit,直接返回当前
                if (childCnt == totalCnt)
                    targetIndex = curItem;
                else
                // 若足
                {
                    // 若在左边界(即左边child数未达到limit)
                    if (curItem - vp.getOffscreenPageLimit() < 0)
                        targetIndex = curItem;
                        // 右边界
                    else
                        targetIndex = vp.getOffscreenPageLimit();
                }
            }
            // childCnt完整(即总项>childCnt,且不在边界)
            else
                targetIndex = vp.getOffscreenPageLimit();
    
            // 取-子元素
            List<View> vs = new ArrayList<View>();
            for (int i = 0; i < childCnt; i++)
                vs.add(vp.getChildAt(i));
    
            // 对子元素-排序,因默认排序-不一定正确(viewpager内部机制)
            Collections.sort(vs, new Comparator<View>() {
                @Override
                public int compare(View lhs, View rhs) {
                    // TODO Auto-generated method stub
                    if (lhs.getLeft() > rhs.getLeft())
                        return 1;
                    else if (lhs.getLeft() < rhs.getLeft())
                        return -1;
                    else
                        return 0;
                }
            });
    
            // debug
            // for (int i = 0; i<childCnt; i++)
            // System.out.println("nimei>>vp-"+i+".x:"+vs.get(i).getLeft());
            // System.out.println("nimei>>index:"+targetIndex);
    
            return vs.get(targetIndex);
        }
    
    }
    


    展开全文
  • android SCViewPager 欢迎页面滑动效果,支持上下滑动切换页面页面切换渐变出现下一个页面特效,这充分扩展了ViewPager 的切换页面功能。
  • android SCViewPager 欢迎页面滑动效果,支持上下滑动切换页面页面切换渐变出现下一个页面特效,这充分扩展了ViewPager 的切换页面功能。
  • 最近在app里面嵌套了H5页面的链接显示正常,就是滑动屏幕的时候下面没有内容但是可以滑动一段空白,显示有点不美观,后来就增加了禁止屏幕触摸滑动事件解决了 $(document).ready(function(){ function ...
  • github
  • document.body.addEventListener('touchmove', function (e) { e.preventDefault(); //阻止默认的处理方式(阻止下拉滑动的效果)}, {passive: false}); //passive 参数不能省略,用来兼容ios和android...
  • MainActivity 应用的入口 Activity,该页面有两个入口,直播列表页面的数据完全一样,直播列表点击进入直播间以后,使用不同的服务器接口来实现上下滑动。 LiveListActivity 直播列表页面。 LiveSlideDetailActivity...
  • 项目中需要用到GridView展示90个item,但是每个item底部的数据格式是不一致的,导致加载完成后上下来回滑动多次之后突然消失。解决方法就是item.xml中高宽不能同时使用match_parent或者wrap_content。需要使用具体的...
  • 闹钟AlarmAndMusic 和支持播放音乐效果的,上下滑动调整时间和页面旋转风车效果,
  • Appium 测试,实现上下、左右滑动页面  原文:http://blog.csdn.net/liuy5277/article/details/48543225 作者:liuy5277   本人对原文做了部分修改,4个方法改成静态方法,这样使用的时候,不用new   设计一...
  • 页面滑动的时候,悬浮按钮移动到最右侧隐藏起来,页面停止滑动的时候显示出来    3.悬浮按钮点击跳转到指定的分享页面确定了功能点,实现了一个Demo来看下:分析实现: 1、功能实现起来其实并不复杂,首先按钮...
  • FragmentStateAdapter 上下滑动 先说是图片滑动 最为简单 … 略(哈哈哈)继承PagerAdapter 寻找数据源 ,实现适配器,适配器的四个方法 分别是 getCount() 返回数据源全部 isViewFromObject 返回一个类型 ...
  • 在淘宝的商品详情页,我们会看到顶部的title背景颜色随着scrollView的上下滑动而渐变,这样的功能在我们应用中会经常用到,今天就来说一下我实现下这种功能方法,当然方法可能比较笨,看到博客的大牛,希望能得到...
  • 近期要做一个含有两个tab切换页面,两个页面有公共的描述信息区域,两个tab都是listview,可以向上或向下拉动刷新,在页面中部有一个tab切换区域,向上滑动的时候tab区域到顶部后就不在移动,向下拉又重新回到初始...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 226
精华内容 90
关键字:

android上下滑动页面