自定义viewgroup嵌套两个scrollview,scrollview嵌套TabLayout+ViewPager,ViewPager放置scrollview
/**
* Created by Administrator on 2017/6/30 0030.
*/
public class PullUpToLoadDetail extends ViewGroup {
public static String TAG = PullUpToLoadDetail.class.getName();
HzjrScrollView 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 boolean newScrollViewIsTop = true;
public PullUpToLoadDetail(Context context) {
super(context);
init();
}
public PullUpToLoadDetail(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public PullUpToLoadDetail(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
post(new Runnable() {
@Override
public void run() {
topScrollView = (HzjrScrollView) getChildAt(0);
bottomScrollView = (HzjrScrollView) getChildAt(1);
topScrollView.setScrollListener(new HzjrScrollView.ScrollListener() {
@Override
public void onScrollToBottom() {
topScrollViewIsBottom = true;
}
@Override
public void onScrollToTop() {
}
@Override
public void ziScrollIsOnTop() {
}@Override
public void ziScrollIsNotOnTop() {
}
@Override
public void onScroll(int scrollY) {
}
@Override
public void notBottom() {
topScrollViewIsBottom = false;
}
});
bottomScrollView.setScrollListener(new HzjrScrollView.ScrollListener() {
@Override
public void onScrollToBottom() {
}
@Override
public void ziScrollIsOnTop() {
newScrollViewIsTop = true;
}@Override
public void ziScrollIsNotOnTop() {
newScrollViewIsTop = false;
}
@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;
}
}
}
// LogUtil.showLog("wwww","pullUPToLoadDetail===111=="+newScrollViewIsTop);
if (bottomScrollVIewIsInTop&&newScrollViewIsTop) {
int dy = lastY - y;
// LogUtil.showLog("wwww","pullUPToLoadDetail==222==="+newScrollViewIsTop);
//判断是否是向下滑动和是否在第二屏
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();
}
}
}
/**PullUpToLoadDetail中的scrollview
* Created by Administrator on 2017/6/30 0030.
*/
public class HzjrScrollView extends ScrollView {
private static String TAG=HzjrScrollView.class.getName();
public void setScrollListener(ScrollListener scrollListener) {
this.mScrollListener = scrollListener;
}
private ScrollListener mScrollListener;
public HzjrScrollView(Context context) {
super(context);
initListenerState();
}
private boolean isOnTop=true;
private void initListenerState() {
post(new Runnable() {
@Override
public void run() {
NewScrollView.setNewScrollListener(new NewScrollView.NewScrollListener() {
@Override
public void onScrollToBottom() {
isOnTop=false;
if(mScrollListener!=null){
mScrollListener.ziScrollIsNotOnTop();
}
}
@Override
public void onScrollToTop() {
isOnTop=true;
if(mScrollListener!=null){
mScrollListener.ziScrollIsOnTop();
}
}
@Override
public void onScroll(int scrollY) {
if (scrollY==0){
isOnTop=true;
if(mScrollListener!=null){
mScrollListener.ziScrollIsOnTop();
}
}else {
isOnTop=false;
if(mScrollListener!=null){
mScrollListener.ziScrollIsNotOnTop();
}
}
}
@Override
public void notBottom() {
isOnTop=false;
if(mScrollListener!=null){
mScrollListener.ziScrollIsNotOnTop();
}
}
});
}
});
}
public HzjrScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
initListenerState();
}
public HzjrScrollView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initListenerState();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_MOVE:
if(mScrollListener!=null){
int contentHeight=getChildAt(0).getHeight();
int scrollHeight=getHeight();
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;
}
float mDownX ;
float mDownY;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//ev.getRawX() 拿到相对于屏幕的坐标
mDownX = ev.getX();//拿到相对于控件本身的位置
mDownY = ev.getY();
// LogUtil.showLog("wwww","1111111HzjrViewpager");
break;
case MotionEvent.ACTION_MOVE:
float moveX = ev.getX();
float moveY = ev.getY();
//计算x轴的变化量
float X = moveX - mDownX;
//计算y轴变化量
float Y = moveY - mDownY;
//计算x轴的变化量
float diffX = Math.abs(moveX - mDownX);
//计算y轴变化量
float diffY = Math.abs(moveY - mDownY);
// LogUtil.showLog("wwww","diffX===="+diffX);
// LogUtil.showLog("wwww","diffY===="+diffY);
// LogUtil.showLog("wwww","X===="+X);
// LogUtil.showLog("wwww","Y===="+Y);
// LogUtil.showLog("www","isOnTop===="+isOnTop);
if (!isOnTop){
// LogUtil.showLog("wwww","nonononononononono");
return false;
}
// if (diffX < diffY&&Y>=0) {
if (isOnTop&&Y>=0&&diffX < diffY) {
// LogUtil.showLog("wwww","22222HzjrViewpager");
getParent().requestDisallowInterceptTouchEvent(false);
return true;
}
break;
case MotionEvent.ACTION_UP:
// LogUtil.showLog("wwww","up---up--up");
// //return true;
break;
}
// LogUtil.showLog("wwww","33333HzjrViewpager");
// return super.dispatchTouchEvent(ev);
return false;
}
public interface ScrollListener{
void onScrollToBottom();
void onScrollToTop();
void onScroll(int scrollY);
void notBottom();
void ziScrollIsOnTop();
void ziScrollIsNotOnTop();
}
}
/**HzjrScrollview中的scrollview
* Created by Administrator on 2017/7/19 0019.
*/
public class NewScrollView extends ScrollView {
public NewScrollView(Context context) {
super(context);
}
public NewScrollView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()){
case MotionEvent.ACTION_MOVE:
// case MotionEvent.ACTION_UP:
if(mListener!=null){
int contentHeight=getChildAt(0).getHeight();
int scrollHeight=getHeight();
// Log.d("wwww","scrollY:"+getScrollY()+"contentHeight:"+contentHeight+" scrollHeight"+scrollHeight+"object:"+this);
// LogUtil.showLog("www","Anyone here???????==");
int scrollY=getScrollY();
mListener.onScroll(scrollY);
if(scrollY+scrollHeight>=contentHeight||contentHeight<=scrollHeight){
mListener.onScrollToBottom();
}else {
mListener.notBottom();
}
requestDisallowInterceptTouchEvent(true);
if(scrollY==0){
// ScrollIsOnTopEvent event = new ScrollIsOnTopEvent(true);
// EventBus.getDefault().post(event);
mListener.onScrollToTop();
// return false;
requestDisallowInterceptTouchEvent(false);
}
}
break;
}
boolean result=super.onTouchEvent(ev);
// requestDisallowInterceptTouchEvent(false);
return result;
// return true;
}
static NewScrollListener mListener;
public static void setNewScrollListener(NewScrollListener listener){
mListener=listener;
}
public interface NewScrollListener{
void onScrollToBottom();
void onScrollToTop();
void onScroll(int scrollY);
void notBottom();
}
}