大家好,又见面了,我是你们的朋友全栈君。
项目里头需要用到一个在垂直方向滑动页签的效果。
具体链接 传送门
其中介绍了四五种方案,选择困难症爆发了。。。。。。
实验了其中的两种,效果上均可行,另外两种均是github的项目,没细看,有兴趣的可以去做对比
地址 VerticalViewPager VerticalViewPager2
再详细看下我实验过的两种方案,
方案一:
旋转 viewpager 旋转viewpager的Item (高能~~~~~~~)
1、onInstantiateItem() of PagerAdapter, create the view and rotate it by -90:
view.setrotation(-90f)
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函数,然后在分发之前,先自己做点事情,具体代码见传送门。
源码已上传 地址 源码
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/163233.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...