2 * Copyright © 2019 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
6 * Privacy Browser is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.views;
22 import android.content.Context;
23 import android.graphics.Bitmap;
24 import android.graphics.drawable.BitmapDrawable;
25 import android.graphics.drawable.Drawable;
26 import android.util.AttributeSet;
27 import android.view.MotionEvent;
28 import android.webkit.HttpAuthHandler;
29 import android.webkit.SslErrorHandler;
30 import android.webkit.WebView;
32 import androidx.annotation.NonNull;
33 import androidx.core.content.ContextCompat;
34 import androidx.core.view.NestedScrollingChild2;
35 import androidx.core.view.NestedScrollingChildHelper;
36 import androidx.core.view.ViewCompat;
38 import com.stoutner.privacybrowser.R;
40 import java.util.ArrayList;
41 import java.util.Collections;
42 import java.util.Date;
43 import java.util.List;
45 // NestedScrollWebView extends WebView to handle nested scrolls (scrolling the app bar off the screen).
46 public class NestedScrollWebView extends WebView implements NestedScrollingChild2 {
47 // These constants identify the blocklists.
48 public final static int BLOCKED_REQUESTS = 0;
49 public final static int EASYLIST = 1;
50 public final static int EASYPRIVACY = 2;
51 public final static int FANBOYS_ANNOYANCE_LIST = 3;
52 public final static int FANBOYS_SOCIAL_BLOCKING_LIST = 4;
53 public final static int ULTRALIST = 5;
54 public final static int ULTRAPRIVACY = 6;
55 public final static int THIRD_PARTY_REQUESTS = 7;
57 // Keep a copy of the WebView fragment ID.
58 private long webViewFragmentId;
60 // Store the handlers.
61 private SslErrorHandler sslErrorHandler;
62 private HttpAuthHandler httpAuthHandler;
64 // Track if domain settings are applied to this nested scroll WebView and, if so, the database ID.
65 private boolean domainSettingsApplied;
66 private int domainSettingsDatabaseId;
68 // Keep track of when the domain name changes so that domain settings can be reapplied. This should never be null.
69 private String currentDomainName = "";
71 // Track the status of first-party cookies.
72 private boolean acceptFirstPartyCookies;
74 // Track the domain settings JavaScript status. This can be removed once night mode does not require JavaScript.
75 private boolean domainSettingsJavaScriptEnabled;
77 // Track the resource requests.
78 private List<String[]> resourceRequests = Collections.synchronizedList(new ArrayList<>()); // Using a synchronized list makes adding resource requests thread safe.
79 private boolean easyListEnabled;
80 private boolean easyPrivacyEnabled;
81 private boolean fanboysAnnoyanceListEnabled;
82 private boolean fanboysSocialBlockingListEnabled;
83 private boolean ultraListEnabled;
84 private boolean ultraPrivacyEnabled;
85 private boolean blockAllThirdPartyRequests;
86 private int blockedRequests;
87 private int easyListBlockedRequests;
88 private int easyPrivacyBlockedRequests;
89 private int fanboysAnnoyanceListBlockedRequests;
90 private int fanboysSocialBlockingListBlockedRequests;
91 private int ultraListBlockedRequests;
92 private int ultraPrivacyBlockedRequests;
93 private int thirdPartyBlockedRequests;
95 // The pinned SSL certificate variables.
96 private boolean hasPinnedSslCertificate;
97 private String pinnedSslIssuedToCName;
98 private String pinnedSslIssuedToOName;
99 private String pinnedSslIssuedToUName;
100 private String pinnedSslIssuedByCName;
101 private String pinnedSslIssuedByOName;
102 private String pinnedSslIssuedByUName;
103 private Date pinnedSslStartDate;
104 private Date pinnedSslEndDate;
106 // The current IP addresses variables.
107 private boolean hasCurrentIpAddresses;
108 private String currentIpAddresses;
110 // The pinned IP addresses variables.
111 private boolean hasPinnedIpAddresses;
112 private String pinnedIpAddresses;
114 // The ignore pinned domain information tracker. This is set when a user proceeds past a pinned mismatch dialog to prevent the dialog from showing again until after the domain changes.
115 private boolean ignorePinnedDomainInformation;
117 // Track navigation of history.
118 private boolean navigatingHistory;
120 // The default or favorite icon.
121 private Bitmap favoriteOrDefaultIcon;
124 private boolean nightMode;
126 // Track swipe to refresh.
127 private boolean swipeToRefresh;
129 // The nested scrolling child helper is used throughout the class.
130 private NestedScrollingChildHelper nestedScrollingChildHelper;
132 // The previous Y position needs to be tracked between motion events.
133 private int previousYPosition;
137 // The basic constructor.
138 public NestedScrollWebView(Context context) {
139 // Roll up to the next constructor.
143 // The intermediate constructor.
144 public NestedScrollWebView(Context context, AttributeSet attributeSet) {
145 // Roll up to the next constructor.
146 this(context, attributeSet, android.R.attr.webViewStyle);
149 // The full constructor.
150 public NestedScrollWebView(Context context, AttributeSet attributeSet, int defaultStyle) {
151 // Run the default commands.
152 super(context, attributeSet, defaultStyle);
154 // Initialize the nested scrolling child helper.
155 nestedScrollingChildHelper = new NestedScrollingChildHelper(this);
157 // Enable nested scrolling by default.
158 nestedScrollingChildHelper.setNestedScrollingEnabled(true);
163 // WebView Fragment ID.
164 public void setWebViewFragmentId(long webViewFragmentId) {
165 // Store the WebView fragment ID.
166 this.webViewFragmentId = webViewFragmentId;
169 public long getWebViewFragmentId() {
170 // Return the WebView fragment ID.
171 return webViewFragmentId;
175 // SSL error handler.
176 public void setSslErrorHandler(SslErrorHandler sslErrorHandler) {
177 // Store the current SSL error handler.
178 this.sslErrorHandler = sslErrorHandler;
181 public SslErrorHandler getSslErrorHandler() {
182 // Return the current SSL error handler.
183 return sslErrorHandler;
186 public void resetSslErrorHandler() {
187 // Reset the current SSL error handler.
188 sslErrorHandler = null;
192 // HTTP authentication handler.
193 public void setHttpAuthHandler(HttpAuthHandler httpAuthHandler) {
194 // Store the current HTTP authentication handler.
195 this.httpAuthHandler = httpAuthHandler;
198 public HttpAuthHandler getHttpAuthHandler() {
199 // Return the current HTTP authentication handler.
200 return httpAuthHandler;
203 public void resetHttpAuthHandler() {
204 // Reset the current HTTP authentication handler.
205 httpAuthHandler = null;
210 public void setDomainSettingsApplied(boolean applied) {
211 // Store the domain settings applied status.
212 domainSettingsApplied = applied;
215 public boolean getDomainSettingsApplied() {
216 // Return the domain settings applied status.
217 return domainSettingsApplied;
221 // Domain settings database ID.
222 public void setDomainSettingsDatabaseId(int databaseId) {
223 // Store the domain settings database ID.
224 domainSettingsDatabaseId = databaseId;
227 public int getDomainSettingsDatabaseId() {
228 // Return the domain settings database ID.
229 return domainSettingsDatabaseId;
233 // Current domain name. To function well when called, the domain name should never be allowed to be null.
234 public void setCurrentDomainName(@NonNull String domainName) {
235 // Store the current domain name.
236 currentDomainName = domainName;
239 public void resetCurrentDomainName() {
240 // Reset the current domain name.
241 currentDomainName = "";
244 public String getCurrentDomainName() {
245 // Return the current domain name.
246 return currentDomainName;
250 // First-party cookies.
251 public void setAcceptFirstPartyCookies(boolean status) {
252 // Store the accept first-party cookies status.
253 acceptFirstPartyCookies = status;
256 public boolean getAcceptFirstPartyCookies() {
257 // Return the accept first-party cookies status.
258 return acceptFirstPartyCookies;
262 // Domain settings JavaScript enabled. This can be removed once night mode does not require JavaScript.
263 public void setDomainSettingsJavaScriptEnabled(boolean status) {
264 // Store the domain settings JavaScript status.
265 domainSettingsJavaScriptEnabled = status;
268 public boolean getDomainSettingsJavaScriptEnabled() {
269 // Return the domain settings JavaScript status.
270 return domainSettingsJavaScriptEnabled;
274 // Resource requests.
275 public void addResourceRequest(String[] resourceRequest) {
276 // Add the resource request to the list.
277 resourceRequests.add(resourceRequest);
280 public List<String[]> getResourceRequests() {
281 // Return the list of resource requests as an array list.
282 return resourceRequests;
285 public void clearResourceRequests() {
286 // Clear the resource requests.
287 resourceRequests.clear();
292 public void enableBlocklist(int blocklist, boolean status) {
293 // Update the status of the indicated blocklist.
296 // Update the status of the blocklist.
297 easyListEnabled = status;
301 // Update the status of the blocklist.
302 easyPrivacyEnabled = status;
305 case FANBOYS_ANNOYANCE_LIST:
306 // Update the status of the blocklist.
307 fanboysAnnoyanceListEnabled = status;
310 case FANBOYS_SOCIAL_BLOCKING_LIST:
311 // Update the status of the blocklist.
312 fanboysSocialBlockingListEnabled = status;
316 // Update the status of the blocklist.
317 ultraListEnabled = status;
321 // Update the status of the blocklist.
322 ultraPrivacyEnabled = status;
325 case THIRD_PARTY_REQUESTS:
326 // Update the status of the blocklist.
327 blockAllThirdPartyRequests = status;
332 public boolean isBlocklistEnabled(int blocklist) {
333 // Get the status of the indicated blocklist.
336 // Return the status of the blocklist.
337 return easyListEnabled;
340 // Return the status of the blocklist.
341 return easyPrivacyEnabled;
343 case FANBOYS_ANNOYANCE_LIST:
344 // Return the status of the blocklist.
345 return fanboysAnnoyanceListEnabled;
347 case FANBOYS_SOCIAL_BLOCKING_LIST:
348 // Return the status of the blocklist.
349 return fanboysSocialBlockingListEnabled;
352 // Return the status of the blocklist.
353 return ultraListEnabled;
356 // Return the status of the blocklist.
357 return ultraPrivacyEnabled;
359 case THIRD_PARTY_REQUESTS:
360 // Return the status of the blocklist.
361 return blockAllThirdPartyRequests;
364 // The default value is required but should never be used.
370 // Resource request counters.
371 public void resetRequestsCounters() {
372 // Reset all the resource request counters.
374 easyListBlockedRequests = 0;
375 easyPrivacyBlockedRequests = 0;
376 fanboysAnnoyanceListBlockedRequests = 0;
377 fanboysSocialBlockingListBlockedRequests = 0;
378 ultraListBlockedRequests = 0;
379 ultraPrivacyBlockedRequests = 0;
380 thirdPartyBlockedRequests = 0;
383 public void incrementRequestsCount(int blocklist) {
384 // Increment the count of the indicated blocklist.
386 case BLOCKED_REQUESTS:
387 // Increment the blocked requests count.
392 // Increment the EasyList blocked requests count.
393 easyListBlockedRequests++;
397 // Increment the EasyPrivacy blocked requests count.
398 easyPrivacyBlockedRequests++;
401 case FANBOYS_ANNOYANCE_LIST:
402 // Increment the Fanboy's Annoyance List blocked requests count.
403 fanboysAnnoyanceListBlockedRequests++;
406 case FANBOYS_SOCIAL_BLOCKING_LIST:
407 // Increment the Fanboy's Social Blocking List blocked requests count.
408 fanboysSocialBlockingListBlockedRequests++;
412 // Increment the UltraList blocked requests count.
413 ultraListBlockedRequests++;
417 // Increment the UltraPrivacy blocked requests count.
418 ultraPrivacyBlockedRequests++;
421 case THIRD_PARTY_REQUESTS:
422 // Increment the Third Party blocked requests count.
423 thirdPartyBlockedRequests++;
428 public int getRequestsCount(int blocklist) {
429 // Get the count of the indicated blocklist.
431 case BLOCKED_REQUESTS:
432 // Return the blocked requests count.
433 return blockedRequests;
436 // Return the EasyList blocked requests count.
437 return easyListBlockedRequests;
440 // Return the EasyPrivacy blocked requests count.
441 return easyPrivacyBlockedRequests;
443 case FANBOYS_ANNOYANCE_LIST:
444 // Return the Fanboy's Annoyance List blocked requests count.
445 return fanboysAnnoyanceListBlockedRequests;
447 case FANBOYS_SOCIAL_BLOCKING_LIST:
448 // Return the Fanboy's Social Blocking List blocked requests count.
449 return fanboysSocialBlockingListBlockedRequests;
452 // Return the UltraList blocked requests count.
453 return ultraListBlockedRequests;
456 // Return the UltraPrivacy blocked requests count.
457 return ultraPrivacyBlockedRequests;
459 case THIRD_PARTY_REQUESTS:
460 // Return the Third Party blocked requests count.
461 return thirdPartyBlockedRequests;
464 // Return 0. This should never end up being called.
470 // Pinned SSL certificates.
471 public boolean hasPinnedSslCertificate() {
472 // Return the status of the pinned SSL certificate.
473 return hasPinnedSslCertificate;
476 public void setPinnedSslCertificate(String issuedToCName, String issuedToOName, String issuedToUName, String issuedByCName, String issuedByOName, String issuedByUName, Date startDate, Date endDate) {
477 // Store the pinned SSL certificate information.
478 pinnedSslIssuedToCName = issuedToCName;
479 pinnedSslIssuedToOName = issuedToOName;
480 pinnedSslIssuedToUName = issuedToUName;
481 pinnedSslIssuedByCName = issuedByCName;
482 pinnedSslIssuedByOName = issuedByOName;
483 pinnedSslIssuedByUName = issuedByUName;
484 pinnedSslStartDate = startDate;
485 pinnedSslEndDate = endDate;
487 // Set the pinned SSL certificate tracker.
488 hasPinnedSslCertificate = true;
491 public ArrayList<Object> getPinnedSslCertificate() {
492 // Initialize an array list.
493 ArrayList<Object> arrayList = new ArrayList<>();
495 // Create the SSL certificate string array.
496 String[] sslCertificateStringArray = new String[] {pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName};
498 // Create the SSL certificate date array.
499 Date[] sslCertificateDateArray = new Date[] {pinnedSslStartDate, pinnedSslEndDate};
501 // Add the arrays to the array list.
502 arrayList.add(sslCertificateStringArray);
503 arrayList.add(sslCertificateDateArray);
505 // Return the pinned SSL certificate array list.
509 public void clearPinnedSslCertificate() {
510 // Clear the pinned SSL certificate.
511 pinnedSslIssuedToCName = null;
512 pinnedSslIssuedToOName = null;
513 pinnedSslIssuedToUName = null;
514 pinnedSslIssuedByCName = null;
515 pinnedSslIssuedByOName = null;
516 pinnedSslIssuedByUName = null;
517 pinnedSslStartDate = null;
518 pinnedSslEndDate = null;
520 // Clear the pinned SSL certificate tracker.
521 hasPinnedSslCertificate = false;
525 // Current IP addresses.
526 public boolean hasCurrentIpAddresses() {
527 // Return the status of the current IP addresses.
528 return hasCurrentIpAddresses;
531 public void setCurrentIpAddresses(String ipAddresses) {
532 // Store the current IP addresses.
533 currentIpAddresses = ipAddresses;
535 // Set the current IP addresses tracker.
536 hasCurrentIpAddresses = true;
539 public String getCurrentIpAddresses() {
540 // Return the current IP addresses.
541 return currentIpAddresses;
544 public void clearCurrentIpAddresses() {
545 // Clear the current IP addresses.
546 currentIpAddresses = null;
548 // Clear the current IP addresses tracker.
549 hasCurrentIpAddresses = false;
553 // Pinned IP addresses.
554 public boolean hasPinnedIpAddresses() {
555 // Return the status of the pinned IP addresses.
556 return hasPinnedIpAddresses;
559 public void setPinnedIpAddresses(String ipAddresses) {
560 // Store the pinned IP addresses.
561 pinnedIpAddresses = ipAddresses;
563 // Set the pinned IP addresses tracker.
564 hasPinnedIpAddresses = true;
567 public String getPinnedIpAddresses() {
568 // Return the pinned IP addresses.
569 return pinnedIpAddresses;
572 public void clearPinnedIpAddresses() {
573 // Clear the pinned IP addresses.
574 pinnedIpAddresses = null;
576 // Clear the pinned IP addresses tracker.
577 hasPinnedIpAddresses = false;
581 // Ignore pinned information.
582 public void setIgnorePinnedDomainInformation(boolean status) {
583 // Set the status of the ignore pinned domain information tracker.
584 ignorePinnedDomainInformation = status;
587 // The syntax looks better as written, even if it is always inverted.
588 @SuppressWarnings("BooleanMethodIsAlwaysInverted")
589 public boolean ignorePinnedDomainInformation() {
590 // Return the status of the ignore pinned domain information tracker.
591 return ignorePinnedDomainInformation;
595 // Navigating history.
596 public void setNavigatingHistory(boolean status) {
597 // Set the status of navigating history.
598 navigatingHistory = status;
601 public boolean getNavigatingHistory() {
602 // Return the status of navigating history.
603 return navigatingHistory;
607 // Favorite or default icon.
608 public void initializeFavoriteIcon() {
609 // Get the default favorite icon drawable. `ContextCompat` must be used until API >= 21.
610 Drawable favoriteIconDrawable = ContextCompat.getDrawable(getContext(), R.drawable.world);
612 // Cast the favorite icon drawable to a bitmap drawable.
613 BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
615 // Remove the incorrect warning below that the favorite icon bitmap drawable might be null.
616 assert favoriteIconBitmapDrawable != null;
618 // Store the default icon bitmap.
619 favoriteOrDefaultIcon = favoriteIconBitmapDrawable.getBitmap();
622 public void setFavoriteOrDefaultIcon(Bitmap icon) {
623 // Scale the favorite icon bitmap down if it is larger than 256 x 256. Filtering uses bilinear interpolation.
624 if ((icon.getHeight() > 256) || (icon.getWidth() > 256)) {
625 favoriteOrDefaultIcon = Bitmap.createScaledBitmap(icon, 256, 256, true);
627 // Store the icon as presented.
628 favoriteOrDefaultIcon = icon;
632 public Bitmap getFavoriteOrDefaultIcon() {
633 // Return the favorite or default icon.
634 return favoriteOrDefaultIcon;
639 public void setNightMode(boolean status) {
640 // Store the night mode status.
644 public boolean getNightMode() {
645 // Return the night mode status.
651 public void setSwipeToRefresh(boolean status) {
652 // Store the swipe to refresh status.
653 swipeToRefresh = status;
656 public boolean getSwipeToRefresh() {
657 // Return the swipe to refresh status.
658 return swipeToRefresh;
663 public int getHorizontalScrollRange() {
664 // Return the horizontal scroll range.
665 return computeHorizontalScrollRange();
668 public int getVerticalScrollRange() {
669 // Return the vertical scroll range.
670 return computeVerticalScrollRange();
676 public boolean onTouchEvent(MotionEvent motionEvent) {
677 // Initialize a tracker to return if this motion event is handled.
678 boolean motionEventHandled;
680 // Run the commands for the given motion event action.
681 switch (motionEvent.getAction()) {
682 case MotionEvent.ACTION_DOWN:
683 // Start nested scrolling along the vertical axis. `ViewCompat` must be used until the minimum API >= 21.
684 startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
686 // Save the current Y position. Action down will not be called again until a new motion starts.
687 previousYPosition = (int) motionEvent.getY();
689 // Run the default commands.
690 motionEventHandled = super.onTouchEvent(motionEvent);
693 case MotionEvent.ACTION_MOVE:
694 // Get the current Y position.
695 int currentYMotionPosition = (int) motionEvent.getY();
697 // Calculate the pre-scroll delta Y.
698 int preScrollDeltaY = previousYPosition - currentYMotionPosition;
700 // Initialize a variable to track how much of the scroll is consumed.
701 int[] consumedScroll = new int[2];
703 // Initialize a variable to track the offset in the window.
704 int[] offsetInWindow = new int[2];
706 // Get the WebView Y position.
707 int webViewYPosition = getScrollY();
709 // Set the scroll delta Y to initially be the same as the pre-scroll delta Y.
710 int scrollDeltaY = preScrollDeltaY;
712 // Dispatch the nested pre-school. This scrolls the app bar if it needs it. `offsetInWindow` will be returned with an updated value.
713 if (dispatchNestedPreScroll(0, preScrollDeltaY, consumedScroll, offsetInWindow)) {
714 // Update the scroll delta Y if some of it was consumed.
715 // There is currently a bug in Android where if scrolling up at a certain slow speed the input can lock the pre scroll and continue to consume it after the app bar is fully displayed.
716 scrollDeltaY = preScrollDeltaY - consumedScroll[1];
719 // Check to see if the WebView is at the top and and the scroll action is downward.
720 if ((webViewYPosition == 0) && (scrollDeltaY < 0)) { // Swipe to refresh is being engaged.
721 // Stop the nested scroll so that swipe to refresh has complete control. This way releasing the scroll to refresh circle doesn't scroll the WebView at the same time.
723 } else { // Swipe to refresh is not being engaged.
724 // Start the nested scroll so that the app bar can scroll off the screen.
725 startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
727 // Dispatch the nested scroll. This scrolls the WebView. The delta Y unconsumed normally controls the swipe refresh layout, but that is handled with the `if` statement above.
728 dispatchNestedScroll(0, scrollDeltaY, 0, 0, offsetInWindow);
730 // Store the current Y position for use in the next action move.
731 previousYPosition = previousYPosition - scrollDeltaY;
734 // Run the default commands.
735 motionEventHandled = super.onTouchEvent(motionEvent);
740 // Stop nested scrolling.
743 // Run the default commands.
744 motionEventHandled = super.onTouchEvent(motionEvent);
747 // Perform a click. This is required by the Android accessibility guidelines.
750 // Return the status of the motion event.
751 return motionEventHandled;
754 // The Android accessibility guidelines require overriding `performClick()` and calling it from `onTouchEvent()`.
756 public boolean performClick() {
757 return super.performClick();
761 // Method from NestedScrollingChild.
763 public void setNestedScrollingEnabled(boolean status) {
764 // Set the status of the nested scrolling.
765 nestedScrollingChildHelper.setNestedScrollingEnabled(status);
768 // Method from NestedScrollingChild.
770 public boolean isNestedScrollingEnabled() {
771 // Return the status of nested scrolling.
772 return nestedScrollingChildHelper.isNestedScrollingEnabled();
776 // Method from NestedScrollingChild.
778 public boolean startNestedScroll(int axes) {
779 // Start a nested scroll along the indicated axes.
780 return nestedScrollingChildHelper.startNestedScroll(axes);
783 // Method from NestedScrollingChild2.
785 public boolean startNestedScroll(int axes, int type) {
786 // Start a nested scroll along the indicated axes for the given type of input which caused the scroll event.
787 return nestedScrollingChildHelper.startNestedScroll(axes, type);
791 // Method from NestedScrollingChild.
793 public void stopNestedScroll() {
794 // Stop the nested scroll.
795 nestedScrollingChildHelper.stopNestedScroll();
798 // Method from NestedScrollingChild2.
800 public void stopNestedScroll(int type) {
801 // Stop the nested scroll of the given type of input which caused the scroll event.
802 nestedScrollingChildHelper.stopNestedScroll(type);
806 // Method from NestedScrollingChild.
808 public boolean hasNestedScrollingParent() {
809 // Return the status of the nested scrolling parent.
810 return nestedScrollingChildHelper.hasNestedScrollingParent();
813 // Method from NestedScrollingChild2.
815 public boolean hasNestedScrollingParent(int type) {
816 // return the status of the nested scrolling parent for the given type of input which caused the scroll event.
817 return nestedScrollingChildHelper.hasNestedScrollingParent(type);
821 // Method from NestedScrollingChild.
823 public boolean dispatchNestedPreScroll(int deltaX, int deltaY, int[] consumed, int[] offsetInWindow) {
824 // Dispatch a nested pre-scroll with the specified deltas, which lets a parent to consume some of the scroll if desired.
825 return nestedScrollingChildHelper.dispatchNestedPreScroll(deltaX, deltaY, consumed, offsetInWindow);
828 // Method from NestedScrollingChild2.
830 public boolean dispatchNestedPreScroll(int deltaX, int deltaY, int[] consumed, int[] offsetInWindow, int type) {
831 // Dispatch a nested pre-scroll with the specified deltas for the given type of input which caused the scroll event, which lets a parent to consume some of the scroll if desired.
832 return nestedScrollingChildHelper.dispatchNestedPreScroll(deltaX, deltaY, consumed, offsetInWindow, type);
836 // Method from NestedScrollingChild.
838 public boolean dispatchNestedScroll(int deltaXConsumed, int deltaYConsumed, int deltaXUnconsumed, int deltaYUnconsumed, int[] offsetInWindow) {
839 // Dispatch a nested scroll with the specified deltas.
840 return nestedScrollingChildHelper.dispatchNestedScroll(deltaXConsumed, deltaYConsumed, deltaXUnconsumed, deltaYUnconsumed, offsetInWindow);
843 // Method from NestedScrollingChild2.
845 public boolean dispatchNestedScroll(int deltaXConsumed, int deltaYConsumed, int deltaXUnconsumed, int deltaYUnconsumed, int[] offsetInWindow, int type) {
846 // Dispatch a nested scroll with the specified deltas for the given type of input which caused the scroll event.
847 return nestedScrollingChildHelper.dispatchNestedScroll(deltaXConsumed, deltaYConsumed, deltaXUnconsumed, deltaYUnconsumed, offsetInWindow, type);
851 // Method from NestedScrollingChild.
853 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
854 // Dispatch a nested pre-fling with the specified velocity, which lets a parent consume the fling if desired.
855 return nestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
858 // Method from NestedScrollingChild.
860 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
861 // Dispatch a nested fling with the specified velocity.
862 return nestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);