Home | History | Annotate | Download | only in ui
      1 /*
      2  * Copyright (C) 2015 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 package com.android.messaging.ui;
     17 
     18 import android.os.Bundle;
     19 import android.os.Parcelable;
     20 import android.support.v4.view.PagerAdapter;
     21 import android.view.View;
     22 import android.view.ViewGroup;
     23 
     24 import com.android.messaging.Factory;
     25 import com.android.messaging.util.Assert;
     26 import com.android.messaging.util.UiUtils;
     27 import com.google.common.annotations.VisibleForTesting;
     28 
     29 /**
     30  * A PagerAdapter that provides a fixed number of paged Views provided by a fixed set of
     31  * {@link PagerViewHolder}'s. This allows us to put a fixed number of Views, instead of fragments,
     32  * into a given ViewPager.
     33  */
     34 public class FixedViewPagerAdapter<T extends PagerViewHolder> extends PagerAdapter {
     35     private final T[] mViewHolders;
     36 
     37     public FixedViewPagerAdapter(final T[] viewHolders) {
     38         Assert.notNull(viewHolders);
     39         mViewHolders = viewHolders;
     40     }
     41 
     42     @Override
     43     public Object instantiateItem(final ViewGroup container, final int position) {
     44         final PagerViewHolder viewHolder = getViewHolder(position);
     45         final View view = viewHolder.getView(container);
     46         if (view == null) {
     47             return null;
     48         }
     49         view.setTag(viewHolder);
     50         container.addView(view);
     51         return viewHolder;
     52     }
     53 
     54     @Override
     55     public void destroyItem(final ViewGroup container, final int position, final Object object) {
     56         final PagerViewHolder viewHolder = getViewHolder(position);
     57         final View destroyedView = viewHolder.destroyView();
     58         if (destroyedView != null) {
     59             container.removeView(destroyedView);
     60         }
     61     }
     62 
     63     @Override
     64     public int getCount() {
     65         return mViewHolders.length;
     66     }
     67 
     68     @Override
     69     public boolean isViewFromObject(final View view, final Object object) {
     70         return view.getTag() == object;
     71     }
     72 
     73     public T getViewHolder(final int i) {
     74         return getViewHolder(i, true /* rtlAware */);
     75     }
     76 
     77     @VisibleForTesting
     78     public T getViewHolder(final int i, final boolean rtlAware) {
     79         return mViewHolders[rtlAware ? getRtlPosition(i) : i];
     80     }
     81 
     82     @Override
     83     public Parcelable saveState() {
     84         // The paged views in the view pager gets created and destroyed as the user scrolls through
     85         // them. By default, only the pages to the immediate left and right of the current visible
     86         // page are realized. Moreover, if the activity gets destroyed and recreated, the pages are
     87         // automatically destroyed. Therefore, in order to preserve transient page UI states that
     88         // are not persisted in the DB we'd like to store them in a Bundle when views get
     89         // destroyed. When the views get recreated, we rehydrate them by passing them the saved
     90         // data. When the activity gets destroyed, it invokes saveState() on this adapter to
     91         // add this saved Bundle to the overall saved instance state.
     92         final Bundle savedViewHolderState = new Bundle(Factory.get().getApplicationContext()
     93                 .getClassLoader());
     94         for (int i = 0; i < mViewHolders.length; i++) {
     95             final Parcelable pageState = getViewHolder(i).saveState();
     96             savedViewHolderState.putParcelable(getInstanceStateKeyForPage(i), pageState);
     97         }
     98         return savedViewHolderState;
     99     }
    100 
    101     @Override
    102     public void restoreState(final Parcelable state, final ClassLoader loader) {
    103         if (state instanceof Bundle) {
    104             final Bundle restoredViewHolderState = (Bundle) state;
    105             ((Bundle) state).setClassLoader(Factory.get().getApplicationContext().getClassLoader());
    106             for (int i = 0; i < mViewHolders.length; i++) {
    107                 final Parcelable pageState = restoredViewHolderState
    108                         .getParcelable(getInstanceStateKeyForPage(i));
    109                 getViewHolder(i).restoreState(pageState);
    110             }
    111         } else {
    112             super.restoreState(state, loader);
    113         }
    114     }
    115 
    116     public void resetState() {
    117         for (int i = 0; i < mViewHolders.length; i++) {
    118             getViewHolder(i).resetState();
    119         }
    120     }
    121 
    122     private String getInstanceStateKeyForPage(final int i) {
    123         return getViewHolder(i).getClass().getCanonicalName() + "_savedstate_" + i;
    124     }
    125 
    126     protected int getRtlPosition(final int position) {
    127         if (UiUtils.isRtlMode()) {
    128             return mViewHolders.length - 1 - position;
    129         }
    130         return position;
    131     }
    132 }
    133