您的位置:首页 > 移动开发 > Android开发

Android 左右切换页面item

2016-08-22 12:26 176 查看
转载请标明出处: 【明明爱的博客】

一、概述

好的交互会让人用起来很舒服,其实很多页面是没有必要切换页面的,例如图上密码登录和短信登录的两种情况。什么都不说,先上图:



这种登录方式没必要让用户要切换界面。

二、分析

其实以上的实现方式有很多,如viewpager、自定义view等。

本文先用viewpager来实现,后续会出用自定义view的文章。

难点分析:

- 怎样得到滑动时的事件

- 通过什么数值来得到动画的比例

- 得到需要滑动的view

ok,其实同过分析就这两个难点而已。通过查看viewpager的api可以知道viewpager提供了onPageScrolled(int position, float offset, int offsetPixels)方法,刚好解决了得到滑动事件的难点。

position 当前viewpager的fragment 第一个为0,第二个为1,如此类推

offset 滑动比例 如果position 从 0到1时 滑动比例:0~1, 当position = 1时,offset=0, offsetPixels=0。 如果position 从1~0时 滑动比例:1~0。

offsetPixels 屏幕宽度

package com.mingmingai.test_custom_login.customview;

/**
* Created by 明明爱
*/
public class CustomViewpager extends ViewPager {

private View leftView;
private View rightView;
private List<Fragment> fragmentsList;
private float mTrans;   //滑动的距离
private float mLScaleY;   //最大的缩小比例
private static final float lDefaultScaleX = 0.9f;   //leftView默认缩小X的比例
private static final float defaultScaleY = 0.9f;   //默认缩小Y的比例
private static final float scalePrecent = 0.1f;   //默认缩小的比例
private int screenWidth = 0;   //屏幕宽度
private int scrollX = 230;   //滑动多少距离之后向相反方向返回
private int defaultTranslationX = 10;   //默认移动的X距离

public CustomViewpager(Context context) {
super(context);
}

public CustomViewpager(Context context, AttributeSet attrs) {
super(context, attrs);
screenWidth = CommonUtils.getWindowWidth(context);
}

public void setFragmentsList(List<Fragment> fragmentsList) {
this.fragmentsList = fragmentsList;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;   //拦截
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
return false;   //不给viewpager滑动
}

@Override
protected void onPageScrolled(int position, float offset, int offsetPixels) {
if (position +1<= fragmentsList.size() - 1) {
// 滑动特别小的距离时,我们认为没有动,可有可无的判断
float effectOffset = isSmall(offset) ? 0 : offset;
leftView = fragmentsList.get(position).getView();   //得到View

rightView = fragmentsList.get(position + 1).getView();   //得到View
startAnimate(leftView, rightView, effectOffset, offsetPixels);
}
super.onPageScrolled(position, offset, offsetPixels);
}

private void startAnimate(View leftView, View rightView, float effectOffset, int positionOffsetPixels) {
if (leftView != null)
{
manageLayer(leftView, true);
mLScaleY = (float) (defaultScaleY - scalePrecent*effectOffset);

if (positionOffsetPixels > scrollX){
mTrans = scrollX*((positionOffsetPixels-scrollX)/(screenWidth - scrollX))+(positionOffsetPixels-scrollX)-defaultTranslationX;
rightView.bringToFront();
}else{
leftView.bringToFront();
mTrans = -defaultTranslationX;
}
ViewHelper.setTranslationX(leftView,mTrans);
ViewHelper.setScaleX(leftView, lDefaultScaleX);
ViewHelper.setScaleY(leftView, mLScaleY);
}
if (rightView != null)
{
manageLayer(rightView, true);
mLScaleY = (float) (defaultScaleY - scalePrecent*(1-effectOffset));
ViewHelper.setScaleX(rightView, lDefaultScaleX);
ViewHelper.setScaleY(rightView, mLScaleY);

if (positionOffsetPixels > scrollX){
mTrans = -getWidth()+scrollX*2+defaultTranslationX;
if (Math.abs(mTrans) >= getWidth()-positionOffsetPixels){
mTrans = -getWidth() - getPageMargin() + positionOffsetPixels+defaultTranslationX;
}
}else{
mTrans = -getWidth() - getPageMargin() + positionOffsetPixels*2+defaultTranslationX;
}
ViewHelper.setTranslationX(rightView, mTrans);
}
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void manageLayer(View v, boolean enableHardware)
{
//      if (!API_11)
//          return;
int layerType = enableHardware ? View.LAYER_TYPE_HARDWARE
: View.LAYER_TYPE_NONE;
if (layerType != v.getLayerType())
v.setLayerType(layerType, null);
}

private boolean isSmall(float positionOffset)
{
return Math.abs(positionOffset) < 0.0001;
}
}


代码分析:

leftView和rightView分别是要滑动的两个View,主要的动画都在startAnimate()里,mLScaleY是leftView缩小或放大的比例。if (positionOffsetPixels > scrollX) 当leftView滑动多少距离之后向相反方向返回,之后将rightView在前面显示:rightView.bringToFront();。mTrans是算出需要滑动的距离。

其实viewpager默认的布局是:



所以一开始就把fragment2移动到了fragment1的下面:mTrans = -getWidth() - getPageMargin() + positionOffsetPixels*2+defaultTranslationX;

要理解了动画滑动是滑动view的内容,而非view的实体。但viewpager本身的滑动是会滑动实体的,通过看viewpager的源码,发现viewpager的动画是用了Scroller对象来滑动的。Scroller每次滑动都会调用onDraw里的computeScroll()方法。只有理解好这含义,其他就很好理解了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息