Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Android ViewPager 垂直滑动 纵向滑动 VerticalViewPager[通俗易懂]

Android ViewPager 垂直滑动 纵向滑动 VerticalViewPager[通俗易懂]

作者头像
全栈程序员站长
发布于 2022-09-15 07:53:29
发布于 2022-09-15 07:53:29
2.5K00
代码可运行
举报
运行总次数:0
代码可运行

大家好,又见面了,我是你们的朋友全栈君。

项目里头需要用到一个在垂直方向滑动页签的效果。

具体链接 传送门

其中介绍了四五种方案,选择困难症爆发了。。。。。。

实验了其中的两种,效果上均可行,另外两种均是github的项目,没细看,有兴趣的可以去做对比

地址 VerticalViewPager VerticalViewPager2

再详细看下我实验过的两种方案,

方案一:

旋转 viewpager 旋转viewpager的Item (高能~~~~~~~)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
1、onInstantiateItem() of PagerAdapter, create the view and rotate it by -90:
view.setrotation(-90f)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
If you are using FragmentPagerAdapter, then:
objFragment.getView().setRoration(-90)
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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 MotionEvents prior to handling them, e.g.:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 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代码

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
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中 , 具体如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyViewPager">
        <attr name="isVertical" format="boolean" />
    </declare-styleable>
</resources>

使用代码如下

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<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函数,然后在分发之前,先自己做点事情,具体代码见传送门

源码已上传 地址 源码

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/163233.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
仿抖音上下滑动分页视频
目录介绍 01.先来看一下需求 02.有几种实现方式 2.1 使用ViewPager 2.2 使用RecyclerView 03.用ViewPager实现 3.1 自定义ViewPager 3.2 ViewPager和Fragment 3.3 修改滑动距离翻页 3.4 修改滑动速度 04.用RecyclerView实现 4.1 自定义LayoutManager 4.2 添加滑动监听 4.3 监听页面是否滚动 4.4 attach和Detached 05.优化点详谈 5.1 ViewPager改变滑动速率 5
杨充
2019/11/22
6K0
ViewPager,ScrollView 嵌套ViewPager滑动冲突解决
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/52939127
程序员徐公
2018/09/17
5.8K0
ViewPager,ScrollView  嵌套ViewPager滑动冲突解决
android 布局 使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题
使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题。 我的问题原型:      这个问题,我相信遇到的人会比较少,我是在 一个 viewPager 中,其中 一个 fragment
林冠宏-指尖下的幽灵
2018/01/03
1.5K0
Android:SwipeRefreshLayout和ViewPager滑动冲突的原因和正确的解决方式
2016.01.21 用几部真机测试,发现有些手机,手指没有滑动,move也一直执行。这回导致我们的判断出现一些问题。现在已经修复,加入了TouchSlop判断。
全栈程序员站长
2022/09/12
1.6K0
Android:SwipeRefreshLayout和ViewPager滑动冲突的原因和正确的解决方式
Android打造不一样的新手引导页面(二)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/52270186
程序员徐公
2018/09/18
9720
Android打造不一样的新手引导页面(二)
ViewPager 全面总结
Viewpager,视图翻页工具,提供了多页面切换的效果。Android 3.0后引入的一个UI控件,位于v4包中。低版本使用需要导入v4包,但是现在我们开发的APP一般不再兼容3.0及以下的系统版本,另外现在大多数使用Android studio进行开发,默认导入v7包,v7包含了v4,所以不用导包,越来越方便了。
全栈程序员站长
2022/09/15
1.1K0
ViewPager 全面总结
巧妙运用补间动画,自定义广告轮播CarouselView 2.0
  这是前一篇文章绘制的CarouselView的升级版,有兴趣的同学,可以去关注一下笔者前一篇文章。自定义广告图片轮播View——CarouselView
饮水思源为名
2018/09/06
1.1K0
巧妙运用补间动画,自定义广告轮播CarouselView 2.0
Android TouchEvent事件传递机制
本文从http://blog.csdn.net/morgan_xww/article/details/9372285和http://www.cnblogs.com/linjzong/p/4191891.html整理而来
提莫队长
2019/02/21
3820
巧用ViewPager 打造不一样的广告轮播切换效果
如果大家关注了我的微信公众号的话,一定知道我在5月6号的时候推送了一篇文章,文章名为Android超高仿QQ附近的人搜索展示(一),通过该文可以利用ViewPager实现单页显示多个Item且能够添加一些炫酷的动画效果。我当时阅读这篇文章的时候,简单做了下记录,然后想了想,可以按照该思路做一个比较特殊轮播效果,如图:
全栈程序员站长
2022/09/15
7720
巧用ViewPager 打造不一样的广告轮播切换效果
ViewPager2使用笔记
一.代码位置(阅读原文) XTester-fragment+tab+viewpager2 二.引用 implementation 'com.google.android.material:materi
项勇
2023/03/24
6730
ViewPager2使用笔记
Android 滑动效果高级篇(八)—— 自定义控件
自定义控件,较常用View、ViewGroup、Scroller三个类,其继承关系如下:
阳光岛主
2019/02/19
1.2K0
Android ViewDragHelper及移动处理总结
概述 2013年谷歌i/o大会上介绍了两个新的layout: SlidingPaneLayout和DrawerLayout,现在这俩个类被广泛的运用。我们知道在我们实际的开发中往往会涉及到很多的拖动效果,而ViewDragHelper解决了android中手势处理过于复杂的问题。 其实ViewDragHelper并不是第一个用于分析手势处理的类,gesturedetector也是,但是在和拖动相关的手势分析方面gesturedetector只能说是勉为其难,其拓展性并不好。 为了方便大家的理解,我们
xiangzhihong
2018/02/05
1.5K0
Android ViewDragHelper及移动处理总结
android 个人中心下拉弹回效果-PullscrollView
实现效果: 这个效果就是仿qq个人中心的下拉弹回效果实现。 核心就是一个 自定义的ScrollView,如下: package com.baobao.testpullscrollview; import android.annotation.SuppressLint; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Rect; import android.
再见孙悟空_
2023/02/10
6450
android 个人中心下拉弹回效果-PullscrollView
Android触摸事件_简述兴奋在突触的传递过程
在实际开发中,经常会遇到与触屏事件有关的问题,最典型的一个就是滑动冲突。比如在使用SliddingMenu菜单的时候,可能会与ViewPager或者其他的一些带有滑动事件的View相冲突,再比如ScrollView嵌套ListView相冲突等等。还有就是在自定义控件的时候,需要处理一些事件时候,也必须把逻辑处理好,父 view 和子view 都需要接收事件,然后处理。如果不明白事件传递机制,很难开发出需要的效果。因此就需要对Android消息传递机制有一个基本的理解与认识,这样才有可能解决开发过程中的需求与问题。
全栈程序员站长
2022/11/04
7400
Android触摸事件_简述兴奋在突触的传递过程
D7-测试Android事件处理机制和生命函数调用
布局很简单,代码就是打个日志看看,为了不影响阅读,放在最后 Android事件处理机制真是个磨人的小妖精,被她卡过两次,一卡住就不行玩安卓,跑过去玩html、js、css了 最好自己动手测试一下,印象更深 一、妖鸟三姐妹:dispatchTouchEvent---onInterceptTouchEvent---onTouchEvent 点击:ViewGroup1(最外层) I/System.out: MainActivity dispatchTouchEvent I/System.out: Vie
张风捷特烈
2018/09/29
4500
D7-测试Android事件处理机制和生命函数调用
相关推荐
仿抖音上下滑动分页视频
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验