• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.viewpager.widget;
18 
19 import android.database.DataSetObservable;
20 import android.database.DataSetObserver;
21 import android.os.Parcelable;
22 import android.view.View;
23 import android.view.ViewGroup;
24 
25 import androidx.annotation.NonNull;
26 import androidx.annotation.Nullable;
27 
28 /**
29  * Base class providing the adapter to populate pages inside of
30  * a {@link ViewPager}.  You will most likely want to use a more
31  * specific implementation of this, such as
32  * {@link androidx.fragment.app.FragmentPagerAdapter} or
33  * {@link androidx.fragment.app.FragmentStatePagerAdapter}.
34  *
35  * <p>When you implement a PagerAdapter, you must override the following methods
36  * at minimum:</p>
37  * <ul>
38  * <li>{@link #instantiateItem(ViewGroup, int)}</li>
39  * <li>{@link #destroyItem(ViewGroup, int, Object)}</li>
40  * <li>{@link #getCount()}</li>
41  * <li>{@link #isViewFromObject(View, Object)}</li>
42  * </ul>
43  *
44  * <p>PagerAdapter is more general than the adapters used for
45  * {@link android.widget.AdapterView AdapterViews}. Instead of providing a
46  * View recycling mechanism directly ViewPager uses callbacks to indicate the
47  * steps taken during an update. A PagerAdapter may implement a form of View
48  * recycling if desired or use a more sophisticated method of managing page
49  * Views such as Fragment transactions where each page is represented by its
50  * own Fragment.</p>
51  *
52  * <p>ViewPager associates each page with a key Object instead of working with
53  * Views directly. This key is used to track and uniquely identify a given page
54  * independent of its position in the adapter. A call to the PagerAdapter method
55  * {@link #startUpdate(ViewGroup)} indicates that the contents of the ViewPager
56  * are about to change. One or more calls to {@link #instantiateItem(ViewGroup, int)}
57  * and/or {@link #destroyItem(ViewGroup, int, Object)} will follow, and the end
58  * of an update will be signaled by a call to {@link #finishUpdate(ViewGroup)}.
59  * By the time {@link #finishUpdate(ViewGroup) finishUpdate} returns the views
60  * associated with the key objects returned by
61  * {@link #instantiateItem(ViewGroup, int) instantiateItem} should be added to
62  * the parent ViewGroup passed to these methods and the views associated with
63  * the keys passed to {@link #destroyItem(ViewGroup, int, Object) destroyItem}
64  * should be removed. The method {@link #isViewFromObject(View, Object)} identifies
65  * whether a page View is associated with a given key object.</p>
66  *
67  * <p>A very simple PagerAdapter may choose to use the page Views themselves
68  * as key objects, returning them from {@link #instantiateItem(ViewGroup, int)}
69  * after creation and adding them to the parent ViewGroup. A matching
70  * {@link #destroyItem(ViewGroup, int, Object)} implementation would remove the
71  * View from the parent ViewGroup and {@link #isViewFromObject(View, Object)}
72  * could be implemented as <code>return view == object;</code>.</p>
73  *
74  * <p>PagerAdapter supports data set changes. Data set changes must occur on the
75  * main thread and must end with a call to {@link #notifyDataSetChanged()} similar
76  * to AdapterView adapters derived from {@link android.widget.BaseAdapter}. A data
77  * set change may involve pages being added, removed, or changing position. The
78  * ViewPager will keep the current page active provided the adapter implements
79  * the method {@link #getItemPosition(Object)}.</p>
80  */
81 public abstract class PagerAdapter {
82     private final DataSetObservable mObservable = new DataSetObservable();
83     private DataSetObserver mViewPagerObserver;
84 
85     public static final int POSITION_UNCHANGED = -1;
86     public static final int POSITION_NONE = -2;
87 
88     /**
89      * Return the number of views available.
90      */
getCount()91     public abstract int getCount();
92 
93     /**
94      * Called when a change in the shown pages is going to start being made.
95      * @param container The containing View which is displaying this adapter's
96      * page views.
97      */
startUpdate(@onNull ViewGroup container)98     public void startUpdate(@NonNull ViewGroup container) {
99         startUpdate((View) container);
100     }
101 
102     /**
103      * Create the page for the given position.  The adapter is responsible
104      * for adding the view to the container given here, although it only
105      * must ensure this is done by the time it returns from
106      * {@link #finishUpdate(ViewGroup)}.
107      *
108      * @param container The containing View in which the page will be shown.
109      * @param position The page position to be instantiated.
110      * @return Returns an Object representing the new page.  This does not
111      * need to be a View, but can be some other container of the page.
112      */
113     @NonNull
instantiateItem(@onNull ViewGroup container, int position)114     public Object instantiateItem(@NonNull ViewGroup container, int position) {
115         return instantiateItem((View) container, position);
116     }
117 
118     /**
119      * Remove a page for the given position.  The adapter is responsible
120      * for removing the view from its container, although it only must ensure
121      * this is done by the time it returns from {@link #finishUpdate(ViewGroup)}.
122      *
123      * @param container The containing View from which the page will be removed.
124      * @param position The page position to be removed.
125      * @param object The same object that was returned by
126      * {@link #instantiateItem(View, int)}.
127      */
destroyItem(@onNull ViewGroup container, int position, @NonNull Object object)128     public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
129         destroyItem((View) container, position, object);
130     }
131 
132     /**
133      * Called to inform the adapter of which item is currently considered to
134      * be the "primary", that is the one show to the user as the current page.
135      * This method will not be invoked when the adapter contains no items.
136      *
137      * @param container The containing View from which the page will be removed.
138      * @param position The page position that is now the primary.
139      * @param object The same object that was returned by
140      * {@link #instantiateItem(View, int)}.
141      */
setPrimaryItem(@onNull ViewGroup container, int position, @NonNull Object object)142     public void setPrimaryItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
143         setPrimaryItem((View) container, position, object);
144     }
145 
146     /**
147      * Called when the a change in the shown pages has been completed.  At this
148      * point you must ensure that all of the pages have actually been added or
149      * removed from the container as appropriate.
150      * @param container The containing View which is displaying this adapter's
151      * page views.
152      */
finishUpdate(@onNull ViewGroup container)153     public void finishUpdate(@NonNull ViewGroup container) {
154         finishUpdate((View) container);
155     }
156 
157     /**
158      * Called when a change in the shown pages is going to start being made.
159      * @param container The containing View which is displaying this adapter's
160      * page views.
161      *
162      * @deprecated Use {@link #startUpdate(ViewGroup)}
163      */
164     @Deprecated
startUpdate(@onNull View container)165     public void startUpdate(@NonNull View container) {
166     }
167 
168     /**
169      * Create the page for the given position.  The adapter is responsible
170      * for adding the view to the container given here, although it only
171      * must ensure this is done by the time it returns from
172      * {@link #finishUpdate(ViewGroup)}.
173      *
174      * @param container The containing View in which the page will be shown.
175      * @param position The page position to be instantiated.
176      * @return Returns an Object representing the new page.  This does not
177      * need to be a View, but can be some other container of the page.
178      *
179      * @deprecated Use {@link #instantiateItem(ViewGroup, int)}
180      */
181     @Deprecated
182     @NonNull
instantiateItem(@onNull View container, int position)183     public Object instantiateItem(@NonNull View container, int position) {
184         throw new UnsupportedOperationException(
185                 "Required method instantiateItem was not overridden");
186     }
187 
188     /**
189      * Remove a page for the given position.  The adapter is responsible
190      * for removing the view from its container, although it only must ensure
191      * this is done by the time it returns from {@link #finishUpdate(View)}.
192      *
193      * @param container The containing View from which the page will be removed.
194      * @param position The page position to be removed.
195      * @param object The same object that was returned by
196      * {@link #instantiateItem(View, int)}.
197      *
198      * @deprecated Use {@link #destroyItem(ViewGroup, int, Object)}
199      */
200     @Deprecated
destroyItem(@onNull View container, int position, @NonNull Object object)201     public void destroyItem(@NonNull View container, int position, @NonNull Object object) {
202         throw new UnsupportedOperationException("Required method destroyItem was not overridden");
203     }
204 
205     /**
206      * Called to inform the adapter of which item is currently considered to
207      * be the "primary", that is the one show to the user as the current page.
208      *
209      * @param container The containing View from which the page will be removed.
210      * @param position The page position that is now the primary.
211      * @param object The same object that was returned by
212      * {@link #instantiateItem(View, int)}.
213      *
214      * @deprecated Use {@link #setPrimaryItem(ViewGroup, int, Object)}
215      */
216     @Deprecated
setPrimaryItem(@onNull View container, int position, @NonNull Object object)217     public void setPrimaryItem(@NonNull View container, int position, @NonNull Object object) {
218     }
219 
220     /**
221      * Called when the a change in the shown pages has been completed.  At this
222      * point you must ensure that all of the pages have actually been added or
223      * removed from the container as appropriate.
224      * @param container The containing View which is displaying this adapter's
225      * page views.
226      *
227      * @deprecated Use {@link #finishUpdate(ViewGroup)}
228      */
229     @Deprecated
finishUpdate(@onNull View container)230     public void finishUpdate(@NonNull View container) {
231     }
232 
233     /**
234      * Determines whether a page View is associated with a specific key object
235      * as returned by {@link #instantiateItem(ViewGroup, int)}. This method is
236      * required for a PagerAdapter to function properly.
237      *
238      * @param view Page View to check for association with <code>object</code>
239      * @param object Object to check for association with <code>view</code>
240      * @return true if <code>view</code> is associated with the key object <code>object</code>
241      */
isViewFromObject(@onNull View view, @NonNull Object object)242     public abstract boolean isViewFromObject(@NonNull View view, @NonNull Object object);
243 
244     /**
245      * Save any instance state associated with this adapter and its pages that should be
246      * restored if the current UI state needs to be reconstructed.
247      *
248      * @return Saved state for this adapter
249      */
250     @Nullable
saveState()251     public Parcelable saveState() {
252         return null;
253     }
254 
255     /**
256      * Restore any instance state associated with this adapter and its pages
257      * that was previously saved by {@link #saveState()}.
258      *
259      * @param state State previously saved by a call to {@link #saveState()}
260      * @param loader A ClassLoader that should be used to instantiate any restored objects
261      */
restoreState(@ullable Parcelable state, @Nullable ClassLoader loader)262     public void restoreState(@Nullable Parcelable state, @Nullable ClassLoader loader) {
263     }
264 
265     /**
266      * Called when the host view is attempting to determine if an item's position
267      * has changed. Returns {@link #POSITION_UNCHANGED} if the position of the given
268      * item has not changed or {@link #POSITION_NONE} if the item is no longer present
269      * in the adapter.
270      *
271      * <p>The default implementation assumes that items will never
272      * change position and always returns {@link #POSITION_UNCHANGED}.
273      *
274      * @param object Object representing an item, previously returned by a call to
275      *               {@link #instantiateItem(View, int)}.
276      * @return object's new position index from [0, {@link #getCount()}),
277      *         {@link #POSITION_UNCHANGED} if the object's position has not changed,
278      *         or {@link #POSITION_NONE} if the item is no longer present.
279      */
getItemPosition(@onNull Object object)280     public int getItemPosition(@NonNull Object object) {
281         return POSITION_UNCHANGED;
282     }
283 
284     /**
285      * This method should be called by the application if the data backing this adapter has changed
286      * and associated views should update.
287      */
notifyDataSetChanged()288     public void notifyDataSetChanged() {
289         synchronized (this) {
290             if (mViewPagerObserver != null) {
291                 mViewPagerObserver.onChanged();
292             }
293         }
294         mObservable.notifyChanged();
295     }
296 
297     /**
298      * Register an observer to receive callbacks related to the adapter's data changing.
299      *
300      * @param observer The {@link android.database.DataSetObserver} which will receive callbacks.
301      */
registerDataSetObserver(@onNull DataSetObserver observer)302     public void registerDataSetObserver(@NonNull DataSetObserver observer) {
303         mObservable.registerObserver(observer);
304     }
305 
306     /**
307      * Unregister an observer from callbacks related to the adapter's data changing.
308      *
309      * @param observer The {@link android.database.DataSetObserver} which will be unregistered.
310      */
unregisterDataSetObserver(@onNull DataSetObserver observer)311     public void unregisterDataSetObserver(@NonNull DataSetObserver observer) {
312         mObservable.unregisterObserver(observer);
313     }
314 
setViewPagerObserver(DataSetObserver observer)315     void setViewPagerObserver(DataSetObserver observer) {
316         synchronized (this) {
317             mViewPagerObserver = observer;
318         }
319     }
320 
321     /**
322      * This method may be called by the ViewPager to obtain a title string
323      * to describe the specified page. This method may return null
324      * indicating no title for this page. The default implementation returns
325      * null.
326      *
327      * @param position The position of the title requested
328      * @return A title for the requested page
329      */
330     @Nullable
getPageTitle(int position)331     public CharSequence getPageTitle(int position) {
332         return null;
333     }
334 
335     /**
336      * Returns the proportional width of a given page as a percentage of the
337      * ViewPager's measured width from (0.f-1.f]
338      *
339      * @param position The position of the page requested
340      * @return Proportional width for the given page position
341      */
getPageWidth(int position)342     public float getPageWidth(int position) {
343         return 1.f;
344     }
345 }
346