1 // Copyright 2019 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.feed.shared.stream; 6 7 import android.view.View; 8 9 import androidx.annotation.IntDef; 10 import androidx.annotation.Nullable; 11 12 import java.lang.annotation.Retention; 13 import java.lang.annotation.RetentionPolicy; 14 import java.util.List; 15 16 /** Interface used for interacting with the Stream library in order to render a stream of cards. */ 17 public interface Stream { 18 /** Constant used to notify host that a view's position on screen is not known. */ 19 int POSITION_NOT_KNOWN = Integer.MIN_VALUE; 20 21 @IntDef({FeedFirstCardDensity.UNKNOWN, FeedFirstCardDensity.NOT_DENSE, 22 FeedFirstCardDensity.DENSE}) 23 @Retention(RetentionPolicy.SOURCE) 24 @interface FeedFirstCardDensity { 25 int UNKNOWN = 0; 26 int NOT_DENSE = 1; 27 int DENSE = 2; 28 } 29 30 /** 31 * Called when the Stream is being created. {@code savedInstanceState} should be a previous 32 * string returned from {@link #getSavedInstanceStateString()}. 33 * 34 * @param savedInstanceState state to restore to. 35 * @throws IllegalStateException if method is called multiple times. 36 */ onCreate(@ullable String savedInstanceState)37 void onCreate(@Nullable String savedInstanceState); 38 39 /** 40 * Called when the Stream is visible on the screen, may be partially obscured or about to be 41 * displayed. This maps similarly to {@link android.app.Activity#onStart()}. 42 * 43 * <p>This will cause the Stream to start pre-warming feed services. 44 */ onShow()45 void onShow(); 46 47 /** 48 * Called when the Stream is no longer visible on screen. This should act similarly to {@link 49 * android.app.Activity#onStop()}. 50 */ onHide()51 void onHide(); 52 53 /** 54 * Called when the Stream is destroyed. This should act similarly to {@link 55 * android.app.Activity#onDestroy()}. 56 */ onDestroy()57 void onDestroy(); 58 59 /** 60 * The returned string should be passed to {@link #onCreate(String)} when the activity is 61 * recreated and the stream needs to be recreated. 62 */ getSavedInstanceStateString()63 String getSavedInstanceStateString(); 64 65 /** 66 * Return the root view which holds all card stream views. The Feed library builds Views when 67 * this method is called (caches as needed). This must be called after {@link 68 * #onCreate()}. Multiple calls to this method will return the same View. 69 * 70 * @throws IllegalStateException when called before {@link #onCreate()}. 71 */ getView()72 View getView(); 73 74 /** 75 * Set headers on the stream. Headers will be added to the top of the stream in the order they 76 * are in the list. The headers are not sticky and will scroll with content. Headers can be 77 * cleared by passing in an empty list. 78 */ setHeaderViews(List<Header> headers)79 void setHeaderViews(List<Header> headers); 80 81 /** 82 * Sets whether or not the Stream should show Feed content. Header views will still be shown if 83 * set. 84 */ setStreamContentVisibility(boolean visible)85 void setStreamContentVisibility(boolean visible); 86 87 /** 88 * Notifies the Stream to purge unnecessary memory. This just purges recycling pools for now. 89 * Can expand out as needed. 90 */ trim()91 void trim(); 92 93 /** 94 * Called by the host to scroll the Stream by a certain amount. If the Stream is unable to 95 * scroll the desired amount, it will scroll as much as possible. 96 * 97 * @param dx amount in pixels for Stream to scroll horizontally 98 * @param dy amount in pixels for Stream to scroll vertically 99 */ smoothScrollBy(int dx, int dy)100 void smoothScrollBy(int dx, int dy); 101 102 /** 103 * Returns the top position in pixels of the View at the {@code position} in the vertical 104 * hierarchy. This should act similarly to {@code RecyclerView.getChildAt(position).getTop()}. 105 * 106 * <p>Returns {@link #POSITION_NOT_KNOWN} if position is not known. This could be returned if 107 * {@code position} it not a valid position or the actual child has not been placed on screen 108 * and rendered. 109 */ getChildTopAt(int position)110 int getChildTopAt(int position); 111 112 /** 113 * Returns true if the child at the position is visible on screen. The view could be partially 114 * visible and this would still return true. 115 */ isChildAtPositionVisible(int position)116 boolean isChildAtPositionVisible(int position); 117 addScrollListener(ScrollListener listener)118 void addScrollListener(ScrollListener listener); 119 removeScrollListener(ScrollListener listener)120 void removeScrollListener(ScrollListener listener); 121 addOnContentChangedListener(ContentChangedListener listener)122 void addOnContentChangedListener(ContentChangedListener listener); 123 removeOnContentChangedListener(ContentChangedListener listener)124 void removeOnContentChangedListener(ContentChangedListener listener); 125 126 /** 127 * Allow the container to trigger a refresh of the stream. 128 * 129 * <p>Note: this will assume {@link RequestReason.HOST_REQUESTED}. 130 */ triggerRefresh()131 void triggerRefresh(); 132 133 /** 134 * @return Whether the placeholder is shown. 135 */ isPlaceholderShown()136 boolean isPlaceholderShown(); 137 138 /** 139 * Called when the placeholder is shown and the first batch of articles are about to show. 140 */ hidePlaceholder()141 void hidePlaceholder(); 142 143 /** 144 * Get whether the first card of Feed is dense in portrait mode. 145 */ getFirstCardDensity()146 default int getFirstCardDensity() { 147 return FeedFirstCardDensity.UNKNOWN; 148 }; 149 150 /** 151 * Interface users can implement to know when content in the Stream has changed content on 152 * screen. 153 */ 154 interface ContentChangedListener { 155 /** 156 * Called by Stream when content being shown has changed. This could be new cards being 157 * created, the content of a card changing, etc... 158 */ onContentChanged()159 void onContentChanged(); 160 161 /** 162 * Called by Stream when an 163 * {@link androidx.recyclerview.widget.SimpleItemAnimator#onAddFinished} event is received. 164 */ onAddFinished()165 default void onAddFinished(){}; 166 167 /** 168 * Called by Stream when an 169 * {@link androidx.recyclerview.widget.SimpleItemAnimator#onAddStarting} event is received. 170 */ onAddStarting()171 default void onAddStarting(){}; 172 } 173 174 /** Interface users can implement to be told about changes to scrolling in the Stream. */ 175 interface ScrollListener { 176 /** 177 * Constant used to denote that a scroll was performed but scroll delta could not be 178 * calculated. This normally maps to a programmatic scroll. 179 */ 180 int UNKNOWN_SCROLL_DELTA = Integer.MIN_VALUE; 181 onScrollStateChanged(@crollState int state)182 void onScrollStateChanged(@ScrollState int state); 183 184 /** 185 * Called when a scroll happens and provides the amount of pixels scrolled. {@link 186 * #UNKNOWN_SCROLL_DELTA} will be specified if scroll delta would not be determined. An 187 * example of this would be a scroll initiated programmatically. 188 */ onScrolled(int dx, int dy)189 void onScrolled(int dx, int dy); 190 191 /** 192 * Possible scroll states. 193 * 194 * <p>When adding new values, the value of {@link ScrollState#NEXT_VALUE} should be used and 195 * incremented. When removing values, {@link ScrollState#NEXT_VALUE} should not be changed, 196 * and those values should not be reused. 197 */ 198 @IntDef({ScrollState.IDLE, ScrollState.DRAGGING, ScrollState.SETTLING, 199 ScrollState.NEXT_VALUE}) 200 @interface ScrollState { 201 /** Stream is not scrolling */ 202 int IDLE = 0; 203 204 /** Stream is currently scrolling through external means such as user input. */ 205 int DRAGGING = 1; 206 207 /** Stream is animating to a final position. */ 208 int SETTLING = 2; 209 210 /** The next value that should be used when adding additional values to the IntDef. */ 211 int NEXT_VALUE = 3; 212 } 213 } 214 } 215