这两天没事,写了一个带有粘性效果的图片滑动,具体的实现不是很难,基本都有详细的注释供大家参考,希望能帮助到有需要的人,下面是动态效果图.
1、布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.dfhe.customscrollview.CustomScrollView
android:id="@+id/cv"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/a"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/b"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/c"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/d"/>
</com.dfhe.customscrollview.CustomScrollView>
</RelativeLayout><span style="color:#009900;">
</span>
2、自定义的CustomeScroll的控件,里面都有详细的注释
package com.dfhe.customscrollview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Scroller;
/**
* 项目名称:CustomScrollView
* 类描述:
* 创建人:Administrator
* 创建时间:2016/2/26 10:09
* 修改人:Administrator
* 修改时间:2016/2/26 10:09
* 修改备注:
*
* @param
*/
public class CustomScrollView extends ViewGroup {
private int mScreenHeight;
private int mLastY;
private int mStart;
private Scroller mScroller;
private int mEnd;
private int childCount;
public CustomScrollView(Context context) {
this(context, null);
}
public CustomScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
//获取屏幕的高度
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
mScreenHeight = wm.getDefaultDisplay().getHeight();
mScroller = new Scroller(context);
}
/**
* 使用遍历的方式通知子View对自身进行测量
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
//获取到子view的数量,然后对他们自身进行测量
int count = getChildCount();
for (int i = 0; i < count; i++) {
View viewChild = getChildAt(i);
measureChild(viewChild, widthMeasureSpec, heightMeasureSpec);
}
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
childCount = getChildCount();
//设置ViewGroup的高度
MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
mlp.height = mScreenHeight * childCount;
setLayoutParams(mlp);
//摆放每个子View的位置
for (int i = 0; i < childCount; i++) {
//拿到每一个子View
View child = getChildAt(i);
//判断子View是不是存在
if (child.getVisibility() != View.GONE) {
//如果存在,摆放好每个child的位置
child.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);
}
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
//这里获取getScrolly,有可能你在之前已经滑动了一段距离,所以为了保证mStart的值有效,最好是获取一下,当然默认是0(在没有滑动的情况下)
mStart = getScrollY();
break;
case MotionEvent.ACTION_MOVE:
if (!mScroller.isFinished()) {
//mScroller的动画效果
mScroller.abortAnimation();
}
int dy = mLastY - y;
if (getScrollY() < -150) {
dy = 0;
}
//这里加上350是为了,滑动到最后一个图片的时候有一个粘性的效果
if (getScrollY() >= getHeight() * (childCount - 1) + 350) {
dy = 0;
}
scrollBy(0, dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mEnd = getScrollY();
int dScrollY = mEnd - mStart;
if (dScrollY > 0) {
//判断是否是向上滑动(这里的滑动判断是view控件的边缘减去view控件中内容的边缘)
if (dScrollY < mScreenHeight / 3) {
//向上滑动的距离小于屏幕的三分之一的时候,让其回到滑动的初始位置(也就是不滑动到下一页)
mScroller.startScroll(0, getScrollY(), 0, -dScrollY);
} else {
//否则如果大于屏幕的三分之一的距离的话,滑动到下一页
//这里屏幕的高度,减去滑动的距离,意思就是手指已经滑动了dScrollY的距离了,只需要让它自己再滑动mScreenHeight - dScrollY的距离即可
mScroller.startScroll(0, getScrollY(), 0, mScreenHeight - dScrollY);
}
} else {
//同理,如果不是向上滑动就是向下滑动
if (-dScrollY < mScreenHeight / 3) {
mScroller.startScroll(0, getScrollY(), 0, -dScrollY);
} else {
mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight - dScrollY);
}
}
break;
}
postInvalidate();
return true;
}
//在调用了Scroller对象后,需要更新mScollerX和mScollerY就需要调用这个方法
//也就是当坐标发生偏移的时候,就会调用这个方法来更新
@Override
public void computeScroll() {
super.computeScroll();
if (mScroller.computeScrollOffset()) {
scrollTo(0, mScroller.getCurrY());
postInvalidate();
}
}
}
MainActivity中不需要做任何处理效果就已经出来了,当然,如果需要源码,可以去我的gitHub中去下载源码,地址:点击打开链接