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 the current URL. This is used to not block resource requests to the main URL.
69 private String currentUrl;
71 // Keep track of when the domain name changes so that domain settings can be reapplied. This should never be null.
72 private String currentDomainName = "";
74 // Track the status of first-party cookies.
75 private boolean acceptFirstPartyCookies;
77 // Track the domain settings JavaScript status. This can be removed once night mode does not require JavaScript.
78 private boolean domainSettingsJavaScriptEnabled;
80 // Track the resource requests.
81 private List<String[]> resourceRequests = Collections.synchronizedList(new ArrayList<>()); // Using a synchronized list makes adding resource requests thread safe.
82 private boolean easyListEnabled;
83 private boolean easyPrivacyEnabled;
84 private boolean fanboysAnnoyanceListEnabled;
85 private boolean fanboysSocialBlockingListEnabled;
86 private boolean ultraListEnabled;
87 private boolean ultraPrivacyEnabled;
88 private boolean blockAllThirdPartyRequests;
89 private int blockedRequests;
90 private int easyListBlockedRequests;
91 private int easyPrivacyBlockedRequests;
92 private int fanboysAnnoyanceListBlockedRequests;
93 private int fanboysSocialBlockingListBlockedRequests;
94 private int ultraListBlockedRequests;
95 private int ultraPrivacyBlockedRequests;
96 private int thirdPartyBlockedRequests;
98 // The pinned SSL certificate variables.
99 private boolean hasPinnedSslCertificate;
100 private String pinnedSslIssuedToCName;
101 private String pinnedSslIssuedToOName;
102 private String pinnedSslIssuedToUName;
103 private String pinnedSslIssuedByCName;
104 private String pinnedSslIssuedByOName;
105 private String pinnedSslIssuedByUName;
106 private Date pinnedSslStartDate;
107 private Date pinnedSslEndDate;
109 // The current IP addresses variables.
110 private boolean hasCurrentIpAddresses;
111 private String currentIpAddresses;
113 // The pinned IP addresses variables.
114 private boolean hasPinnedIpAddresses;
115 private String pinnedIpAddresses;
117 // 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.
118 private boolean ignorePinnedDomainInformation;
120 // The default or favorite icon.
121 private Bitmap favoriteOrDefaultIcon;
124 private boolean nightMode;
126 // Track swipe to refresh.
127 private boolean swipeToRefresh;
129 // Track a URL waiting for a proxy.
130 private String waitingForProxyUrlString = "";
132 // The nested scrolling child helper is used throughout the class.
133 private NestedScrollingChildHelper nestedScrollingChildHelper;
135 // The previous Y position needs to be tracked between motion events.
136 private int previousYPosition;
140 // The basic constructor.
141 public NestedScrollWebView(Context context) {
142 // Roll up to the next constructor.
146 // The intermediate constructor.
147 public NestedScrollWebView(Context context, AttributeSet attributeSet) {
148 // Roll up to the next constructor.
149 this(context, attributeSet, android.R.attr.webViewStyle);
152 // The full constructor.
153 public NestedScrollWebView(Context context, AttributeSet attributeSet, int defaultStyle) {
154 // Run the default commands.
155 super(context, attributeSet, defaultStyle);
157 // Initialize the nested scrolling child helper.
158 nestedScrollingChildHelper = new NestedScrollingChildHelper(this);
160 // Enable nested scrolling by default.
161 nestedScrollingChildHelper.setNestedScrollingEnabled(true);
166 // WebView Fragment ID.
167 public void setWebViewFragmentId(long webViewFragmentId) {
168 // Store the WebView fragment ID.
169 this.webViewFragmentId = webViewFragmentId;
172 public long getWebViewFragmentId() {
173 // Return the WebView fragment ID.
174 return webViewFragmentId;
178 // SSL error handler.
179 public void setSslErrorHandler(SslErrorHandler sslErrorHandler) {
180 // Store the current SSL error handler.
181 this.sslErrorHandler = sslErrorHandler;
184 public SslErrorHandler getSslErrorHandler() {
185 // Return the current SSL error handler.
186 return sslErrorHandler;
189 public void resetSslErrorHandler() {
190 // Reset the current SSL error handler.
191 sslErrorHandler = null;
195 // HTTP authentication handler.
196 public void setHttpAuthHandler(HttpAuthHandler httpAuthHandler) {
197 // Store the current HTTP authentication handler.
198 this.httpAuthHandler = httpAuthHandler;
201 public HttpAuthHandler getHttpAuthHandler() {
202 // Return the current HTTP authentication handler.
203 return httpAuthHandler;
206 public void resetHttpAuthHandler() {
207 // Reset the current HTTP authentication handler.
208 httpAuthHandler = null;
213 public void setDomainSettingsApplied(boolean applied) {
214 // Store the domain settings applied status.
215 domainSettingsApplied = applied;
218 public boolean getDomainSettingsApplied() {
219 // Return the domain settings applied status.
220 return domainSettingsApplied;
224 // Domain settings database ID.
225 public void setDomainSettingsDatabaseId(int databaseId) {
226 // Store the domain settings database ID.
227 domainSettingsDatabaseId = databaseId;
230 public int getDomainSettingsDatabaseId() {
231 // Return the domain settings database ID.
232 return domainSettingsDatabaseId;
237 public void setCurrentUrl(String url) {
238 // Store the current URL.
242 public String getCurrentUrl() {
243 // Return the current URL.
248 // Current domain name. To function well when called, the domain name should never be allowed to be null.
249 public void setCurrentDomainName(@NonNull String domainName) {
250 // Store the current domain name.
251 currentDomainName = domainName;
254 public void resetCurrentDomainName() {
255 // Reset the current domain name.
256 currentDomainName = "";
259 public String getCurrentDomainName() {
260 // Return the current domain name.
261 return currentDomainName;
265 // First-party cookies.
266 public void setAcceptFirstPartyCookies(boolean status) {
267 // Store the accept first-party cookies status.
268 acceptFirstPartyCookies = status;
271 public boolean getAcceptFirstPartyCookies() {
272 // Return the accept first-party cookies status.
273 return acceptFirstPartyCookies;
277 // Domain settings JavaScript enabled. This can be removed once night mode does not require JavaScript.
278 public void setDomainSettingsJavaScriptEnabled(boolean status) {
279 // Store the domain settings JavaScript status.
280 domainSettingsJavaScriptEnabled = status;
283 public boolean getDomainSettingsJavaScriptEnabled() {
284 // Return the domain settings JavaScript status.
285 return domainSettingsJavaScriptEnabled;
289 // Resource requests.
290 public void addResourceRequest(String[] resourceRequest) {
291 // Add the resource request to the list.
292 resourceRequests.add(resourceRequest);
295 public List<String[]> getResourceRequests() {
296 // Return the list of resource requests as an array list.
297 return resourceRequests;
300 public void clearResourceRequests() {
301 // Clear the resource requests.
302 resourceRequests.clear();
307 public void enableBlocklist(int blocklist, boolean status) {
308 // Update the status of the indicated blocklist.
311 // Update the status of the blocklist.
312 easyListEnabled = status;
316 // Update the status of the blocklist.
317 easyPrivacyEnabled = status;
320 case FANBOYS_ANNOYANCE_LIST:
321 // Update the status of the blocklist.
322 fanboysAnnoyanceListEnabled = status;
325 case FANBOYS_SOCIAL_BLOCKING_LIST:
326 // Update the status of the blocklist.
327 fanboysSocialBlockingListEnabled = status;
331 // Update the status of the blocklist.
332 ultraListEnabled = status;
336 // Update the status of the blocklist.
337 ultraPrivacyEnabled = status;
340 case THIRD_PARTY_REQUESTS:
341 // Update the status of the blocklist.
342 blockAllThirdPartyRequests = status;
347 public boolean isBlocklistEnabled(int blocklist) {
348 // Get the status of the indicated blocklist.
351 // Return the status of the blocklist.
352 return easyListEnabled;
355 // Return the status of the blocklist.
356 return easyPrivacyEnabled;
358 case FANBOYS_ANNOYANCE_LIST:
359 // Return the status of the blocklist.
360 return fanboysAnnoyanceListEnabled;
362 case FANBOYS_SOCIAL_BLOCKING_LIST:
363 // Return the status of the blocklist.
364 return fanboysSocialBlockingListEnabled;
367 // Return the status of the blocklist.
368 return ultraListEnabled;
371 // Return the status of the blocklist.
372 return ultraPrivacyEnabled;
374 case THIRD_PARTY_REQUESTS:
375 // Return the status of the blocklist.
376 return blockAllThirdPartyRequests;
379 // The default value is required but should never be used.
385 // Resource request counters.
386 public void resetRequestsCounters() {
387 // Reset all the resource request counters.
389 easyListBlockedRequests = 0;
390 easyPrivacyBlockedRequests = 0;
391 fanboysAnnoyanceListBlockedRequests = 0;
392 fanboysSocialBlockingListBlockedRequests = 0;
393 ultraListBlockedRequests = 0;
394 ultraPrivacyBlockedRequests = 0;
395 thirdPartyBlockedRequests = 0;
398 public void incrementRequestsCount(int blocklist) {
399 // Increment the count of the indicated blocklist.
401 case BLOCKED_REQUESTS:
402 // Increment the blocked requests count.
407 // Increment the EasyList blocked requests count.
408 easyListBlockedRequests++;
412 // Increment the EasyPrivacy blocked requests count.
413 easyPrivacyBlockedRequests++;
416 case FANBOYS_ANNOYANCE_LIST:
417 // Increment the Fanboy's Annoyance List blocked requests count.
418 fanboysAnnoyanceListBlockedRequests++;
421 case FANBOYS_SOCIAL_BLOCKING_LIST:
422 // Increment the Fanboy's Social Blocking List blocked requests count.
423 fanboysSocialBlockingListBlockedRequests++;
427 // Increment the UltraList blocked requests count.
428 ultraListBlockedRequests++;
432 // Increment the UltraPrivacy blocked requests count.
433 ultraPrivacyBlockedRequests++;
436 case THIRD_PARTY_REQUESTS:
437 // Increment the Third Party blocked requests count.
438 thirdPartyBlockedRequests++;
443 public int getRequestsCount(int blocklist) {
444 // Get the count of the indicated blocklist.
446 case BLOCKED_REQUESTS:
447 // Return the blocked requests count.
448 return blockedRequests;
451 // Return the EasyList blocked requests count.
452 return easyListBlockedRequests;
455 // Return the EasyPrivacy blocked requests count.
456 return easyPrivacyBlockedRequests;
458 case FANBOYS_ANNOYANCE_LIST:
459 // Return the Fanboy's Annoyance List blocked requests count.
460 return fanboysAnnoyanceListBlockedRequests;
462 case FANBOYS_SOCIAL_BLOCKING_LIST:
463 // Return the Fanboy's Social Blocking List blocked requests count.
464 return fanboysSocialBlockingListBlockedRequests;
467 // Return the UltraList blocked requests count.
468 return ultraListBlockedRequests;
471 // Return the UltraPrivacy blocked requests count.
472 return ultraPrivacyBlockedRequests;
474 case THIRD_PARTY_REQUESTS:
475 // Return the Third Party blocked requests count.
476 return thirdPartyBlockedRequests;
479 // Return 0. This should never end up being called.
485 // Pinned SSL certificates.
486 public boolean hasPinnedSslCertificate() {
487 // Return the status of the pinned SSL certificate.
488 return hasPinnedSslCertificate;
491 public void setPinnedSslCertificate(String issuedToCName, String issuedToOName, String issuedToUName, String issuedByCName, String issuedByOName, String issuedByUName, Date startDate, Date endDate) {
492 // Store the pinned SSL certificate information.
493 pinnedSslIssuedToCName = issuedToCName;
494 pinnedSslIssuedToOName = issuedToOName;
495 pinnedSslIssuedToUName = issuedToUName;
496 pinnedSslIssuedByCName = issuedByCName;
497 pinnedSslIssuedByOName = issuedByOName;
498 pinnedSslIssuedByUName = issuedByUName;
499 pinnedSslStartDate = startDate;
500 pinnedSslEndDate = endDate;
502 // Set the pinned SSL certificate tracker.
503 hasPinnedSslCertificate = true;
506 public ArrayList<Object> getPinnedSslCertificate() {
507 // Initialize an array list.
508 ArrayList<Object> arrayList = new ArrayList<>();
510 // Create the SSL certificate string array.
511 String[] sslCertificateStringArray = new String[] {pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName};
513 // Create the SSL certificate date array.
514 Date[] sslCertificateDateArray = new Date[] {pinnedSslStartDate, pinnedSslEndDate};
516 // Add the arrays to the array list.
517 arrayList.add(sslCertificateStringArray);
518 arrayList.add(sslCertificateDateArray);
520 // Return the pinned SSL certificate array list.
524 public void clearPinnedSslCertificate() {
525 // Clear the pinned SSL certificate.
526 pinnedSslIssuedToCName = null;
527 pinnedSslIssuedToOName = null;
528 pinnedSslIssuedToUName = null;
529 pinnedSslIssuedByCName = null;
530 pinnedSslIssuedByOName = null;
531 pinnedSslIssuedByUName = null;
532 pinnedSslStartDate = null;
533 pinnedSslEndDate = null;
535 // Clear the pinned SSL certificate tracker.
536 hasPinnedSslCertificate = false;
540 // Current IP addresses.
541 public boolean hasCurrentIpAddresses() {
542 // Return the status of the current IP addresses.
543 return hasCurrentIpAddresses;
546 public void setCurrentIpAddresses(String ipAddresses) {
547 // Store the current IP addresses.
548 currentIpAddresses = ipAddresses;
550 // Set the current IP addresses tracker.
551 hasCurrentIpAddresses = true;
554 public String getCurrentIpAddresses() {
555 // Return the current IP addresses.
556 return currentIpAddresses;
559 public void clearCurrentIpAddresses() {
560 // Clear the current IP addresses.
561 currentIpAddresses = null;
563 // Clear the current IP addresses tracker.
564 hasCurrentIpAddresses = false;
568 // Pinned IP addresses.
569 public boolean hasPinnedIpAddresses() {
570 // Return the status of the pinned IP addresses.
571 return hasPinnedIpAddresses;
574 public void setPinnedIpAddresses(String ipAddresses) {
575 // Store the pinned IP addresses.
576 pinnedIpAddresses = ipAddresses;
578 // Set the pinned IP addresses tracker.
579 hasPinnedIpAddresses = true;
582 public String getPinnedIpAddresses() {
583 // Return the pinned IP addresses.
584 return pinnedIpAddresses;
587 public void clearPinnedIpAddresses() {
588 // Clear the pinned IP addresses.
589 pinnedIpAddresses = null;
591 // Clear the pinned IP addresses tracker.
592 hasPinnedIpAddresses = false;
596 // Ignore pinned information.
597 public void setIgnorePinnedDomainInformation(boolean status) {
598 // Set the status of the ignore pinned domain information tracker.
599 ignorePinnedDomainInformation = status;
602 // The syntax looks better as written, even if it is always inverted.
603 @SuppressWarnings("BooleanMethodIsAlwaysInverted")
604 public boolean ignorePinnedDomainInformation() {
605 // Return the status of the ignore pinned domain information tracker.
606 return ignorePinnedDomainInformation;
610 // Favorite or default icon.
611 public void initializeFavoriteIcon() {
612 // Get the default favorite icon drawable. `ContextCompat` must be used until API >= 21.
613 Drawable favoriteIconDrawable = ContextCompat.getDrawable(getContext(), R.drawable.world);
615 // Cast the favorite icon drawable to a bitmap drawable.
616 BitmapDrawable favoriteIconBitmapDrawable = (BitmapDrawable) favoriteIconDrawable;
618 // Remove the incorrect warning below that the favorite icon bitmap drawable might be null.
619 assert favoriteIconBitmapDrawable != null;
621 // Store the default icon bitmap.
622 favoriteOrDefaultIcon = favoriteIconBitmapDrawable.getBitmap();
625 public void setFavoriteOrDefaultIcon(Bitmap icon) {
626 // Scale the favorite icon bitmap down if it is larger than 256 x 256. Filtering uses bilinear interpolation.
627 if ((icon.getHeight() > 256) || (icon.getWidth() > 256)) {
628 favoriteOrDefaultIcon = Bitmap.createScaledBitmap(icon, 256, 256, true);
630 // Store the icon as presented.
631 favoriteOrDefaultIcon = icon;
635 public Bitmap getFavoriteOrDefaultIcon() {
636 // Return the favorite or default icon.
637 return favoriteOrDefaultIcon;
642 public void setNightMode(boolean status) {
643 // Store the night mode status.
647 public boolean getNightMode() {
648 // Return the night mode status.
654 public void setSwipeToRefresh(boolean status) {
655 // Store the swipe to refresh status.
656 swipeToRefresh = status;
659 public boolean getSwipeToRefresh() {
660 // Return the swipe to refresh status.
661 return swipeToRefresh;
665 // Waiting for proxy.
666 public void setWaitingForProxyUrlString(String urlString) {
667 // Store the waiting for proxy URL string.
668 waitingForProxyUrlString = urlString;
671 public String getWaitingForProxyUrlString() {
672 // Return the waiting for proxy URL string.
673 return waitingForProxyUrlString;
676 public void resetWaitingForProxyUrlString() {
677 // Clear the waiting for proxy URL string.
678 waitingForProxyUrlString = "";
682 public int getHorizontalScrollRange() {
683 // Return the horizontal scroll range.
684 return computeHorizontalScrollRange();
687 public int getVerticalScrollRange() {
688 // Return the vertical scroll range.
689 return computeVerticalScrollRange();
695 public boolean onTouchEvent(MotionEvent motionEvent) {
696 // Initialize a tracker to return if this motion event is handled.
697 boolean motionEventHandled;
699 // Run the commands for the given motion event action.
700 switch (motionEvent.getAction()) {
701 case MotionEvent.ACTION_DOWN:
702 // Start nested scrolling along the vertical axis. `ViewCompat` must be used until the minimum API >= 21.
703 startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
705 // Save the current Y position. Action down will not be called again until a new motion starts.
706 previousYPosition = (int) motionEvent.getY();
708 // Run the default commands.
709 motionEventHandled = super.onTouchEvent(motionEvent);
712 case MotionEvent.ACTION_MOVE:
713 // Get the current Y position.
714 int currentYMotionPosition = (int) motionEvent.getY();
716 // Calculate the pre-scroll delta Y.
717 int preScrollDeltaY = previousYPosition - currentYMotionPosition;
719 // Initialize a variable to track how much of the scroll is consumed.
720 int[] consumedScroll = new int[2];
722 // Initialize a variable to track the offset in the window.
723 int[] offsetInWindow = new int[2];
725 // Get the WebView Y position.
726 int webViewYPosition = getScrollY();
728 // Set the scroll delta Y to initially be the same as the pre-scroll delta Y.
729 int scrollDeltaY = preScrollDeltaY;
731 // Dispatch the nested pre-school. This scrolls the app bar if it needs it. `offsetInWindow` will be returned with an updated value.
732 if (dispatchNestedPreScroll(0, preScrollDeltaY, consumedScroll, offsetInWindow)) {
733 // Update the scroll delta Y if some of it was consumed.
734 // 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.
735 scrollDeltaY = preScrollDeltaY - consumedScroll[1];
738 // Check to see if the WebView is at the top and and the scroll action is downward.
739 if ((webViewYPosition == 0) && (scrollDeltaY < 0)) { // Swipe to refresh is being engaged.
740 // 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.
742 } else { // Swipe to refresh is not being engaged.
743 // Start the nested scroll so that the app bar can scroll off the screen.
744 startNestedScroll(ViewCompat.SCROLL_AXIS_VERTICAL);
746 // 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.
747 dispatchNestedScroll(0, scrollDeltaY, 0, 0, offsetInWindow);
749 // Store the current Y position for use in the next action move.
750 previousYPosition = previousYPosition - scrollDeltaY;
753 // Run the default commands.
754 motionEventHandled = super.onTouchEvent(motionEvent);
759 // Stop nested scrolling.
762 // Run the default commands.
763 motionEventHandled = super.onTouchEvent(motionEvent);
766 // Perform a click. This is required by the Android accessibility guidelines.
769 // Return the status of the motion event.
770 return motionEventHandled;
773 // The Android accessibility guidelines require overriding `performClick()` and calling it from `onTouchEvent()`.
775 public boolean performClick() {
776 return super.performClick();
780 // Method from NestedScrollingChild.
782 public void setNestedScrollingEnabled(boolean status) {
783 // Set the status of the nested scrolling.
784 nestedScrollingChildHelper.setNestedScrollingEnabled(status);
787 // Method from NestedScrollingChild.
789 public boolean isNestedScrollingEnabled() {
790 // Return the status of nested scrolling.
791 return nestedScrollingChildHelper.isNestedScrollingEnabled();
795 // Method from NestedScrollingChild.
797 public boolean startNestedScroll(int axes) {
798 // Start a nested scroll along the indicated axes.
799 return nestedScrollingChildHelper.startNestedScroll(axes);
802 // Method from NestedScrollingChild2.
804 public boolean startNestedScroll(int axes, int type) {
805 // Start a nested scroll along the indicated axes for the given type of input which caused the scroll event.
806 return nestedScrollingChildHelper.startNestedScroll(axes, type);
810 // Method from NestedScrollingChild.
812 public void stopNestedScroll() {
813 // Stop the nested scroll.
814 nestedScrollingChildHelper.stopNestedScroll();
817 // Method from NestedScrollingChild2.
819 public void stopNestedScroll(int type) {
820 // Stop the nested scroll of the given type of input which caused the scroll event.
821 nestedScrollingChildHelper.stopNestedScroll(type);
825 // Method from NestedScrollingChild.
827 public boolean hasNestedScrollingParent() {
828 // Return the status of the nested scrolling parent.
829 return nestedScrollingChildHelper.hasNestedScrollingParent();
832 // Method from NestedScrollingChild2.
834 public boolean hasNestedScrollingParent(int type) {
835 // return the status of the nested scrolling parent for the given type of input which caused the scroll event.
836 return nestedScrollingChildHelper.hasNestedScrollingParent(type);
840 // Method from NestedScrollingChild.
842 public boolean dispatchNestedPreScroll(int deltaX, int deltaY, int[] consumed, int[] offsetInWindow) {
843 // Dispatch a nested pre-scroll with the specified deltas, which lets a parent to consume some of the scroll if desired.
844 return nestedScrollingChildHelper.dispatchNestedPreScroll(deltaX, deltaY, consumed, offsetInWindow);
847 // Method from NestedScrollingChild2.
849 public boolean dispatchNestedPreScroll(int deltaX, int deltaY, int[] consumed, int[] offsetInWindow, int type) {
850 // 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.
851 return nestedScrollingChildHelper.dispatchNestedPreScroll(deltaX, deltaY, consumed, offsetInWindow, type);
855 // Method from NestedScrollingChild.
857 public boolean dispatchNestedScroll(int deltaXConsumed, int deltaYConsumed, int deltaXUnconsumed, int deltaYUnconsumed, int[] offsetInWindow) {
858 // Dispatch a nested scroll with the specified deltas.
859 return nestedScrollingChildHelper.dispatchNestedScroll(deltaXConsumed, deltaYConsumed, deltaXUnconsumed, deltaYUnconsumed, offsetInWindow);
862 // Method from NestedScrollingChild2.
864 public boolean dispatchNestedScroll(int deltaXConsumed, int deltaYConsumed, int deltaXUnconsumed, int deltaYUnconsumed, int[] offsetInWindow, int type) {
865 // Dispatch a nested scroll with the specified deltas for the given type of input which caused the scroll event.
866 return nestedScrollingChildHelper.dispatchNestedScroll(deltaXConsumed, deltaYConsumed, deltaXUnconsumed, deltaYUnconsumed, offsetInWindow, type);
870 // Method from NestedScrollingChild.
872 public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
873 // Dispatch a nested pre-fling with the specified velocity, which lets a parent consume the fling if desired.
874 return nestedScrollingChildHelper.dispatchNestedPreFling(velocityX, velocityY);
877 // Method from NestedScrollingChild.
879 public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
880 // Dispatch a nested fling with the specified velocity.
881 return nestedScrollingChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);