用到的两个类:
package com.example.administrator.permissiondemo.activity;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.Scroller;
/**
* Created by baoyunlong on 16/6/8.
*/
public class PullUpToLoadMore extends ViewGroup {
private ScrollViewListener scrollViewListener = null;
public void setOnScrollListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
if (oldy < y) {// 手指向上滑动,屏幕内容下滑
scrollViewListener.onScroll(oldy, y, false);
} else if (oldy > y) {// 手指向下滑动,屏幕内容上滑
scrollViewListener.onScroll(oldy, y, true);
}
}
}
public interface ScrollViewListener {//dy Y轴滑动距离,isUp 是否返回顶部
void onScroll(int oldy, int dy, boolean isUp);
}
public static String TAG = PullUpToLoadMore.class.getName();
MyScrollView topScrollView, bottomScrollView;
VelocityTracker velocityTracker = VelocityTracker.obtain();
Scroller scroller = new Scroller(getContext());
int currPosition = 0;
int position1Y;
int lastY;
public int scaledTouchSlop;//最小滑动距离
int speed = 200;
boolean isIntercept;
public boolean bottomScrollVIewIsInTop = false;
public boolean topScrollViewIsBottom = false;
public PullUpToLoadMore(Context context) {
super(context);
init();
}
public PullUpToLoadMore(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PullUpToLoadMore(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
post(new Runnable() {
@Override
public void run() {
topScrollView = (MyScrollView) getChildAt(0);
bottomScrollView = (MyScrollView) getChildAt(1);
topScrollView.setScrollListener(new MyScrollView.ScrollListener() {
@Override
public void onScrollToBottom() {
topScrollViewIsBottom = true;
}
@Override
public void onScrollToTop() {
}
@Override
public void onScroll(int scrollY) {
}
@Override
public void notBottom() {
topScrollViewIsBottom = false;
}
});
bottomScrollView.setScrollListener(new MyScrollView.ScrollListener() {
@Override
public void onScrollToBottom() {
}
@Override
public void onScrollToTop() {
}
@Override
public void onScroll(int scrollY) {
if (scrollY == 0) {
bottomScrollVIewIsInTop = true;
} else {
bottomScrollVIewIsInTop = false;
}
}
@Override
public void notBottom() {
}
});
position1Y = topScrollView.getBottom();
scaledTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
}
});
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
//防止子View禁止父view拦截事件
this.requestDisallowInterceptTouchEvent(false);
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int y = (int) ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
//判断是否已经滚动到了底部
if (topScrollViewIsBottom) {
int dy = lastY - y;
//判断是否是向上滑动和是否在第一屏
if (dy > 0 && currPosition == 0) {
if (dy >= scaledTouchSlop) {
isIntercept = true;//拦截事件
lastY = y;
}
}
}
if (bottomScrollVIewIsInTop) {
int dy = lastY - y;
//判断是否是向下滑动和是否在第二屏
if (dy < 0 && currPosition == 1) {
if (Math.abs(dy) >= scaledTouchSlop) {
isIntercept = true;
}
}
}
break;
}
return isIntercept;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
velocityTracker.addMovement(event);
switch (event.getAction()) {
case MotionEvent.ACTION_MOVE:
int dy = lastY - y;
if (getScrollY() + dy < 0) {
dy = getScrollY() + dy + Math.abs(getScrollY() + dy);
}
if (getScrollY() + dy + getHeight() > bottomScrollView.getBottom()) {
dy = dy - (getScrollY() + dy - (bottomScrollView.getBottom() - getHeight()));
}
scrollBy(0, dy);
break;
case MotionEvent.ACTION_UP:
isIntercept = false;
velocityTracker.computeCurrentVelocity(1000);
float yVelocity = velocityTracker.getYVelocity();
if (currPosition == 0) {
if (yVelocity < 0 && yVelocity < -speed) {
smoothScroll(position1Y);
currPosition = 1;
} else {
smoothScroll(0);
}
} else {
if (yVelocity > 0 && yVelocity > speed) {
smoothScroll(0);
currPosition = 0;
} else {
smoothScroll(position1Y);
}
}
break;
}
lastY = y;
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int childCount = getChildCount();
int childTop = 0;
for (int i = 0; i < childCount; i++) {
View child = getChildAt(i);
child.layout(l, childTop, r, childTop + child.getMeasuredHeight());
childTop += child.getMeasuredHeight();
}
}
//通过Scroller实现弹性滑动
private void smoothScroll(int tartY) {
int dy = tartY - getScrollY();
scroller.startScroll(getScrollX(), getScrollY(), 0, dy);
invalidate();
}
//滚动到顶部
public void scrollToTop() {
smoothScroll(0);
currPosition = 0;
topScrollView.smoothScrollTo(0, 0);
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
}
and:
package com.example.administrator.permissiondemo.activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.ScrollView;
/**
* Created by baoyunlong on 16/6/8.
*/
public class MyScrollView extends ScrollView {
private ScrollViewListener scrollViewListener = null;
public void setOnScrollListener(ScrollViewListener scrollViewListener) {
this.scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged(int x, int y, int oldx, int oldy) {
super.onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null) {
if (oldy < y) {// 手指向上滑动,屏幕内容下滑
scrollViewListener.onScroll(oldy, y, false);
} else if (oldy > y) {// 手指向下滑动,屏幕内容上滑
scrollViewListener.onScroll(oldy, y, true);
}
}
}
public interface ScrollViewListener {//dy Y轴滑动距离,isUp 是否返回顶部
void onScroll(int oldy, int dy, boolean isUp);
}
private static String TAG = MyScrollView.class.getName();
public void setScrollListener(ScrollListener scrollListener) {
this.mScrollListener = scrollListener;
}
private ScrollListener mScrollListener;
public MyScrollView(Context context) {
super(context);
}
public MyScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MyScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
if (mScrollListener != null) {
int contentHeight = getChildAt(0).getHeight();
int scrollHeight = getHeight();
Log.d(TAG, "scrollY:" + getScrollY() + "contentHeight:" + contentHeight + " scrollHeight" + scrollHeight + "object:" + this);
int scrollY = getScrollY();
mScrollListener.onScroll(scrollY);
if (scrollY + scrollHeight >= contentHeight || contentHeight <= scrollHeight) {
mScrollListener.onScrollToBottom();
} else {
mScrollListener.notBottom();
}
if (scrollY == 0) {
mScrollListener.onScrollToTop();
}
}
break;
}
boolean result = super.onTouchEvent(ev);
requestDisallowInterceptTouchEvent(false);
return result;
}
public interface ScrollListener {
void onScrollToBottom();
void onScrollToTop();
void onScroll(int scrollY);
void notBottom();
}
}
其中MyScrollView相当于一个页面,由PullUpToLoadMore包裹:布局代码:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.administrator.permissiondemo.activity.PullUpToLoadMore
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.administrator.permissiondemo.activity.MyScrollView
android:id="@+id/ceshi2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:id="@+id/lv_header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<ImageView
android:id="@+id/iv_header"
android:layout_width="match_parent"
android:layout_height="@dimen/head_height3"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:src="@drawable/a1" />
</LinearLayout>
<TextView
android:id="@+id/cd_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="儿童基础级钢琴课1\n\n儿童基础级钢琴课2\n\n儿童基础级钢琴课3\n\n儿童基础级钢琴课4\n\n儿童基础级钢琴课5\n\n儿童基础级钢琴课6\n\n儿童基础级钢琴课7\n\n儿童基础级钢琴课8\n\n儿童基础级钢琴课9\n\n儿童基础级钢琴课10\n\n儿童基础级钢琴课11\n\n儿童基础级钢琴课12\n\n儿童基础级钢琴课13\n\n儿童基础级钢琴课14\n\n儿童基础级钢琴课15\n\n儿童基础级钢琴课16\n\n儿童基础级钢琴课17\n\n儿童基础级钢琴课18\n\n儿童基础级钢琴课19\n\n儿童基础级钢琴课20\n\n儿童基础级钢琴课21\n\n"
android:textColor="#000000"
android:textSize="@dimen/textSize20" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="15dp"
android:text="继续下滑看图文详情"
android:textColor="#f00" />
</LinearLayout>
</LinearLayout>
</com.example.administrator.permissiondemo.activity.MyScrollView>
<com.example.administrator.permissiondemo.activity.MyScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a1" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a3" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a4" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a5" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a9" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a8" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/a10" />
</LinearLayout>
</com.example.administrator.permissiondemo.activity.MyScrollView>
</com.example.administrator.permissiondemo.activity.PullUpToLoadMore>
<include layout="@layout/title_coursededails" />
</RelativeLayout>
完成