blob: c6f6e81d452b9b431f8edd1cabee81bbed71a766 [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
Jeff Sharkey1162fd72009-11-04 17:58:08 -080019import android.content.BroadcastReceiver;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.Context;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080021import android.content.Intent;
22import android.content.IntentFilter;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080023import android.content.res.TypedArray;
24import android.os.Handler;
25import android.os.Message;
26import android.util.AttributeSet;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080027import android.util.Log;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080028import android.widget.RemoteViews.RemoteView;
29
30/**
31 * Simple {@link ViewAnimator} that will animate between two or more views
32 * that have been added to it. Only one child is shown at a time. If
33 * requested, can automatically flip between each child at a regular interval.
34 *
35 * @attr ref android.R.styleable#ViewFlipper_flipInterval
Jeff Sharkey1162fd72009-11-04 17:58:08 -080036 * @attr ref android.R.styleable#ViewFlipper_autoStart
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080037 */
Jeff Sharkey1162fd72009-11-04 17:58:08 -080038@RemoteView
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080039public class ViewFlipper extends ViewAnimator {
Jeff Sharkey1162fd72009-11-04 17:58:08 -080040 private static final String TAG = "ViewFlipper";
Jeff Sharkey2b95c242010-02-08 17:40:30 -080041 private static final boolean LOGD = false;
Jeff Sharkey1162fd72009-11-04 17:58:08 -080042
43 private static final int DEFAULT_INTERVAL = 3000;
44
45 private int mFlipInterval = DEFAULT_INTERVAL;
46 private boolean mAutoStart = false;
47
48 private boolean mRunning = false;
49 private boolean mStarted = false;
50 private boolean mVisible = false;
51 private boolean mUserPresent = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052
53 public ViewFlipper(Context context) {
54 super(context);
55 }
56
57 public ViewFlipper(Context context, AttributeSet attrs) {
58 super(context, attrs);
59
60 TypedArray a = context.obtainStyledAttributes(attrs,
61 com.android.internal.R.styleable.ViewFlipper);
Jeff Sharkey1162fd72009-11-04 17:58:08 -080062 mFlipInterval = a.getInt(
63 com.android.internal.R.styleable.ViewFlipper_flipInterval, DEFAULT_INTERVAL);
64 mAutoStart = a.getBoolean(
65 com.android.internal.R.styleable.ViewFlipper_autoStart, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080066 a.recycle();
67 }
68
Jeff Sharkey1162fd72009-11-04 17:58:08 -080069 private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
70 @Override
71 public void onReceive(Context context, Intent intent) {
72 final String action = intent.getAction();
73 if (Intent.ACTION_SCREEN_OFF.equals(action)) {
74 mUserPresent = false;
75 updateRunning();
76 } else if (Intent.ACTION_USER_PRESENT.equals(action)) {
77 mUserPresent = true;
Mason Tangf70036b2010-06-14 17:47:24 -070078 updateRunning(false);
Jeff Sharkey1162fd72009-11-04 17:58:08 -080079 }
80 }
81 };
82
83 @Override
84 protected void onAttachedToWindow() {
85 super.onAttachedToWindow();
86
87 // Listen for broadcasts related to user-presence
88 final IntentFilter filter = new IntentFilter();
89 filter.addAction(Intent.ACTION_SCREEN_OFF);
90 filter.addAction(Intent.ACTION_USER_PRESENT);
91 getContext().registerReceiver(mReceiver, filter);
92
93 if (mAutoStart) {
94 // Automatically start when requested
95 startFlipping();
96 }
97 }
98
99 @Override
100 protected void onDetachedFromWindow() {
101 super.onDetachedFromWindow();
102 mVisible = false;
103
104 getContext().unregisterReceiver(mReceiver);
105 updateRunning();
106 }
107
108 @Override
109 protected void onWindowVisibilityChanged(int visibility) {
110 super.onWindowVisibilityChanged(visibility);
111 mVisible = visibility == VISIBLE;
Mason Tangf70036b2010-06-14 17:47:24 -0700112 updateRunning(false);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800113 }
114
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800115 /**
116 * How long to wait before flipping to the next view
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800117 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800118 * @param milliseconds
119 * time in milliseconds
120 */
121 @android.view.RemotableViewMethod
122 public void setFlipInterval(int milliseconds) {
123 mFlipInterval = milliseconds;
124 }
125
126 /**
127 * Start a timer to cycle through child views
128 */
129 public void startFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800130 mStarted = true;
131 updateRunning();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800132 }
133
134 /**
135 * No more flips
136 */
137 public void stopFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800138 mStarted = false;
139 updateRunning();
140 }
141
142 /**
143 * Internal method to start or stop dispatching flip {@link Message} based
144 * on {@link #mRunning} and {@link #mVisible} state.
145 */
146 private void updateRunning() {
Mason Tangf70036b2010-06-14 17:47:24 -0700147 updateRunning(true);
148 }
149
150 /**
151 * Internal method to start or stop dispatching flip {@link Message} based
152 * on {@link #mRunning} and {@link #mVisible} state.
153 *
154 * @param flipNow Determines whether or not to execute the animation now, in
155 * addition to queuing future flips. If omitted, defaults to
156 * true.
157 */
158 private void updateRunning(boolean flipNow) {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800159 boolean running = mVisible && mStarted && mUserPresent;
160 if (running != mRunning) {
161 if (running) {
Mason Tangf70036b2010-06-14 17:47:24 -0700162 showOnly(mWhichChild, flipNow);
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800163 Message msg = mHandler.obtainMessage(FLIP_MSG);
164 mHandler.sendMessageDelayed(msg, mFlipInterval);
165 } else {
166 mHandler.removeMessages(FLIP_MSG);
167 }
168 mRunning = running;
169 }
170 if (LOGD) {
171 Log.d(TAG, "updateRunning() mVisible=" + mVisible + ", mStarted=" + mStarted
172 + ", mUserPresent=" + mUserPresent + ", mRunning=" + mRunning);
173 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800174 }
175
176 /**
177 * Returns true if the child views are flipping.
178 */
179 public boolean isFlipping() {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800180 return mStarted;
181 }
182
183 /**
184 * Set if this view automatically calls {@link #startFlipping()} when it
185 * becomes attached to a window.
186 */
187 public void setAutoStart(boolean autoStart) {
188 mAutoStart = autoStart;
189 }
190
191 /**
192 * Returns true if this view automatically calls {@link #startFlipping()}
193 * when it becomes attached to a window.
194 */
195 public boolean isAutoStart() {
196 return mAutoStart;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800197 }
198
199 private final int FLIP_MSG = 1;
200
201 private final Handler mHandler = new Handler() {
202 @Override
203 public void handleMessage(Message msg) {
204 if (msg.what == FLIP_MSG) {
Jeff Sharkey1162fd72009-11-04 17:58:08 -0800205 if (mRunning) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800206 showNext();
207 msg = obtainMessage(FLIP_MSG);
208 sendMessageDelayed(msg, mFlipInterval);
209 }
210 }
211 }
212 };
213}