/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.messaging.ui; import android.os.Bundle; import android.os.Parcelable; import androidx.viewpager.widget.PagerAdapter; import android.view.View; import android.view.ViewGroup; import com.android.messaging.Factory; import com.android.messaging.util.Assert; import com.android.messaging.util.UiUtils; import com.google.common.annotations.VisibleForTesting; /** * A PagerAdapter that provides a fixed number of paged Views provided by a fixed set of * {@link PagerViewHolder}'s. This allows us to put a fixed number of Views, instead of fragments, * into a given ViewPager. */ public class FixedViewPagerAdapter extends PagerAdapter { private final T[] mViewHolders; public FixedViewPagerAdapter(final T[] viewHolders) { Assert.notNull(viewHolders); mViewHolders = viewHolders; } @Override public Object instantiateItem(final ViewGroup container, final int position) { final PagerViewHolder viewHolder = getViewHolder(position); final View view = viewHolder.getView(container); if (view == null) { return null; } view.setTag(viewHolder); container.addView(view); return viewHolder; } @Override public void destroyItem(final ViewGroup container, final int position, final Object object) { final PagerViewHolder viewHolder = getViewHolder(position); final View destroyedView = viewHolder.destroyView(); if (destroyedView != null) { container.removeView(destroyedView); } } @Override public int getCount() { return mViewHolders.length; } @Override public boolean isViewFromObject(final View view, final Object object) { return view.getTag() == object; } public T getViewHolder(final int i) { return getViewHolder(i, true /* rtlAware */); } @VisibleForTesting public T getViewHolder(final int i, final boolean rtlAware) { return mViewHolders[rtlAware ? getRtlPosition(i) : i]; } @Override public Parcelable saveState() { // The paged views in the view pager gets created and destroyed as the user scrolls through // them. By default, only the pages to the immediate left and right of the current visible // page are realized. Moreover, if the activity gets destroyed and recreated, the pages are // automatically destroyed. Therefore, in order to preserve transient page UI states that // are not persisted in the DB we'd like to store them in a Bundle when views get // destroyed. When the views get recreated, we rehydrate them by passing them the saved // data. When the activity gets destroyed, it invokes saveState() on this adapter to // add this saved Bundle to the overall saved instance state. final Bundle savedViewHolderState = new Bundle(Factory.get().getApplicationContext() .getClassLoader()); for (int i = 0; i < mViewHolders.length; i++) { final Parcelable pageState = getViewHolder(i).saveState(); savedViewHolderState.putParcelable(getInstanceStateKeyForPage(i), pageState); } return savedViewHolderState; } @Override public void restoreState(final Parcelable state, final ClassLoader loader) { if (state instanceof Bundle) { final Bundle restoredViewHolderState = (Bundle) state; ((Bundle) state).setClassLoader(Factory.get().getApplicationContext().getClassLoader()); for (int i = 0; i < mViewHolders.length; i++) { final Parcelable pageState = restoredViewHolderState .getParcelable(getInstanceStateKeyForPage(i)); getViewHolder(i).restoreState(pageState); } } else { super.restoreState(state, loader); } } public void resetState() { for (int i = 0; i < mViewHolders.length; i++) { getViewHolder(i).resetState(); } } private String getInstanceStateKeyForPage(final int i) { return getViewHolder(i).getClass().getCanonicalName() + "_savedstate_" + i; } protected int getRtlPosition(final int position) { if (UiUtils.isRtlMode()) { return mViewHolders.length - 1 - position; } return position; } }