blob: b962298e3d46c11b5264d07c8e85e991d1cb4e3a [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
Ashley Rose433cb1d2019-02-28 18:41:26 -050019import android.annotation.IntRange;
Mathew Inwood978c6e22018-08-21 15:58:55 +010020import android.annotation.UnsupportedAppUsage;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080021import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.Context;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080023import android.content.Intent;
24import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080025import android.content.res.TypedArray;
Aurimas Liutikas99441c52016-10-11 16:48:32 -070026import android.os.Message;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080027import android.util.AttributeSet;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080028import android.util.Log;
Ashley Rose55f9f922019-01-28 19:29:36 -050029import android.view.inspector.InspectableProperty;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080030import android.widget.RemoteViews.RemoteView;
31
32/**
33 * Simple {@link ViewAnimator} that will animate between two or more views
34 * that have been added to it. Only one child is shown at a time. If
35 * requested, can automatically flip between each child at a regular interval.
36 *
37 * @attr ref android.R.styleable#ViewFlipper_flipInterval
Jeff Sharkey1162fd72009-11-04 17:58:08 -080038 * @attr ref android.R.styleable#ViewFlipper_autoStart
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039 */
Jeff Sharkey1162fd72009-11-04 17:58:08 -080040@RemoteView
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080041public class ViewFlipper extends ViewAnimator {
Jeff Sharkey1162fd72009-11-04 17:58:08 -080042 private static final String TAG = "ViewFlipper";
Jeff Sharkey2b95c242010-02-08 17:40:30 -080043 private static final boolean LOGD = false;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080044
45 private static final int DEFAULT_INTERVAL = 3000;
46
47 private int mFlipInterval = DEFAULT_INTERVAL;
48 private boolean mAutoStart = false;
49
50 private boolean mRunning = false;
51 private boolean mStarted = false;
52 private boolean mVisible = false;
Mathew Inwood978c6e22018-08-21 15:58:55 +010053 @UnsupportedAppUsage
Jeff Sharkey1162fd72009-11-04 17:58:08 -080054 private boolean mUserPresent = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055
56 public ViewFlipper(Context context) {
57 super(context);
58 }
59
60 public ViewFlipper(Context context, AttributeSet attrs) {
61 super(context, attrs);
62
63 TypedArray a = context.obtainStyledAttributes(attrs,
64 com.android.internal.R.styleable.ViewFlipper);
Jeff Sharkey1162fd72009-11-04 17:58:08 -080065 mFlipInterval = a.getInt(
66 com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL);
67 mAutoStart = a.getBoolean(
68 com.android.internal.R.styleable.ViewFlipper_autoStart, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080069 a.recycle();
70 }
71
Jeff Sharkey1162fd72009-11-04 17:58:08 -080072 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
73 @Override
74 public void onReceive(Context context, Intent intent) {
75 final String action = intent.getAction();
76 if (Intent.ACTION_SCREEN_OFF.equals(action)) {
77 mUserPresent = false;
78 updateRunning();
79 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
80 mUserPresent = true;
Mason Tangf70036b2010-06-14 17:47:24 -070081 updateRunning(false);
Jeff Sharkey1162fd72009-11-04 17:58:08 -080082 }
83 }
84 };
85
86 @Override
87 protected void onAttachedToWindow() {
88 super.onAttachedToWindow();
89
90 // Listen for broadcasts related to user-presence
91 final IntentFilter filter = new IntentFilter();
92 filter.addAction(Intent.ACTION_SCREEN_OFF);
93 filter.addAction(Intent.ACTION_USER_PRESENT);
Svetoslav39999cf2014-07-16 15:12:03 -070094
95 // OK, this is gross but needed. This class is supported by the
96 // remote views machanism and as a part of that the remote views
97 // can be inflated by a context for another user without the app
98 // having interact users permission - just for loading resources.
99 // For exmaple, when adding widgets from a user profile to the
100 // home screen. Therefore, we register the receiver as the current
101 // user not the one the context is for.
102 getContext().registerReceiverAsUser(mReceiver, android.os.Process.myUserHandle(),
John Reckd0374c62015-10-20 13:25:01 -0700103 filter, null, getHandler());
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800104
105 if (mAutoStart) {
106 // Automatically start when requested
107 startFlipping();
108 }
109 }
110
111 @Override
112 protected void onDetachedFromWindow() {
113 super.onDetachedFromWindow();
114 mVisible = false;
115
116 getContext().unregisterReceiver(mReceiver);
117 updateRunning();
118 }
119
120 @Override
121 protected void onWindowVisibilityChanged(int visibility) {
122 super.onWindowVisibilityChanged(visibility);
123 mVisible = visibility == VISIBLE;
Mason Tangf70036b2010-06-14 17:47:24 -0700124 updateRunning(false);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800125 }
126
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800127 /**
128 * How long to wait before flipping to the next view
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800129 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800130 * @param milliseconds
131 * time in milliseconds
132 */
133 @android.view.RemotableViewMethod
Ashley Rose433cb1d2019-02-28 18:41:26 -0500134 public void setFlipInterval(@IntRange(from = 0) int milliseconds) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800135 mFlipInterval = milliseconds;
136 }
137
138 /**
Ashley Rose55f9f922019-01-28 19:29:36 -0500139 * Get the delay before flipping to the next view.
140 *
141 * @return delay time in milliseconds
142 */
143 @InspectableProperty
Ashley Rose433cb1d2019-02-28 18:41:26 -0500144 @IntRange(from = 0)
Ashley Rose55f9f922019-01-28 19:29:36 -0500145 public int getFlipInterval() {
146 return mFlipInterval;
147 }
148
149 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800150 * Start a timer to cycle through child views
151 */
152 public void startFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800153 mStarted = true;
154 updateRunning();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800155 }
156
157 /**
158 * No more flips
159 */
160 public void stopFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800161 mStarted = false;
162 updateRunning();
163 }
164
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800165 @Override
Dianne Hackborna7bb6fb2015-02-03 18:13:40 -0800166 public CharSequence getAccessibilityClassName() {
167 return ViewFlipper.class.getName();
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -0800168 }
169
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800170 /**
171 * Internal method to start or stop dispatching flip {@link Message} based
172 * on {@link #mRunning} and {@link #mVisible} state.
173 */
174 private void updateRunning() {
Mason Tangf70036b2010-06-14 17:47:24 -0700175 updateRunning(true);
176 }
177
178 /**
179 * Internal method to start or stop dispatching flip {@link Message} based
180 * on {@link #mRunning} and {@link #mVisible} state.
181 *
182 * @param flipNow Determines whether or not to execute the animation now, in
183 * addition to queuing future flips. If omitted, defaults to
184 * true.
185 */
Mathew Inwood978c6e22018-08-21 15:58:55 +0100186 @UnsupportedAppUsage
Mason Tangf70036b2010-06-14 17:47:24 -0700187 private void updateRunning(boolean flipNow) {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800188 boolean running = mVisible && mStarted && mUserPresent;
189 if (running != mRunning) {
190 if (running) {
Mason Tangf70036b2010-06-14 17:47:24 -0700191 showOnly(mWhichChild, flipNow);
John Reckd0374c62015-10-20 13:25:01 -0700192 postDelayed(mFlipRunnable, mFlipInterval);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800193 } else {
John Reckd0374c62015-10-20 13:25:01 -0700194 removeCallbacks(mFlipRunnable);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800195 }
196 mRunning = running;
197 }
198 if (LOGD) {
199 Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
200 + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning);
201 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 }
203
204 /**
205 * Returns true if the child views are flipping.
206 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500207 @InspectableProperty(hasAttributeId = false)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800208 public boolean isFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800209 return mStarted;
210 }
211
212 /**
213 * Set if this view automatically calls {@link #startFlipping()} when it
214 * becomes attached to a window.
215 */
216 public void setAutoStart(boolean autoStart) {
217 mAutoStart = autoStart;
218 }
219
220 /**
221 * Returns true if this view automatically calls {@link #startFlipping()}
222 * when it becomes attached to a window.
223 */
Ashley Rose55f9f922019-01-28 19:29:36 -0500224 @InspectableProperty
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800225 public boolean isAutoStart() {
226 return mAutoStart;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800227 }
228
John Reckd0374c62015-10-20 13:25:01 -0700229 private final Runnable mFlipRunnable = new Runnable() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800230 @Override
John Reckd0374c62015-10-20 13:25:01 -0700231 public void run() {
232 if (mRunning) {
233 showNext();
234 postDelayed(mFlipRunnable, mFlipInterval);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800235 }
236 }
237 };
238}