147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang/* 247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * Copyright (C) 2014 The Android Open Source Project 347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * 447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * Licensed under the Apache License, Version 2.0 (the "License"); 547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * you may not use this file except in compliance with the License. 647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * You may obtain a copy of the License at 747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * 847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * http://www.apache.org/licenses/LICENSE-2.0 947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * 1047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * Unless required by applicable law or agreed to in writing, software 1147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * distributed under the License is distributed on an "AS IS" BASIS, 1247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * See the License for the specific language governing permissions and 1447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * limitations under the License. 1547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang */ 1647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 1747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangpackage com.android.deskclock.timer; 1847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 1947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.app.Fragment; 2047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.app.FragmentManager; 2147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.app.FragmentTransaction; 2247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.support.v13.app.FragmentCompat; 2347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.support.v13.app.FragmentStatePagerAdapter; 2447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.support.v4.util.SparseArrayCompat; 2547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.support.v4.view.PagerAdapter; 2647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.view.View; 2747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangimport android.view.ViewGroup; 2847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 2947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang/** 3047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * Forked from support lib's {@link FragmentStatePagerAdapter}, with some minor 3147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * changes that couldn't be accomplished through subclassing: we need to override the 3247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * onDataSetChanged method using the private member mFragments which cannot be accessed outside. 3347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * 3447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * This class is used for TimerFragment's vertical view pager only. It removed the save/restore 3547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * functionality, because all the fragments needs to be destroyed whenever TimerFragment's 3647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * onPause, in order to bind the newly created timer view with the new pager fragment. 3747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang */ 3847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhangpublic abstract class FragmentStatePagerAdapter2 extends PagerAdapter { 3947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 4047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang private final FragmentManager mFragmentManager; 4147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang private FragmentTransaction mCurTransaction = null; 4247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 4347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang private SparseArrayCompat<Fragment> mFragments = new SparseArrayCompat<Fragment>(); 4447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang private Fragment mCurrentPrimaryItem = null; 4547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 4647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 4747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public FragmentStatePagerAdapter2(FragmentManager fm) { 4847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mFragmentManager = fm; 4947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 5047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 5147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang /** 5247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang * Return the Fragment associated with a specified position. 5347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang */ 5447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public abstract Fragment getItem(int position); 5547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 5647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 5747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public void startUpdate(ViewGroup container) { 5847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 5947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 6047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 6147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public Object instantiateItem(ViewGroup container, int position) { 6247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang // If we already have this item instantiated, there is nothing 6347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang // to do. This can happen when we are restoring the entire pager 6447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang // from its saved state, where the fragment manager has already 6547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang // taken care of restoring the fragments we previously had instantiated. 6647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang final Fragment existing = mFragments.get(position); 6747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (existing != null) { 6847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang return existing; 6947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 7047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 7147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (mCurTransaction == null) { 7247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurTransaction = mFragmentManager.beginTransaction(); 7347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 7447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 7547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang Fragment fragment = getItem(position); 7647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (fragment != mCurrentPrimaryItem) { 7747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang setItemVisible(fragment, false); 7847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 7947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mFragments.put(position, fragment); 8047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurTransaction.add(container.getId(), fragment); 8147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 8247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang return fragment; 8347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 8447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 8547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 8647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public void destroyItem(ViewGroup container, int position, Object object) { 8747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang Fragment fragment = (Fragment) object; 8847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 8947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (mCurTransaction == null) { 9047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurTransaction = mFragmentManager.beginTransaction(); 9147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 9247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mFragments.delete(position); 9347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 9447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurTransaction.remove(fragment); 9547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 9647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 9747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 9847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public void setPrimaryItem(ViewGroup container, int position, Object object) { 9947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang Fragment fragment = (Fragment) object; 10047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (fragment != mCurrentPrimaryItem) { 10147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (mCurrentPrimaryItem != null) { 10247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang setItemVisible(mCurrentPrimaryItem, false); 10347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 10447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (fragment != null) { 10547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang setItemVisible(fragment, true); 10647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 10747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurrentPrimaryItem = fragment; 10847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 10947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 11047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 11147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 11247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public void finishUpdate(ViewGroup container) { 11347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (mCurTransaction != null) { 11447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurTransaction.commitAllowingStateLoss(); 11547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mCurTransaction = null; 11647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mFragmentManager.executePendingTransactions(); 11747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 11847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 11947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 12047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 12147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public boolean isViewFromObject(View view, Object object) { 12247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang return ((Fragment) object).getView() == view; 12347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 12447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 12547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public void setItemVisible(Fragment item, boolean visible) { 12647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang FragmentCompat.setMenuVisibility(item, visible); 12747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang FragmentCompat.setUserVisibleHint(item, visible); 12847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 12947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 13047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang @Override 13147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public void notifyDataSetChanged() { 13247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang // update positions in mFragments 13347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang SparseArrayCompat<Fragment> newFragments = 13447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang new SparseArrayCompat<Fragment>(mFragments.size()); 13547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang for (int i = 0; i < mFragments.size(); i++) { 13647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang final int oldPos = mFragments.keyAt(i); 13747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang final Fragment f = mFragments.valueAt(i); 13847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang final int newPos = getItemPosition(f); 13947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 14047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang if (newPos != POSITION_NONE) { 14147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang final int pos = (newPos >= 0) ? newPos : oldPos; 14247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang newFragments.put(pos, f); 14347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 14447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 14547f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang mFragments = newFragments; 14647f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 14747f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang super.notifyDataSetChanged(); 14847f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 14947f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 15047f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang public Fragment getFragmentAt(int position) { 15147f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang return mFragments.valueAt(position); 15247f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang } 15347f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang 15447f0d4a36f4e4e019fb450bd9a95837c68849f32rachelzhang} 155