Skip to content

Commit

Permalink
when to top of listview, get velocity by reflect; when finger down, s…
Browse files Browse the repository at this point in the history
…top listview scrolling
  • Loading branch information
lorienzhang committed May 25, 2017
1 parent 9faec60 commit 61bfee4
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 15 deletions.
20 changes: 13 additions & 7 deletions src/main/java/com/lorien/wl/view/MyListView.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,18 @@ public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
}

public void flingY(int velocityY) {
// if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
// fling(velocityY);
// } else {
//
// }
mFlingRunnable.startFling(velocityY);
// 5.0
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
fling(velocityY);
}
// 4.4
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
mFlingRunnable.startFling(velocityY);
}
// 4.4 以下
else {
// TODO
}
}

private class FlingRunnable implements Runnable {
Expand All @@ -62,7 +68,7 @@ public void run() {
int delta = y - mLastFlingY;
if (!finish) {
mLastFlingY = y;
// ListView自动滚动
// ListView滚动一段距离
MyListView.this.scrollListBy(delta);
post(this);
} else {
Expand Down
87 changes: 79 additions & 8 deletions src/main/java/com/lorien/wl/view/WLLayout.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package com.lorien.wl.view;

import android.content.Context;
import android.os.Build;
import android.support.annotation.RequiresApi;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
Expand All @@ -12,10 +10,14 @@
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.ListAdapter;
import android.widget.OverScroller;
import android.widget.Scroller;

import com.lorien.wl.R;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

Expand Down Expand Up @@ -164,6 +166,28 @@ public class WLLayout extends ViewGroup {
* ListView的滚动监听
*/
private AbsListView.OnScrollListener mListViewScrollLisenter;
/**
* ListView的滚动状态
*/
private int mListViewScrollState;
/**
* 反射,强制停止ListView
*/
private static Method mFlingEndMethod = null;
private static Field mFlingRunnableField = null;
static{
try {
mFlingRunnableField = AbsListView.class.getDeclaredField("mFlingRunnable");
mFlingRunnableField.setAccessible(true);
mFlingEndMethod = mFlingRunnableField.getType().getDeclaredMethod("endFling");
mFlingEndMethod.setAccessible(true);
} catch (Exception e) {
mFlingEndMethod = null;
mFlingRunnableField = null;
}
}

private OverScroller mScrollerReflectd;

public WLLayout(Context context) {
this(context, null);
Expand All @@ -181,8 +205,6 @@ public WLLayout(Context context, AttributeSet attrs, int defStyleAttr) {
mMaximumVelocity = ViewConfiguration.get(context).getScaledMaximumFlingVelocity();
}


@RequiresApi(api = Build.VERSION_CODES.KITKAT)
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!isEnabled() || mWebView == null || mListView == null) {
Expand Down Expand Up @@ -226,6 +248,10 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
}
// 清空WVHolder列表
mWVholderList.clear();

if (mListViewScrollState == AbsListView.OnScrollListener.SCROLL_STATE_FLING) {
stopListViewFling(mListView);
}
return super.dispatchTouchEvent(ev);

case MotionEvent.ACTION_MOVE:
Expand Down Expand Up @@ -265,6 +291,22 @@ public boolean dispatchTouchEvent(MotionEvent ev) {
return super.dispatchTouchEvent(ev);
}

/**
* 反射方法,强制停止ListView滚动
* @param list
*/
private void stopListViewFling(MyListView list) {
if (mFlingEndMethod != null) {
try {
mFlingEndMethod.invoke(mFlingRunnableField.get(list));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
Log.d(TAG, "###method: stopListViewFling()###", new Throwable(e));
}
}
}

/**
* 手指抬起后,滑动webview和listview
*
Expand Down Expand Up @@ -314,7 +356,6 @@ private void movePos(int deltaY) {
mListView.offsetTopAndBottom(distanceY);
}


@Override
protected void onFinishInflate() {
super.onFinishInflate();
Expand All @@ -334,6 +375,24 @@ protected void onFinishInflate() {
mListView.setOnScrollListener(mListViewScrollLisenter);
}

private void reflectAbsListView() {
try {
Class<?> absListViewCls = Class.forName("android.widget.AbsListView");
Field mFlingRunnableField = absListViewCls.getDeclaredField("mFlingRunnable");
mFlingRunnableField.setAccessible(true);
Object mFlingRunnable = mFlingRunnableField.get(mListView);


Class<?> flingRunnableCls = Class.forName("android.widget.AbsListView$FlingRunnable");
Field mScrollerFeild = flingRunnableCls.getDeclaredField("mScroller");
mScrollerFeild.setAccessible(true);
mScrollerReflectd = (OverScroller) mScrollerFeild.get(mFlingRunnable);
} catch (Exception e) {
mScrollerReflectd = null;
Log.d(TAG, "###Exception Stack###", new Throwable(e));
}
}

/**
* 对WebView和ListView进行测量
*
Expand Down Expand Up @@ -423,7 +482,7 @@ private int getListViewContentHeight() {
*/
private void onScrollCheckerFinish(int velocity) {
if (mCurrentPos == POS_START) {
// KITKAT 4.4
// 存在版本兼容问题
mListView.flingY(velocity);
}
if (mCurrentPos == POS_END) {
Expand Down Expand Up @@ -469,7 +528,7 @@ private int getScrollVelocityY() {
}

/**
* Scroller控制器
* Tracker
*/
class ScrollChecker implements Runnable {

Expand Down Expand Up @@ -633,6 +692,7 @@ class ListViewScrollListener implements AbsListView.OnScrollListener {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
mScrollState = scrollState;
mListViewScrollState = scrollState;
if (scrollState == SCROLL_STATE_IDLE) {
mPositionState = STATE_POS_NONE;
}
Expand All @@ -643,6 +703,12 @@ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun
if (mPositionState != STATE_POS_NONE) {
return;
}

if (mScrollerReflectd == null) {
// 反射出AbsListView.FlingRunnable.OverScroller对象
reflectAbsListView();
}

// ListView有header view
if (mIsListViewHasHeader) {
if (firstVisibleItem == 1) {
Expand Down Expand Up @@ -675,7 +741,12 @@ public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCoun
}
int initialVelocity = calcListViewTopVelocity(startTime, duration, mIsListViewHasHeader);
startTime = 0;
Log.d(TAG, "### calcListViewTopVelocity(): " + initialVelocity);
Log.d(TAG, "### when to top of ListView, curVelocity: " + initialVelocity);
// 如果能够成功反射出来OverScroll,就是用反射出来的加速度
if (mScrollerReflectd != null) {
initialVelocity = (int) mScrollerReflectd.getCurrVelocity();
Log.d(TAG, "### when to top of ListView, curVelocity reflected: " + initialVelocity);
}
if (Math.abs(initialVelocity) > mMinimumVelocity) {
flingWL(initialVelocity);
}
Expand Down

0 comments on commit 61bfee4

Please sign in to comment.