仿京東樣式下拉檢視圖文詳情效果
阿新 • • 發佈:2018-11-29
用到的兩個類:
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>
完成