1+ package com .hjq .md .widget ;
2+
3+ import android .annotation .SuppressLint ;
4+ import android .content .Context ;
5+ import android .os .Build ;
6+ import android .support .annotation .RequiresApi ;
7+ import android .support .v4 .view .NestedScrollingChild ;
8+ import android .support .v4 .view .NestedScrollingChildHelper ;
9+ import android .support .v4 .view .ViewCompat ;
10+ import android .util .AttributeSet ;
11+ import android .view .MotionEvent ;
12+ import android .webkit .WebView ;
13+
14+ /**
15+ * NestedScrollWebView
16+ */
17+ public class NestedScrollWebView extends WebView implements NestedScrollingChild {
18+
19+ private NestedScrollingChildHelper mChildHelper ;
20+
21+ private int mLastMotionY ;
22+
23+ private final int [] mScrollOffset = new int [2 ];
24+ private final int [] mScrollConsumed = new int [2 ];
25+
26+ private int mNestedYOffset ;
27+ private boolean mChange ;
28+
29+ public NestedScrollWebView (Context context ) {
30+ super (context );
31+ init ();
32+ }
33+
34+ public NestedScrollWebView (Context context , AttributeSet attrs ) {
35+ super (context , attrs );
36+ init ();
37+ }
38+
39+ public NestedScrollWebView (Context context , AttributeSet attrs , int defStyleAttr ) {
40+ super (context , attrs , defStyleAttr );
41+ init ();
42+ }
43+
44+ @ RequiresApi (api = Build .VERSION_CODES .LOLLIPOP )
45+ public NestedScrollWebView (Context context , AttributeSet attrs , int defStyleAttr , int defStyleRes ) {
46+ super (context , attrs , defStyleAttr , defStyleRes );
47+ init ();
48+ }
49+
50+ public NestedScrollWebView (Context context , AttributeSet attrs , int defStyleAttr , boolean privateBrowsing ) {
51+ super (context , attrs , defStyleAttr , privateBrowsing );
52+ init ();
53+ }
54+
55+ private void init () {
56+ if (mChildHelper == null ) {
57+ mChildHelper = new NestedScrollingChildHelper (this );
58+ setNestedScrollingEnabled (true );
59+ }
60+ }
61+
62+ @ SuppressLint ("ClickableViewAccessibility" )
63+ @ Override
64+ public boolean onTouchEvent (MotionEvent event ) {
65+ boolean result = false ;
66+
67+ MotionEvent trackedEvent = MotionEvent .obtain (event );
68+
69+ final int action = event .getActionMasked ();
70+
71+ if (action == MotionEvent .ACTION_DOWN ) {
72+ mNestedYOffset = 0 ;
73+ }
74+
75+ int y = (int ) event .getY ();
76+
77+ event .offsetLocation (0 , mNestedYOffset );
78+
79+ switch (action ) {
80+ case MotionEvent .ACTION_DOWN :
81+ mChange = false ;
82+ mLastMotionY = y ;
83+ startNestedScroll (ViewCompat .SCROLL_AXIS_VERTICAL );
84+ result = super .onTouchEvent (event );
85+ break ;
86+ case MotionEvent .ACTION_MOVE :
87+ int deltaY = mLastMotionY - y ;
88+
89+ if (dispatchNestedPreScroll (0 , deltaY , mScrollConsumed , mScrollOffset )) {
90+ deltaY -= mScrollConsumed [1 ];
91+ trackedEvent .offsetLocation (0 , mScrollOffset [1 ]);
92+ mNestedYOffset += mScrollOffset [1 ];
93+ }
94+
95+ mLastMotionY = y - mScrollOffset [1 ];
96+
97+ int oldY = getScrollY ();
98+ int newScrollY = Math .max (0 , oldY + deltaY );
99+ int dyConsumed = newScrollY - oldY ;
100+ int dyUnconsumed = deltaY - dyConsumed ;
101+
102+ if (dispatchNestedScroll (0 , dyConsumed , 0 , dyUnconsumed , mScrollOffset )) {
103+ mLastMotionY -= mScrollOffset [1 ];
104+ trackedEvent .offsetLocation (0 , mScrollOffset [1 ]);
105+ mNestedYOffset += mScrollOffset [1 ];
106+ }
107+
108+ if (mScrollConsumed [1 ]==0 && mScrollOffset [1 ]==0 ) {
109+ if (mChange ){
110+ mChange =false ;
111+ trackedEvent .setAction (MotionEvent .ACTION_DOWN );
112+ super .onTouchEvent (trackedEvent );
113+ }else {
114+ result = super .onTouchEvent (trackedEvent );
115+ }
116+ trackedEvent .recycle ();
117+ }else {
118+ if (!mChange ){
119+ mChange = true ;
120+ super .onTouchEvent (MotionEvent .obtain (0 ,0 ,MotionEvent .ACTION_CANCEL ,0 ,0 ,0 ));
121+ }
122+ }
123+
124+ //result = super.onTouchEvent(trackedEvent);
125+ //trackedEvent.recycle();
126+ break ;
127+ case MotionEvent .ACTION_POINTER_DOWN :
128+ case MotionEvent .ACTION_UP :
129+ case MotionEvent .ACTION_CANCEL :
130+ stopNestedScroll ();
131+ result = super .onTouchEvent (event );
132+ break ;
133+ }
134+ return result ;
135+ }
136+
137+ // NestedScrollingChild
138+
139+ @ Override
140+ public void setNestedScrollingEnabled (boolean enabled ) {
141+ mChildHelper .setNestedScrollingEnabled (enabled );
142+ }
143+
144+ @ Override
145+ public boolean isNestedScrollingEnabled () {
146+ return mChildHelper .isNestedScrollingEnabled ();
147+ }
148+
149+ @ Override
150+ public boolean startNestedScroll (int axes ) {
151+ return mChildHelper .startNestedScroll (axes );
152+ }
153+
154+ @ Override
155+ public void stopNestedScroll () {
156+ mChildHelper .stopNestedScroll ();
157+ }
158+
159+ @ Override
160+ public boolean hasNestedScrollingParent () {
161+ return mChildHelper .hasNestedScrollingParent ();
162+ }
163+
164+ @ Override
165+ public boolean dispatchNestedScroll (int dxConsumed , int dyConsumed , int dxUnconsumed , int dyUnconsumed , int [] offsetInWindow ) {
166+ return mChildHelper .dispatchNestedScroll (dxConsumed , dyConsumed , dxUnconsumed , dyUnconsumed , offsetInWindow );
167+ }
168+
169+ @ Override
170+ public boolean dispatchNestedPreScroll (int dx , int dy , int [] consumed , int [] offsetInWindow ) {
171+ return mChildHelper .dispatchNestedPreScroll (dx , dy , consumed , offsetInWindow );
172+ }
173+
174+ @ Override
175+ public boolean dispatchNestedFling (float velocityX , float velocityY , boolean consumed ) {
176+ return mChildHelper .dispatchNestedFling (velocityX , velocityY , consumed );
177+ }
178+
179+ @ Override
180+ public boolean dispatchNestedPreFling (float velocityX , float velocityY ) {
181+ return mChildHelper .dispatchNestedPreFling (velocityX , velocityY );
182+ }
183+ }
0 commit comments