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