1 /* 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 */ 16 package com.android.settings; 17 18 import android.animation.Animator; 19 import android.animation.Animator.AnimatorListener; 20 import android.content.Context; 21 import android.content.res.Configuration; 22 import android.support.v4.view.PagerAdapter; 23 import android.view.LayoutInflater; 24 import android.view.View; 25 import android.view.ViewGroup; 26 import android.view.animation.AccelerateInterpolator; 27 import android.view.animation.DecelerateInterpolator; 28 import android.view.animation.Interpolator; 29 import android.widget.FrameLayout; 30 import android.widget.LinearLayout; 31 import android.widget.ScrollView; 32 33 /** 34 * A PagerAdapter used by PreviewSeekBarPreferenceFragment that for showing multiple preview screen 35 * regarding a single setting and allowing the user to swipe across them. 36 */ 37 public class PreviewPagerAdapter extends PagerAdapter { 38 39 /** Duration to use when cross-fading between previews. */ 40 private static final long CROSS_FADE_DURATION_MS = 400; 41 42 /** Interpolator to use when cross-fading between previews. */ 43 private static final Interpolator FADE_IN_INTERPOLATOR = new DecelerateInterpolator(); 44 45 /** Interpolator to use when cross-fading between previews. */ 46 private static final Interpolator FADE_OUT_INTERPOLATOR = new AccelerateInterpolator(); 47 48 private FrameLayout[] mPreviewFrames; 49 50 private boolean mIsLayoutRtl; 51 52 private Runnable mAnimationEndAction; 53 54 private int mAnimationCounter; 55 PreviewPagerAdapter(Context context, boolean isLayoutRtl, int[] previewSampleResIds, Configuration[] configurations)56 public PreviewPagerAdapter(Context context, boolean isLayoutRtl, 57 int[] previewSampleResIds, Configuration[] configurations) { 58 mIsLayoutRtl = isLayoutRtl; 59 mPreviewFrames = new FrameLayout[previewSampleResIds.length]; 60 61 for (int i = 0; i < previewSampleResIds.length; ++i) { 62 int p = mIsLayoutRtl ? previewSampleResIds.length - 1 - i : i; 63 mPreviewFrames[p] = new FrameLayout(context); 64 mPreviewFrames[p].setLayoutParams(new LinearLayout.LayoutParams( 65 LinearLayout.LayoutParams.MATCH_PARENT, 66 LinearLayout.LayoutParams.MATCH_PARENT)); 67 68 for (Configuration configuration : configurations) { 69 // Create a new configuration for the specified value. It won't 70 // have any theme set, so manually apply the current theme. 71 final Context configContext = context.createConfigurationContext(configuration); 72 configContext.setTheme(context.getThemeResId()); 73 74 final LayoutInflater configInflater = LayoutInflater.from(configContext); 75 final View sampleView = configInflater.inflate(previewSampleResIds[i], 76 mPreviewFrames[p], false); 77 sampleView.setAlpha(0); 78 sampleView.setVisibility(View.INVISIBLE); 79 mPreviewFrames[p].addView(sampleView); 80 } 81 } 82 } 83 84 @Override destroyItem(ViewGroup container, int position, Object object)85 public void destroyItem (ViewGroup container, int position, Object object) { 86 container.removeView((View) object); 87 } 88 89 @Override getCount()90 public int getCount() { 91 return mPreviewFrames.length; 92 } 93 94 @Override instantiateItem(ViewGroup container, int position)95 public Object instantiateItem(ViewGroup container, int position) { 96 container.addView(mPreviewFrames[position]); 97 return mPreviewFrames[position]; 98 } 99 100 @Override isViewFromObject(View view, Object object)101 public boolean isViewFromObject(View view, Object object) { 102 return (view == object); 103 } 104 isAnimating()105 boolean isAnimating() { 106 return mAnimationCounter > 0; 107 } 108 setAnimationEndAction(Runnable action)109 void setAnimationEndAction(Runnable action) { 110 mAnimationEndAction = action; 111 } 112 setPreviewLayer(int newIndex, int currentIndex, int currentItem, boolean animate)113 void setPreviewLayer(int newIndex, int currentIndex, int currentItem, boolean animate) { 114 for (FrameLayout previewFrame : mPreviewFrames) { 115 if (currentIndex >= 0) { 116 final View lastLayer = previewFrame.getChildAt(currentIndex); 117 if (animate && previewFrame == mPreviewFrames[currentItem]) { 118 lastLayer.animate() 119 .alpha(0) 120 .setInterpolator(FADE_OUT_INTERPOLATOR) 121 .setDuration(CROSS_FADE_DURATION_MS) 122 .setListener(new PreviewFrameAnimatorListener()) 123 .withEndAction(new Runnable() { 124 @Override 125 public void run() { 126 lastLayer.setVisibility(View.INVISIBLE); 127 } 128 }); 129 } else { 130 lastLayer.setAlpha(0); 131 lastLayer.setVisibility(View.INVISIBLE); 132 } 133 } 134 135 final View nextLayer = previewFrame.getChildAt(newIndex); 136 if (animate && previewFrame == mPreviewFrames[currentItem]) { 137 nextLayer.animate() 138 .alpha(1) 139 .setInterpolator(FADE_IN_INTERPOLATOR) 140 .setDuration(CROSS_FADE_DURATION_MS) 141 .setListener(new PreviewFrameAnimatorListener()) 142 .withStartAction(new Runnable() { 143 @Override 144 public void run() { 145 nextLayer.setVisibility(View.VISIBLE); 146 } 147 }); 148 } else { 149 nextLayer.setVisibility(View.VISIBLE); 150 nextLayer.setAlpha(1); 151 } 152 } 153 } 154 runAnimationEndAction()155 private void runAnimationEndAction() { 156 if (mAnimationEndAction != null && !isAnimating()) { 157 mAnimationEndAction.run(); 158 mAnimationEndAction = null; 159 } 160 } 161 162 private class PreviewFrameAnimatorListener implements AnimatorListener { 163 @Override onAnimationStart(Animator animation)164 public void onAnimationStart(Animator animation) { 165 mAnimationCounter++; 166 } 167 168 @Override onAnimationEnd(Animator animation)169 public void onAnimationEnd(Animator animation) { 170 mAnimationCounter--; 171 runAnimationEndAction(); 172 } 173 174 @Override onAnimationCancel(Animator animation)175 public void onAnimationCancel(Animator animation) { 176 // Empty method. 177 } 178 179 @Override onAnimationRepeat(Animator animation)180 public void onAnimationRepeat(Animator animation) { 181 // Empty method. 182 } 183 } 184 } 185