blob: bb68055d7cb8b7b43436c7824e8b3ad35608463f [file] [log] [blame]
Noah Wang49fabb92016-01-12 09:00:57 -08001/*
2 * Copyright (C) 2016 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 */
16package com.android.settings;
17
Noah Wang6e7d4102016-04-10 03:57:24 -070018import android.animation.Animator;
19import android.animation.Animator.AnimatorListener;
Noah Wang49fabb92016-01-12 09:00:57 -080020import android.content.Context;
21import android.content.res.Configuration;
22import android.support.v4.view.PagerAdapter;
23import android.view.LayoutInflater;
24import android.view.View;
25import android.view.ViewGroup;
Noah Wang5666ddf2016-08-23 14:56:27 -070026import android.view.ViewStub;
27import android.view.ViewStub.OnInflateListener;
Noah Wang49fabb92016-01-12 09:00:57 -080028import android.view.animation.AccelerateInterpolator;
29import android.view.animation.DecelerateInterpolator;
30import android.view.animation.Interpolator;
31import android.widget.FrameLayout;
Noah Wangabf63122016-02-23 17:26:13 -080032import android.widget.LinearLayout;
33import android.widget.ScrollView;
Noah Wang49fabb92016-01-12 09:00:57 -080034
35/**
36 * A PagerAdapter used by PreviewSeekBarPreferenceFragment that for showing multiple preview screen
37 * regarding a single setting and allowing the user to swipe across them.
38 */
39public class PreviewPagerAdapter extends PagerAdapter {
40
Noah Wang49fabb92016-01-12 09:00:57 -080041 /** Duration to use when cross-fading between previews. */
42 private static final long CROSS_FADE_DURATION_MS = 400;
43
44 /** Interpolator to use when cross-fading between previews. */
45 private static final Interpolator FADE_IN_INTERPOLATOR = new DecelerateInterpolator();
46
47 /** Interpolator to use when cross-fading between previews. */
48 private static final Interpolator FADE_OUT_INTERPOLATOR = new AccelerateInterpolator();
49
Noah Wang37c95e42016-04-09 20:53:14 -070050 private FrameLayout[] mPreviewFrames;
51
52 private boolean mIsLayoutRtl;
Noah Wang6e7d4102016-04-10 03:57:24 -070053
54 private Runnable mAnimationEndAction;
55
56 private int mAnimationCounter;
57
Noah Wang5666ddf2016-08-23 14:56:27 -070058 private boolean[][] mViewStubInflated;
59
Noah Wang37c95e42016-04-09 20:53:14 -070060 public PreviewPagerAdapter(Context context, boolean isLayoutRtl,
61 int[] previewSampleResIds, Configuration[] configurations) {
62 mIsLayoutRtl = isLayoutRtl;
Noah Wangabf63122016-02-23 17:26:13 -080063 mPreviewFrames = new FrameLayout[previewSampleResIds.length];
Noah Wang5666ddf2016-08-23 14:56:27 -070064 mViewStubInflated = new boolean[previewSampleResIds.length][configurations.length];
Noah Wang49fabb92016-01-12 09:00:57 -080065
66 for (int i = 0; i < previewSampleResIds.length; ++i) {
Noah Wang37c95e42016-04-09 20:53:14 -070067 int p = mIsLayoutRtl ? previewSampleResIds.length - 1 - i : i;
68 mPreviewFrames[p] = new FrameLayout(context);
69 mPreviewFrames[p].setLayoutParams(new LinearLayout.LayoutParams(
Noah Wangabf63122016-02-23 17:26:13 -080070 LinearLayout.LayoutParams.MATCH_PARENT,
71 LinearLayout.LayoutParams.MATCH_PARENT));
Noah Wang49fabb92016-01-12 09:00:57 -080072
Noah Wang5666ddf2016-08-23 14:56:27 -070073 for (int j = 0; j < configurations.length; ++j) {
Noah Wang49fabb92016-01-12 09:00:57 -080074 // Create a new configuration for the specified value. It won't
75 // have any theme set, so manually apply the current theme.
Noah Wang5666ddf2016-08-23 14:56:27 -070076 final Context configContext = context.createConfigurationContext(configurations[j]);
Anas Karbilaada2ea52017-04-20 21:44:13 +090077 configContext.getTheme().setTo(context.getTheme());
Noah Wang49fabb92016-01-12 09:00:57 -080078
79 final LayoutInflater configInflater = LayoutInflater.from(configContext);
Noah Wang5666ddf2016-08-23 14:56:27 -070080 final ViewStub sampleViewStub = new ViewStub(configContext);
81 sampleViewStub.setLayoutResource(previewSampleResIds[i]);
82 final int fi = i, fj = j;
83 sampleViewStub.setOnInflateListener(new OnInflateListener() {
84 @Override
85 public void onInflate(ViewStub stub, View inflated) {
86 inflated.setVisibility(stub.getVisibility());
87 mViewStubInflated[fi][fj] = true;
88 }
89 });
90
91 mPreviewFrames[p].addView(sampleViewStub);
Noah Wang49fabb92016-01-12 09:00:57 -080092 }
93 }
Noah Wang49fabb92016-01-12 09:00:57 -080094 }
95
96 @Override
97 public void destroyItem (ViewGroup container, int position, Object object) {
98 container.removeView((View) object);
99 }
100
101 @Override
102 public int getCount() {
103 return mPreviewFrames.length;
104 }
105
106 @Override
107 public Object instantiateItem(ViewGroup container, int position) {
108 container.addView(mPreviewFrames[position]);
109 return mPreviewFrames[position];
110 }
111
112 @Override
113 public boolean isViewFromObject(View view, Object object) {
114 return (view == object);
115 }
116
Noah Wang6e7d4102016-04-10 03:57:24 -0700117 boolean isAnimating() {
118 return mAnimationCounter > 0;
119 }
120
121 void setAnimationEndAction(Runnable action) {
122 mAnimationEndAction = action;
123 }
124
Noah Wang5666ddf2016-08-23 14:56:27 -0700125 void setPreviewLayer(int newLayerIndex, int currentLayerIndex, int currentFrameIndex,
126 final boolean animate) {
Noah Wang49fabb92016-01-12 09:00:57 -0800127 for (FrameLayout previewFrame : mPreviewFrames) {
Noah Wang5666ddf2016-08-23 14:56:27 -0700128 if (currentLayerIndex >= 0) {
129 final View lastLayer = previewFrame.getChildAt(currentLayerIndex);
130 if (mViewStubInflated[currentFrameIndex][currentLayerIndex]) {
131 // Explicitly set to INVISIBLE only when the stub has
132 // already been inflated.
133 if (previewFrame == mPreviewFrames[currentFrameIndex]) {
134 setVisibility(lastLayer, View.INVISIBLE, animate);
135 } else {
136 setVisibility(lastLayer, View.INVISIBLE, false);
137 }
Noah Wang49fabb92016-01-12 09:00:57 -0800138 }
139 }
140
Noah Wang5666ddf2016-08-23 14:56:27 -0700141 // Set next layer visible, as well as inflate necessary views.
142 View nextLayer = previewFrame.getChildAt(newLayerIndex);
143 if (previewFrame == mPreviewFrames[currentFrameIndex]) {
144 // Inflate immediately if the stub has not yet been inflated.
145 if (!mViewStubInflated[currentFrameIndex][newLayerIndex]) {
146 nextLayer = ((ViewStub) nextLayer).inflate();
147 nextLayer.setAlpha(0.0f);
148 }
149 setVisibility(nextLayer, View.VISIBLE, animate);
Noah Wang49fabb92016-01-12 09:00:57 -0800150 } else {
Noah Wang5666ddf2016-08-23 14:56:27 -0700151 setVisibility(nextLayer, View.VISIBLE, false);
152 }
153 }
154 }
155
156 private void setVisibility(final View view, final int visibility, boolean animate) {
157 final float alpha = (visibility == View.VISIBLE ? 1.0f : 0.0f);
158 if (!animate) {
159 view.setAlpha(alpha);
160 view.setVisibility(visibility);
161 } else {
162 final Interpolator interpolator = (visibility == View.VISIBLE ? FADE_IN_INTERPOLATOR
163 : FADE_OUT_INTERPOLATOR);
164 if (visibility == View.VISIBLE) {
165 // Fade in animation.
166 view.animate()
167 .alpha(alpha)
168 .setInterpolator(FADE_IN_INTERPOLATOR)
169 .setDuration(CROSS_FADE_DURATION_MS)
170 .setListener(new PreviewFrameAnimatorListener())
171 .withStartAction(new Runnable() {
172 @Override
173 public void run() {
174 view.setVisibility(visibility);
175 }
176 });
177 } else {
178 // Fade out animation.
179 view.animate()
180 .alpha(alpha)
181 .setInterpolator(FADE_OUT_INTERPOLATOR)
182 .setDuration(CROSS_FADE_DURATION_MS)
183 .setListener(new PreviewFrameAnimatorListener())
184 .withEndAction(new Runnable() {
185 @Override
186 public void run() {
187 view.setVisibility(visibility);
188 }
189 });
Noah Wang49fabb92016-01-12 09:00:57 -0800190 }
191 }
192 }
Noah Wang6e7d4102016-04-10 03:57:24 -0700193
194 private void runAnimationEndAction() {
195 if (mAnimationEndAction != null && !isAnimating()) {
196 mAnimationEndAction.run();
197 mAnimationEndAction = null;
198 }
199 }
200
201 private class PreviewFrameAnimatorListener implements AnimatorListener {
202 @Override
203 public void onAnimationStart(Animator animation) {
204 mAnimationCounter++;
205 }
206
207 @Override
208 public void onAnimationEnd(Animator animation) {
209 mAnimationCounter--;
210 runAnimationEndAction();
211 }
212
213 @Override
214 public void onAnimationCancel(Animator animation) {
215 // Empty method.
216 }
217
218 @Override
219 public void onAnimationRepeat(Animator animation) {
220 // Empty method.
221 }
222 }
Noah Wang49fabb92016-01-12 09:00:57 -0800223}