blob: 414b1369d23ec10f9581e2033277433b41adcfd9 [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
2 * Copyright (C) 2006 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
17package android.widget;
18
Mathew Inwood978c6e22018-08-21 15:58:55 +010019import android.annotation.UnsupportedAppUsage;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080020import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080021import android.content.Context;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080022import android.content.Intent;
23import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080024import android.content.res.TypedArray;
Aurimas Liutikas99441c52016-10-11 16:48:32 -070025import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.util.AttributeSet;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080027import android.util.Log;
Ashley Rose55f9f922019-01-28 19:29:36 -050028import android.view.inspector.InspectableProperty;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.widget.RemoteViews.RemoteView;
30
31/**
32 * Simple {@link ViewAnimator} that will animate between two or more views
33 * that have been added to it. Only one child is shown at a time. If
34 * requested, can automatically flip between each child at a regular interval.
35 *
36 * @attr ref android.R.styleable#ViewFlipper_flipInterval
Jeff Sharkey1162fd72009-11-04 17:58:08 -080037 * @attr ref android.R.styleable#ViewFlipper_autoStart
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038 */
Jeff Sharkey1162fd72009-11-04 17:58:08 -080039@RemoteView
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040public class ViewFlipper extends ViewAnimator {
Jeff Sharkey1162fd72009-11-04 17:58:08 -080041 private static final String TAG = "ViewFlipper";
Jeff Sharkey2b95c242010-02-08 17:40:30 -080042 private static final boolean LOGD = false;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080043
44 private static final int DEFAULT_INTERVAL = 3000;
45
46 private int mFlipInterval = DEFAULT_INTERVAL;
47 private boolean mAutoStart = false;
48
49 private boolean mRunning = false;
50 private boolean mStarted = false;
51 private boolean mVisible = false;
Mathew Inwood978c6e22018-08-21 15:58:55 +010052 @UnsupportedAppUsage
Jeff Sharkey1162fd72009-11-04 17:58:08 -080053 private boolean mUserPresent = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054
55 public ViewFlipper(Context context) {
56 super(context);
57 }
58
59 public ViewFlipper(Context context, AttributeSet attrs) {
60 super(context, attrs);
61
62 TypedArray a = context.obtainStyledAttributes(attrs,
63 com.android.internal.R.styleable.ViewFlipper);
Jeff Sharkey1162fd72009-11-04 17:58:08 -080064 mFlipInterval = a.getInt(
65 com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL);
66 mAutoStart = a.getBoolean(
67 com.android.internal.R.styleable.ViewFlipper_autoStart, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080068 a.recycle();
69 }
70
Jeff Sharkey1162fd72009-11-04 17:58:08 -080071 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
72 @Override
73 public void onReceive(Context context, Intent intent) {
74 final String action = intent.getAction();
75 if (Intent.ACTION_SCREEN_OFF.equals(action)) {
76 mUserPresent = false;
77 updateRunning();
78 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
79 mUserPresent = true;
Mason Tangf70036b2010-06-14 17:47:24 -070080 updateRunning(false);
Jeff Sharkey1162fd72009-11-04 17:58:08 -080081 }
82 }
83 };
84
85 @Override
86 protected void onAttachedToWindow() {
87 super.onAttachedToWindow();
88
89 // Listen for broadcasts related to user-presence
90 final IntentFilter filter = new IntentFilter();
91 filter.addAction(Intent.ACTION_SCREEN_OFF);
92 filter.addAction(Intent.ACTION_USER_PRESENT);
Svetoslav39999cf2014-07-16 15:12:03 -070093
94 // OK, this is gross but needed. This class is supported by the
95 // remote views machanism and as a part of that the remote views
96 // can be inflated by a context for another user without the app
97 // having interact users permission - just for loading resources.
98 // For exmaple, when adding widgets from a user profile to the
99 // home screen. Therefore, we register the receiver as the current
100 // user not the one the context is for.
101 getContext().registerReceiverAsUser(mReceiver, android.os.Process.myUserHandle(),
John Reckd0374c62015-10-20 13:25:01 -0700102 filter, null, getHandler());
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800103
104 if (mAutoStart) {
105 // Automatically start when requested
106 startFlipping();
107 }
108 }
109
110 @Override
111 protected void onDetachedFromWindow() {
112 super.onDetachedFromWindow();
113 mVisible = false;
114
115 getContext().unregisterReceiver(mReceiver);
116 updateRunning();
117 }
118
119 @Override
120 protected void onWindowVisibilityChanged(int visibility) {
121 super.onWindowVisibilityChanged(visibility);
122 mVisible = visibility == VISIBLE;
Mason Tangf70036b2010-06-14 17:47:24 -0700123 updateRunning(false);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800124 }
125
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800126 /**
127 * How long to wait before flipping to the next view
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800128 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800129 * @param milliseconds
130 * time in milliseconds
131 */
132 @android.view.RemotableViewMethod
133 public void setFlipInterval(int milliseconds) {
134 mFlipInterval = milliseconds;
135 }
136
137 /**
Ashley Rose55f9f922019-01-28 19:29:36 -0500138 * Get the delay before flipping to the next view.
139 *
140 * @return delay time in milliseconds
141 */
142 @InspectableProperty
143 public int getFlipInterval() {
144 return mFlipInterval;
145 }
146
147 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800148 * Start a timer to cycle through child views
149 */
150 public void startFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800151 mStarted = true;
152 updateRunning();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800153 }
154
155 /**
156 * No more flips
157 */
158 public void stopFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800159 mStarted = false;
160 updateRunning();
161 }
162
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800163 @Override
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -0800164 public CharSequence getAccessibilityClassName() {
165 return ViewFlipper.class.getName();
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800166 }
167
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800168 /**
169 * Internal method to start or stop dispatching flip {@link Message} based
170 * on {@link #mRunning} and {@link #mVisible} state.
171 */
172 private void updateRunning() {
Mason Tangf70036b2010-06-14 17:47:24 -0700173 updateRunning(true);
174 }
175
176 /**
177 * Internal method to start or stop dispatching flip {@link Message} based
178 * on {@link #mRunning} and {@link #mVisible} state.
179 *
180 * @param flipNow Determines whether or not to execute the animation now, in
181 * addition to queuing future flips. If omitted, defaults to
182 * true.
183 */
Mathew Inwood978c6e22018-08-21 15:58:55 +0100184 @UnsupportedAppUsage
Mason Tangf70036b2010-06-14 17:47:24 -0700185 private void updateRunning(boolean flipNow) {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800186 boolean running = mVisible && mStarted && mUserPresent;
187 if (running != mRunning) {
188 if (running) {
Mason Tangf70036b2010-06-14 17:47:24 -0700189 showOnly(mWhichChild, flipNow);
John Reckd0374c62015-10-20 13:25:01 -0700190 postDelayed(mFlipRunnable, mFlipInterval);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800191 } else {
John Reckd0374c62015-10-20 13:25:01 -0700192 removeCallbacks(mFlipRunnable);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800193 }
194 mRunning = running;
195 }
196 if (LOGD) {
197 Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
198 + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning);
199 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800200 }
201
202 /**
203 * Returns true if the child views are flipping.
204 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500205 @InspectableProperty(hasAttributeId = false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 public boolean isFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800207 return mStarted;
208 }
209
210 /**
211 * Set if this view automatically calls {@link #startFlipping()} when it
212 * becomes attached to a window.
213 */
214 public void setAutoStart(boolean autoStart) {
215 mAutoStart = autoStart;
216 }
217
218 /**
219 * Returns true if this view automatically calls {@link #startFlipping()}
220 * when it becomes attached to a window.
221 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500222 @InspectableProperty
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800223 public boolean isAutoStart() {
224 return mAutoStart;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 }
226
John Reckd0374c62015-10-20 13:25:01 -0700227 private final Runnable mFlipRunnable = new Runnable() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800228 @Override
John Reckd0374c62015-10-20 13:25:01 -0700229 public void run() {
230 if (mRunning) {
231 showNext();
232 postDelayed(mFlipRunnable, mFlipInterval);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800233 }
234 }
235 };
236}