blob: 50de5136002e4c362c9ce62584931b402c627ff7 [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.view;
18
Christopher Tatea53146c2010-09-07 11:57:52 -070019import android.content.ClipData;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080020import android.content.Context;
Dianne Hackborne36d6e22010-02-17 19:46:25 -080021import android.content.res.Configuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080022import android.content.res.Resources;
23import android.content.res.TypedArray;
24import android.graphics.Bitmap;
Adam Powell2b342f02010-08-18 18:14:13 -070025import android.graphics.Camera;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080026import android.graphics.Canvas;
Philip Milne1557fd72012-04-04 23:41:34 -070027import android.graphics.Insets;
Mike Cleronf116bf82009-09-27 19:14:12 -070028import android.graphics.Interpolator;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080029import android.graphics.LinearGradient;
30import android.graphics.Matrix;
31import android.graphics.Paint;
32import android.graphics.PixelFormat;
svetoslavganov75986cf2009-05-14 22:28:01 -070033import android.graphics.Point;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080034import android.graphics.PorterDuff;
35import android.graphics.PorterDuffXfermode;
36import android.graphics.Rect;
Adam Powell6e346362010-07-23 10:18:23 -070037import android.graphics.RectF;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080038import android.graphics.Region;
39import android.graphics.Shader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080040import android.graphics.drawable.ColorDrawable;
41import android.graphics.drawable.Drawable;
Jeff Brownbd6e1502012-08-28 03:27:37 -070042import android.hardware.display.DisplayManagerGlobal;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070043import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080044import android.os.Handler;
45import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080046import android.os.Parcel;
47import android.os.Parcelable;
48import android.os.RemoteException;
49import android.os.SystemClock;
Philip Milne10ca24a2012-04-23 15:38:27 -070050import android.os.SystemProperties;
Fabrice Di Megliod3d9f3f2012-09-18 12:55:32 -070051import android.text.TextUtils;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052import android.util.AttributeSet;
Doug Feltcb3791202011-07-07 11:57:48 -070053import android.util.FloatProperty;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080054import android.util.Log;
Romain Guyd928d682009-03-31 17:52:16 -070055import android.util.Pool;
svetoslavganov75986cf2009-05-14 22:28:01 -070056import android.util.Poolable;
Romain Guyd928d682009-03-31 17:52:16 -070057import android.util.PoolableManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070058import android.util.Pools;
Doug Feltcb3791202011-07-07 11:57:48 -070059import android.util.Property;
svetoslavganov75986cf2009-05-14 22:28:01 -070060import android.util.SparseArray;
Jeff Brown33bbfd22011-02-24 20:55:35 -080061import android.util.TypedValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080062import android.view.ContextMenu.ContextMenuInfo;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -070063import android.view.AccessibilityIterators.TextSegmentIterator;
64import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
65import android.view.AccessibilityIterators.WordTextSegmentIterator;
66import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
svetoslavganov75986cf2009-05-14 22:28:01 -070067import android.view.accessibility.AccessibilityEvent;
68import android.view.accessibility.AccessibilityEventSource;
69import android.view.accessibility.AccessibilityManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070070import android.view.accessibility.AccessibilityNodeInfo;
Svetoslav Ganov02107852011-10-03 17:06:56 -070071import android.view.accessibility.AccessibilityNodeProvider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080072import android.view.animation.Animation;
Mike Cleron3ecd58c2009-09-28 11:39:02 -070073import android.view.animation.AnimationUtils;
Chet Haase64a48c12012-02-13 16:33:29 -080074import android.view.animation.Transformation;
svetoslavganov75986cf2009-05-14 22:28:01 -070075import android.view.inputmethod.EditorInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080076import android.view.inputmethod.InputConnection;
77import android.view.inputmethod.InputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080078import android.widget.ScrollBarDrawable;
79
Romain Guy1ef3fdb2011-09-09 15:30:30 -070080import static android.os.Build.VERSION_CODES.*;
Philip Milne6c8ea062012-04-03 17:38:43 -070081import static java.lang.Math.max;
Romain Guy1ef3fdb2011-09-09 15:30:30 -070082
Doug Feltcb3791202011-07-07 11:57:48 -070083import com.android.internal.R;
84import com.android.internal.util.Predicate;
85import com.android.internal.view.menu.MenuBuilder;
86
Christopher Tatea0374192010-10-05 13:06:41 -070087import java.lang.ref.WeakReference;
svetoslavganov75986cf2009-05-14 22:28:01 -070088import java.lang.reflect.InvocationTargetException;
89import java.lang.reflect.Method;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080090import java.util.ArrayList;
91import java.util.Arrays;
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070092import java.util.Locale;
Adam Powell4afd62b2011-02-18 15:02:18 -080093import java.util.concurrent.CopyOnWriteArrayList;
Adam Powella9108a22012-07-18 11:18:09 -070094import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095
96/**
97 * <p>
98 * This class represents the basic building block for user interface components. A View
99 * occupies a rectangular area on the screen and is responsible for drawing and
100 * event handling. View is the base class for <em>widgets</em>, which are
Romain Guy8506ab42009-06-11 17:35:47 -0700101 * used to create interactive UI components (buttons, text fields, etc.). The
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800102 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
103 * are invisible containers that hold other Views (or other ViewGroups) and define
104 * their layout properties.
105 * </p>
106 *
Joe Fernandezb54e7a32011-10-03 15:09:50 -0700107 * <div class="special reference">
108 * <h3>Developer Guides</h3>
109 * <p>For information about using this class to develop your application's user interface,
110 * read the <a href="{@docRoot}guide/topics/ui/index.html">User Interface</a> developer guide.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800111 * </div>
Romain Guy8506ab42009-06-11 17:35:47 -0700112 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800113 * <a name="Using"></a>
114 * <h3>Using Views</h3>
115 * <p>
116 * All of the views in a window are arranged in a single tree. You can add views
117 * either from code or by specifying a tree of views in one or more XML layout
118 * files. There are many specialized subclasses of views that act as controls or
119 * are capable of displaying text, images, or other content.
120 * </p>
121 * <p>
122 * Once you have created a tree of views, there are typically a few types of
123 * common operations you may wish to perform:
124 * <ul>
125 * <li><strong>Set properties:</strong> for example setting the text of a
126 * {@link android.widget.TextView}. The available properties and the methods
127 * that set them will vary among the different subclasses of views. Note that
128 * properties that are known at build time can be set in the XML layout
129 * files.</li>
130 * <li><strong>Set focus:</strong> The framework will handled moving focus in
131 * response to user input. To force focus to a specific view, call
132 * {@link #requestFocus}.</li>
133 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
134 * that will be notified when something interesting happens to the view. For
135 * example, all views will let you set a listener to be notified when the view
136 * gains or loses focus. You can register such a listener using
Romain Guy5c22a8c2011-05-13 11:48:45 -0700137 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
Philip Milne6c8ea062012-04-03 17:38:43 -0700138 * Other view subclasses offer more specialized listeners. For example, a Button
Romain Guy5c22a8c2011-05-13 11:48:45 -0700139 * exposes a listener to notify clients when the button is clicked.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800140 * <li><strong>Set visibility:</strong> You can hide or show views using
Romain Guy5c22a8c2011-05-13 11:48:45 -0700141 * {@link #setVisibility(int)}.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800142 * </ul>
143 * </p>
144 * <p><em>
145 * Note: The Android framework is responsible for measuring, laying out and
146 * drawing views. You should not call methods that perform these actions on
147 * views yourself unless you are actually implementing a
148 * {@link android.view.ViewGroup}.
149 * </em></p>
150 *
151 * <a name="Lifecycle"></a>
152 * <h3>Implementing a Custom View</h3>
153 *
154 * <p>
155 * To implement a custom view, you will usually begin by providing overrides for
156 * some of the standard methods that the framework calls on all views. You do
157 * not need to override all of these methods. In fact, you can start by just
158 * overriding {@link #onDraw(android.graphics.Canvas)}.
159 * <table border="2" width="85%" align="center" cellpadding="5">
160 * <thead>
161 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
162 * </thead>
163 *
164 * <tbody>
165 * <tr>
166 * <td rowspan="2">Creation</td>
167 * <td>Constructors</td>
168 * <td>There is a form of the constructor that are called when the view
169 * is created from code and a form that is called when the view is
170 * inflated from a layout file. The second form should parse and apply
171 * any attributes defined in the layout file.
172 * </td>
173 * </tr>
174 * <tr>
175 * <td><code>{@link #onFinishInflate()}</code></td>
176 * <td>Called after a view and all of its children has been inflated
177 * from XML.</td>
178 * </tr>
179 *
180 * <tr>
181 * <td rowspan="3">Layout</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700182 * <td><code>{@link #onMeasure(int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800183 * <td>Called to determine the size requirements for this view and all
184 * of its children.
185 * </td>
186 * </tr>
187 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700188 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800189 * <td>Called when this view should assign a size and position to all
190 * of its children.
191 * </td>
192 * </tr>
193 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700194 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800195 * <td>Called when the size of this view has changed.
196 * </td>
197 * </tr>
198 *
199 * <tr>
200 * <td>Drawing</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700201 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800202 * <td>Called when the view should render its content.
203 * </td>
204 * </tr>
205 *
206 * <tr>
207 * <td rowspan="4">Event processing</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700208 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
Jean Chalard405bc512012-05-29 19:12:34 +0900209 * <td>Called when a new hardware key event occurs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800210 * </td>
211 * </tr>
212 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700213 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
Jean Chalard405bc512012-05-29 19:12:34 +0900214 * <td>Called when a hardware key up event occurs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800215 * </td>
216 * </tr>
217 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700218 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800219 * <td>Called when a trackball motion event occurs.
220 * </td>
221 * </tr>
222 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700223 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800224 * <td>Called when a touch screen motion event occurs.
225 * </td>
226 * </tr>
227 *
228 * <tr>
229 * <td rowspan="2">Focus</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700230 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800231 * <td>Called when the view gains or loses focus.
232 * </td>
233 * </tr>
234 *
235 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700236 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800237 * <td>Called when the window containing the view gains or loses focus.
238 * </td>
239 * </tr>
240 *
241 * <tr>
242 * <td rowspan="3">Attaching</td>
243 * <td><code>{@link #onAttachedToWindow()}</code></td>
244 * <td>Called when the view is attached to a window.
245 * </td>
246 * </tr>
247 *
248 * <tr>
249 * <td><code>{@link #onDetachedFromWindow}</code></td>
250 * <td>Called when the view is detached from its window.
251 * </td>
252 * </tr>
253 *
254 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700255 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800256 * <td>Called when the visibility of the window containing the view
257 * has changed.
258 * </td>
259 * </tr>
260 * </tbody>
261 *
262 * </table>
263 * </p>
264 *
265 * <a name="IDs"></a>
266 * <h3>IDs</h3>
267 * Views may have an integer id associated with them. These ids are typically
268 * assigned in the layout XML files, and are used to find specific views within
269 * the view tree. A common pattern is to:
270 * <ul>
271 * <li>Define a Button in the layout file and assign it a unique ID.
272 * <pre>
Gilles Debunne0243caf2010-08-24 23:06:35 -0700273 * &lt;Button
274 * android:id="@+id/my_button"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800275 * android:layout_width="wrap_content"
276 * android:layout_height="wrap_content"
277 * android:text="@string/my_button_text"/&gt;
278 * </pre></li>
279 * <li>From the onCreate method of an Activity, find the Button
280 * <pre class="prettyprint">
281 * Button myButton = (Button) findViewById(R.id.my_button);
282 * </pre></li>
283 * </ul>
284 * <p>
285 * View IDs need not be unique throughout the tree, but it is good practice to
286 * ensure that they are at least unique within the part of the tree you are
287 * searching.
288 * </p>
289 *
290 * <a name="Position"></a>
291 * <h3>Position</h3>
292 * <p>
293 * The geometry of a view is that of a rectangle. A view has a location,
294 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
295 * two dimensions, expressed as a width and a height. The unit for location
296 * and dimensions is the pixel.
297 * </p>
298 *
299 * <p>
300 * It is possible to retrieve the location of a view by invoking the methods
301 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
302 * coordinate of the rectangle representing the view. The latter returns the
303 * top, or Y, coordinate of the rectangle representing the view. These methods
304 * both return the location of the view relative to its parent. For instance,
305 * when getLeft() returns 20, that means the view is located 20 pixels to the
306 * right of the left edge of its direct parent.
307 * </p>
308 *
309 * <p>
310 * In addition, several convenience methods are offered to avoid unnecessary
311 * computations, namely {@link #getRight()} and {@link #getBottom()}.
312 * These methods return the coordinates of the right and bottom edges of the
313 * rectangle representing the view. For instance, calling {@link #getRight()}
314 * is similar to the following computation: <code>getLeft() + getWidth()</code>
315 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
316 * </p>
317 *
318 * <a name="SizePaddingMargins"></a>
319 * <h3>Size, padding and margins</h3>
320 * <p>
321 * The size of a view is expressed with a width and a height. A view actually
322 * possess two pairs of width and height values.
323 * </p>
324 *
325 * <p>
326 * The first pair is known as <em>measured width</em> and
327 * <em>measured height</em>. These dimensions define how big a view wants to be
328 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
329 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
330 * and {@link #getMeasuredHeight()}.
331 * </p>
332 *
333 * <p>
334 * The second pair is simply known as <em>width</em> and <em>height</em>, or
335 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
336 * dimensions define the actual size of the view on screen, at drawing time and
337 * after layout. These values may, but do not have to, be different from the
338 * measured width and height. The width and height can be obtained by calling
339 * {@link #getWidth()} and {@link #getHeight()}.
340 * </p>
341 *
342 * <p>
343 * To measure its dimensions, a view takes into account its padding. The padding
344 * is expressed in pixels for the left, top, right and bottom parts of the view.
345 * Padding can be used to offset the content of the view by a specific amount of
346 * pixels. For instance, a left padding of 2 will push the view's content by
347 * 2 pixels to the right of the left edge. Padding can be set using the
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -0700348 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
349 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
350 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
351 * {@link #getPaddingEnd()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800352 * </p>
353 *
354 * <p>
355 * Even though a view can define a padding, it does not provide any support for
356 * margins. However, view groups provide such a support. Refer to
357 * {@link android.view.ViewGroup} and
358 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
359 * </p>
360 *
361 * <a name="Layout"></a>
362 * <h3>Layout</h3>
363 * <p>
364 * Layout is a two pass process: a measure pass and a layout pass. The measuring
365 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
366 * of the view tree. Each view pushes dimension specifications down the tree
367 * during the recursion. At the end of the measure pass, every view has stored
368 * its measurements. The second pass happens in
369 * {@link #layout(int,int,int,int)} and is also top-down. During
370 * this pass each parent is responsible for positioning all of its children
371 * using the sizes computed in the measure pass.
372 * </p>
373 *
374 * <p>
375 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
376 * {@link #getMeasuredHeight()} values must be set, along with those for all of
377 * that view's descendants. A view's measured width and measured height values
378 * must respect the constraints imposed by the view's parents. This guarantees
379 * that at the end of the measure pass, all parents accept all of their
380 * children's measurements. A parent view may call measure() more than once on
381 * its children. For example, the parent may measure each child once with
382 * unspecified dimensions to find out how big they want to be, then call
383 * measure() on them again with actual numbers if the sum of all the children's
384 * unconstrained sizes is too big or too small.
385 * </p>
386 *
387 * <p>
388 * The measure pass uses two classes to communicate dimensions. The
389 * {@link MeasureSpec} class is used by views to tell their parents how they
390 * want to be measured and positioned. The base LayoutParams class just
391 * describes how big the view wants to be for both width and height. For each
392 * dimension, it can specify one of:
393 * <ul>
394 * <li> an exact number
Romain Guy980a9382010-01-08 15:06:28 -0800395 * <li>MATCH_PARENT, which means the view wants to be as big as its parent
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800396 * (minus padding)
397 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
398 * enclose its content (plus padding).
399 * </ul>
400 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
401 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
402 * an X and Y value.
403 * </p>
404 *
405 * <p>
406 * MeasureSpecs are used to push requirements down the tree from parent to
407 * child. A MeasureSpec can be in one of three modes:
408 * <ul>
409 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
410 * of a child view. For example, a LinearLayout may call measure() on its child
411 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
412 * tall the child view wants to be given a width of 240 pixels.
413 * <li>EXACTLY: This is used by the parent to impose an exact size on the
414 * child. The child must use this size, and guarantee that all of its
415 * descendants will fit within this size.
416 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
417 * child. The child must gurantee that it and all of its descendants will fit
418 * within this size.
419 * </ul>
420 * </p>
421 *
422 * <p>
423 * To intiate a layout, call {@link #requestLayout}. This method is typically
424 * called by a view on itself when it believes that is can no longer fit within
425 * its current bounds.
426 * </p>
427 *
428 * <a name="Drawing"></a>
429 * <h3>Drawing</h3>
430 * <p>
431 * Drawing is handled by walking the tree and rendering each view that
Joe Fernandez558459f2011-10-13 16:47:36 -0700432 * intersects the invalid region. Because the tree is traversed in-order,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800433 * this means that parents will draw before (i.e., behind) their children, with
434 * siblings drawn in the order they appear in the tree.
435 * If you set a background drawable for a View, then the View will draw it for you
436 * before calling back to its <code>onDraw()</code> method.
437 * </p>
438 *
439 * <p>
Romain Guy8506ab42009-06-11 17:35:47 -0700440 * Note that the framework will not draw views that are not in the invalid region.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800441 * </p>
442 *
443 * <p>
444 * To force a view to draw, call {@link #invalidate()}.
445 * </p>
446 *
447 * <a name="EventHandlingThreading"></a>
448 * <h3>Event Handling and Threading</h3>
449 * <p>
450 * The basic cycle of a view is as follows:
451 * <ol>
452 * <li>An event comes in and is dispatched to the appropriate view. The view
453 * handles the event and notifies any listeners.</li>
454 * <li>If in the course of processing the event, the view's bounds may need
455 * to be changed, the view will call {@link #requestLayout()}.</li>
456 * <li>Similarly, if in the course of processing the event the view's appearance
457 * may need to be changed, the view will call {@link #invalidate()}.</li>
458 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
459 * the framework will take care of measuring, laying out, and drawing the tree
460 * as appropriate.</li>
461 * </ol>
462 * </p>
463 *
464 * <p><em>Note: The entire view tree is single threaded. You must always be on
465 * the UI thread when calling any method on any view.</em>
466 * If you are doing work on other threads and want to update the state of a view
467 * from that thread, you should use a {@link Handler}.
468 * </p>
469 *
470 * <a name="FocusHandling"></a>
471 * <h3>Focus Handling</h3>
472 * <p>
473 * The framework will handle routine focus movement in response to user input.
474 * This includes changing the focus as views are removed or hidden, or as new
475 * views become available. Views indicate their willingness to take focus
476 * through the {@link #isFocusable} method. To change whether a view can take
477 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
478 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
479 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
480 * </p>
481 * <p>
482 * Focus movement is based on an algorithm which finds the nearest neighbor in a
483 * given direction. In rare cases, the default algorithm may not match the
484 * intended behavior of the developer. In these situations, you can provide
485 * explicit overrides by using these XML attributes in the layout file:
486 * <pre>
487 * nextFocusDown
488 * nextFocusLeft
489 * nextFocusRight
490 * nextFocusUp
491 * </pre>
492 * </p>
493 *
494 *
495 * <p>
496 * To get a particular view to take focus, call {@link #requestFocus()}.
497 * </p>
498 *
499 * <a name="TouchMode"></a>
500 * <h3>Touch Mode</h3>
501 * <p>
502 * When a user is navigating a user interface via directional keys such as a D-pad, it is
503 * necessary to give focus to actionable items such as buttons so the user can see
504 * what will take input. If the device has touch capabilities, however, and the user
505 * begins interacting with the interface by touching it, it is no longer necessary to
506 * always highlight, or give focus to, a particular view. This motivates a mode
507 * for interaction named 'touch mode'.
508 * </p>
509 * <p>
510 * For a touch capable device, once the user touches the screen, the device
511 * will enter touch mode. From this point onward, only views for which
512 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
513 * Other views that are touchable, like buttons, will not take focus when touched; they will
514 * only fire the on click listeners.
515 * </p>
516 * <p>
517 * Any time a user hits a directional key, such as a D-pad direction, the view device will
518 * exit touch mode, and find a view to take focus, so that the user may resume interacting
519 * with the user interface without touching the screen again.
520 * </p>
521 * <p>
522 * The touch mode state is maintained across {@link android.app.Activity}s. Call
523 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
524 * </p>
525 *
526 * <a name="Scrolling"></a>
527 * <h3>Scrolling</h3>
528 * <p>
529 * The framework provides basic support for views that wish to internally
530 * scroll their content. This includes keeping track of the X and Y scroll
531 * offset as well as mechanisms for drawing scrollbars. See
Joe Malin32736f02011-01-19 16:14:20 -0800532 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
Mike Cleronf116bf82009-09-27 19:14:12 -0700533 * {@link #awakenScrollBars()} for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800534 * </p>
535 *
536 * <a name="Tags"></a>
537 * <h3>Tags</h3>
538 * <p>
539 * Unlike IDs, tags are not used to identify views. Tags are essentially an
540 * extra piece of information that can be associated with a view. They are most
541 * often used as a convenience to store data related to views in the views
542 * themselves rather than by putting them in a separate structure.
543 * </p>
544 *
Chet Haasecb150fe2012-05-03 15:15:05 -0700545 * <a name="Properties"></a>
546 * <h3>Properties</h3>
547 * <p>
548 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
549 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
550 * available both in the {@link Property} form as well as in similarly-named setter/getter
551 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
552 * be used to set persistent state associated with these rendering-related properties on the view.
553 * The properties and methods can also be used in conjunction with
554 * {@link android.animation.Animator Animator}-based animations, described more in the
555 * <a href="#Animation">Animation</a> section.
556 * </p>
557 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800558 * <a name="Animation"></a>
559 * <h3>Animation</h3>
560 * <p>
Chet Haasecb150fe2012-05-03 15:15:05 -0700561 * Starting with Android 3.0, the preferred way of animating views is to use the
562 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
563 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
564 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
565 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
566 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
567 * makes animating these View properties particularly easy and efficient.
568 * </p>
569 * <p>
570 * Alternatively, you can use the pre-3.0 animation classes to animate how Views are rendered.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800571 * You can attach an {@link Animation} object to a view using
572 * {@link #setAnimation(Animation)} or
573 * {@link #startAnimation(Animation)}. The animation can alter the scale,
574 * rotation, translation and alpha of a view over time. If the animation is
575 * attached to a view that has children, the animation will affect the entire
576 * subtree rooted by that node. When an animation is started, the framework will
577 * take care of redrawing the appropriate views until the animation completes.
578 * </p>
579 *
Jeff Brown85a31762010-09-01 17:01:00 -0700580 * <a name="Security"></a>
581 * <h3>Security</h3>
582 * <p>
583 * Sometimes it is essential that an application be able to verify that an action
584 * is being performed with the full knowledge and consent of the user, such as
585 * granting a permission request, making a purchase or clicking on an advertisement.
586 * Unfortunately, a malicious application could try to spoof the user into
587 * performing these actions, unaware, by concealing the intended purpose of the view.
588 * As a remedy, the framework offers a touch filtering mechanism that can be used to
589 * improve the security of views that provide access to sensitive functionality.
590 * </p><p>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700591 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
Jeff Brown49ed71d2010-12-06 17:13:33 -0800592 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
Jeff Brown85a31762010-09-01 17:01:00 -0700593 * will discard touches that are received whenever the view's window is obscured by
594 * another visible window. As a result, the view will not receive touches whenever a
595 * toast, dialog or other window appears above the view's window.
596 * </p><p>
597 * For more fine-grained control over security, consider overriding the
Romain Guy5c22a8c2011-05-13 11:48:45 -0700598 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
599 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
Jeff Brown85a31762010-09-01 17:01:00 -0700600 * </p>
601 *
Romain Guy171c5922011-01-06 10:04:23 -0800602 * @attr ref android.R.styleable#View_alpha
Romain Guyd6a463a2009-05-21 23:10:10 -0700603 * @attr ref android.R.styleable#View_background
604 * @attr ref android.R.styleable#View_clickable
605 * @attr ref android.R.styleable#View_contentDescription
606 * @attr ref android.R.styleable#View_drawingCacheQuality
607 * @attr ref android.R.styleable#View_duplicateParentState
608 * @attr ref android.R.styleable#View_id
Romain Guy1ef3fdb2011-09-09 15:30:30 -0700609 * @attr ref android.R.styleable#View_requiresFadingEdge
Philip Milne6c8ea062012-04-03 17:38:43 -0700610 * @attr ref android.R.styleable#View_fadeScrollbars
Romain Guyd6a463a2009-05-21 23:10:10 -0700611 * @attr ref android.R.styleable#View_fadingEdgeLength
Jeff Brown85a31762010-09-01 17:01:00 -0700612 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800613 * @attr ref android.R.styleable#View_fitsSystemWindows
Romain Guyd6a463a2009-05-21 23:10:10 -0700614 * @attr ref android.R.styleable#View_isScrollContainer
615 * @attr ref android.R.styleable#View_focusable
616 * @attr ref android.R.styleable#View_focusableInTouchMode
617 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
618 * @attr ref android.R.styleable#View_keepScreenOn
Romain Guy171c5922011-01-06 10:04:23 -0800619 * @attr ref android.R.styleable#View_layerType
Romain Guyd6a463a2009-05-21 23:10:10 -0700620 * @attr ref android.R.styleable#View_longClickable
621 * @attr ref android.R.styleable#View_minHeight
622 * @attr ref android.R.styleable#View_minWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800623 * @attr ref android.R.styleable#View_nextFocusDown
624 * @attr ref android.R.styleable#View_nextFocusLeft
625 * @attr ref android.R.styleable#View_nextFocusRight
626 * @attr ref android.R.styleable#View_nextFocusUp
Romain Guyd6a463a2009-05-21 23:10:10 -0700627 * @attr ref android.R.styleable#View_onClick
628 * @attr ref android.R.styleable#View_padding
629 * @attr ref android.R.styleable#View_paddingBottom
630 * @attr ref android.R.styleable#View_paddingLeft
631 * @attr ref android.R.styleable#View_paddingRight
632 * @attr ref android.R.styleable#View_paddingTop
Fabrice Di Meglio101d5aa2012-02-16 18:36:06 -0800633 * @attr ref android.R.styleable#View_paddingStart
634 * @attr ref android.R.styleable#View_paddingEnd
Romain Guyd6a463a2009-05-21 23:10:10 -0700635 * @attr ref android.R.styleable#View_saveEnabled
Chet Haase73066682010-11-29 15:55:32 -0800636 * @attr ref android.R.styleable#View_rotation
637 * @attr ref android.R.styleable#View_rotationX
638 * @attr ref android.R.styleable#View_rotationY
639 * @attr ref android.R.styleable#View_scaleX
640 * @attr ref android.R.styleable#View_scaleY
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800641 * @attr ref android.R.styleable#View_scrollX
642 * @attr ref android.R.styleable#View_scrollY
Romain Guyd6a463a2009-05-21 23:10:10 -0700643 * @attr ref android.R.styleable#View_scrollbarSize
644 * @attr ref android.R.styleable#View_scrollbarStyle
645 * @attr ref android.R.styleable#View_scrollbars
Mike Cleronf116bf82009-09-27 19:14:12 -0700646 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
647 * @attr ref android.R.styleable#View_scrollbarFadeDuration
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800648 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
649 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800650 * @attr ref android.R.styleable#View_scrollbarThumbVertical
651 * @attr ref android.R.styleable#View_scrollbarTrackVertical
652 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
653 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
Romain Guyd6a463a2009-05-21 23:10:10 -0700654 * @attr ref android.R.styleable#View_soundEffectsEnabled
655 * @attr ref android.R.styleable#View_tag
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -0700656 * @attr ref android.R.styleable#View_textAlignment
Chet Haase73066682010-11-29 15:55:32 -0800657 * @attr ref android.R.styleable#View_transformPivotX
658 * @attr ref android.R.styleable#View_transformPivotY
659 * @attr ref android.R.styleable#View_translationX
660 * @attr ref android.R.styleable#View_translationY
Romain Guyd6a463a2009-05-21 23:10:10 -0700661 * @attr ref android.R.styleable#View_visibility
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800662 *
663 * @see android.view.ViewGroup
664 */
Fabrice Di Megliob03b4342012-06-04 12:55:30 -0700665public class View implements Drawable.Callback, KeyEvent.Callback,
Adam Powell8fc54f92011-09-07 16:40:45 -0700666 AccessibilityEventSource {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800667 private static final boolean DBG = false;
668
669 /**
670 * The logging tag used by this class with android.util.Log.
671 */
672 protected static final String VIEW_LOG_TAG = "View";
673
674 /**
Guang Zhu0d607fb2012-05-11 19:34:56 -0700675 * When set to true, apps will draw debugging information about their layouts.
Romain Guy4b8c4f82012-04-27 15:48:35 -0700676 *
677 * @hide
678 */
679 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
680
681 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800682 * Used to mark a View that has no ID.
683 */
684 public static final int NO_ID = -1;
685
686 /**
687 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
688 * calling setFlags.
689 */
690 private static final int NOT_FOCUSABLE = 0x00000000;
691
692 /**
693 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
694 * setFlags.
695 */
696 private static final int FOCUSABLE = 0x00000001;
697
698 /**
699 * Mask for use with setFlags indicating bits used for focus.
700 */
701 private static final int FOCUSABLE_MASK = 0x00000001;
702
703 /**
704 * This view will adjust its padding to fit sytem windows (e.g. status bar)
705 */
706 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
707
708 /**
Scott Main812634c22011-07-27 13:22:35 -0700709 * This view is visible.
710 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
711 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800712 */
713 public static final int VISIBLE = 0x00000000;
714
715 /**
716 * This view is invisible, but it still takes up space for layout purposes.
Scott Main812634c22011-07-27 13:22:35 -0700717 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
718 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800719 */
720 public static final int INVISIBLE = 0x00000004;
721
722 /**
723 * This view is invisible, and it doesn't take any space for layout
Scott Main812634c22011-07-27 13:22:35 -0700724 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
725 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800726 */
727 public static final int GONE = 0x00000008;
728
729 /**
730 * Mask for use with setFlags indicating bits used for visibility.
731 * {@hide}
732 */
733 static final int VISIBILITY_MASK = 0x0000000C;
734
735 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
736
737 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -0700738 * This view is enabled. Interpretation varies by subclass.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800739 * Use with ENABLED_MASK when calling setFlags.
740 * {@hide}
741 */
742 static final int ENABLED = 0x00000000;
743
744 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -0700745 * This view is disabled. Interpretation varies by subclass.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800746 * Use with ENABLED_MASK when calling setFlags.
747 * {@hide}
748 */
749 static final int DISABLED = 0x00000020;
750
751 /**
752 * Mask for use with setFlags indicating bits used for indicating whether
753 * this view is enabled
754 * {@hide}
755 */
756 static final int ENABLED_MASK = 0x00000020;
757
758 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -0700759 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
760 * called and further optimizations will be performed. It is okay to have
761 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800762 * {@hide}
763 */
764 static final int WILL_NOT_DRAW = 0x00000080;
765
766 /**
767 * Mask for use with setFlags indicating bits used for indicating whether
768 * this view is will draw
769 * {@hide}
770 */
771 static final int DRAW_MASK = 0x00000080;
772
773 /**
774 * <p>This view doesn't show scrollbars.</p>
775 * {@hide}
776 */
777 static final int SCROLLBARS_NONE = 0x00000000;
778
779 /**
780 * <p>This view shows horizontal scrollbars.</p>
781 * {@hide}
782 */
783 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
784
785 /**
786 * <p>This view shows vertical scrollbars.</p>
787 * {@hide}
788 */
789 static final int SCROLLBARS_VERTICAL = 0x00000200;
790
791 /**
792 * <p>Mask for use with setFlags indicating bits used for indicating which
793 * scrollbars are enabled.</p>
794 * {@hide}
795 */
796 static final int SCROLLBARS_MASK = 0x00000300;
797
Jeff Brown85a31762010-09-01 17:01:00 -0700798 /**
799 * Indicates that the view should filter touches when its window is obscured.
800 * Refer to the class comments for more information about this security feature.
801 * {@hide}
802 */
803 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
804
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700805 /**
806 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
807 * that they are optional and should be skipped if the window has
808 * requested system UI flags that ignore those insets for layout.
809 */
810 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800811
812 /**
813 * <p>This view doesn't show fading edges.</p>
814 * {@hide}
815 */
816 static final int FADING_EDGE_NONE = 0x00000000;
817
818 /**
819 * <p>This view shows horizontal fading edges.</p>
820 * {@hide}
821 */
822 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
823
824 /**
825 * <p>This view shows vertical fading edges.</p>
826 * {@hide}
827 */
828 static final int FADING_EDGE_VERTICAL = 0x00002000;
829
830 /**
831 * <p>Mask for use with setFlags indicating bits used for indicating which
832 * fading edges are enabled.</p>
833 * {@hide}
834 */
835 static final int FADING_EDGE_MASK = 0x00003000;
836
837 /**
838 * <p>Indicates this view can be clicked. When clickable, a View reacts
839 * to clicks by notifying the OnClickListener.<p>
840 * {@hide}
841 */
842 static final int CLICKABLE = 0x00004000;
843
844 /**
845 * <p>Indicates this view is caching its drawing into a bitmap.</p>
846 * {@hide}
847 */
848 static final int DRAWING_CACHE_ENABLED = 0x00008000;
849
850 /**
851 * <p>Indicates that no icicle should be saved for this view.<p>
852 * {@hide}
853 */
854 static final int SAVE_DISABLED = 0x000010000;
855
856 /**
857 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
858 * property.</p>
859 * {@hide}
860 */
861 static final int SAVE_DISABLED_MASK = 0x000010000;
862
863 /**
864 * <p>Indicates that no drawing cache should ever be created for this view.<p>
865 * {@hide}
866 */
867 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
868
869 /**
870 * <p>Indicates this view can take / keep focus when int touch mode.</p>
871 * {@hide}
872 */
873 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
874
875 /**
876 * <p>Enables low quality mode for the drawing cache.</p>
877 */
878 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
879
880 /**
881 * <p>Enables high quality mode for the drawing cache.</p>
882 */
883 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
884
885 /**
886 * <p>Enables automatic quality mode for the drawing cache.</p>
887 */
888 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
889
890 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
891 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
892 };
893
894 /**
895 * <p>Mask for use with setFlags indicating bits used for the cache
896 * quality property.</p>
897 * {@hide}
898 */
899 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
900
901 /**
902 * <p>
903 * Indicates this view can be long clicked. When long clickable, a View
904 * reacts to long clicks by notifying the OnLongClickListener or showing a
905 * context menu.
906 * </p>
907 * {@hide}
908 */
909 static final int LONG_CLICKABLE = 0x00200000;
910
911 /**
912 * <p>Indicates that this view gets its drawable states from its direct parent
913 * and ignores its original internal states.</p>
914 *
915 * @hide
916 */
917 static final int DUPLICATE_PARENT_STATE = 0x00400000;
918
919 /**
920 * The scrollbar style to display the scrollbars inside the content area,
921 * without increasing the padding. The scrollbars will be overlaid with
922 * translucency on the view's content.
923 */
924 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
925
926 /**
927 * The scrollbar style to display the scrollbars inside the padded area,
928 * increasing the padding of the view. The scrollbars will not overlap the
929 * content area of the view.
930 */
931 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
932
933 /**
934 * The scrollbar style to display the scrollbars at the edge of the view,
935 * without increasing the padding. The scrollbars will be overlaid with
936 * translucency.
937 */
938 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
939
940 /**
941 * The scrollbar style to display the scrollbars at the edge of the view,
942 * increasing the padding of the view. The scrollbars will only overlap the
943 * background, if any.
944 */
945 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
946
947 /**
948 * Mask to check if the scrollbar style is overlay or inset.
949 * {@hide}
950 */
951 static final int SCROLLBARS_INSET_MASK = 0x01000000;
952
953 /**
954 * Mask to check if the scrollbar style is inside or outside.
955 * {@hide}
956 */
957 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
958
959 /**
960 * Mask for scrollbar style.
961 * {@hide}
962 */
963 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
964
965 /**
966 * View flag indicating that the screen should remain on while the
967 * window containing this view is visible to the user. This effectively
968 * takes care of automatically setting the WindowManager's
969 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
970 */
971 public static final int KEEP_SCREEN_ON = 0x04000000;
972
973 /**
974 * View flag indicating whether this view should have sound effects enabled
975 * for events such as clicking and touching.
976 */
977 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
978
979 /**
980 * View flag indicating whether this view should have haptic feedback
981 * enabled for events such as long presses.
982 */
983 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
984
985 /**
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700986 * <p>Indicates that the view hierarchy should stop saving state when
987 * it reaches this view. If state saving is initiated immediately at
988 * the view, it will be allowed.
989 * {@hide}
990 */
991 static final int PARENT_SAVE_DISABLED = 0x20000000;
992
993 /**
994 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
995 * {@hide}
996 */
997 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
998
999 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07001000 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1001 * should add all focusable Views regardless if they are focusable in touch mode.
1002 */
1003 public static final int FOCUSABLES_ALL = 0x00000000;
1004
1005 /**
1006 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1007 * should add only Views focusable in touch mode.
1008 */
1009 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1010
1011 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001012 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001013 * item.
1014 */
1015 public static final int FOCUS_BACKWARD = 0x00000001;
1016
1017 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001018 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001019 * item.
1020 */
1021 public static final int FOCUS_FORWARD = 0x00000002;
1022
1023 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001024 * Use with {@link #focusSearch(int)}. Move focus to the left.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001025 */
1026 public static final int FOCUS_LEFT = 0x00000011;
1027
1028 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001029 * Use with {@link #focusSearch(int)}. Move focus up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001030 */
1031 public static final int FOCUS_UP = 0x00000021;
1032
1033 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001034 * Use with {@link #focusSearch(int)}. Move focus to the right.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001035 */
1036 public static final int FOCUS_RIGHT = 0x00000042;
1037
1038 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001039 * Use with {@link #focusSearch(int)}. Move focus down.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001040 */
1041 public static final int FOCUS_DOWN = 0x00000082;
1042
Svetoslav Ganov42138042012-03-20 11:51:39 -07001043 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08001044 * Bits of {@link #getMeasuredWidthAndState()} and
1045 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1046 */
1047 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1048
1049 /**
1050 * Bits of {@link #getMeasuredWidthAndState()} and
1051 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1052 */
1053 public static final int MEASURED_STATE_MASK = 0xff000000;
1054
1055 /**
1056 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1057 * for functions that combine both width and height into a single int,
1058 * such as {@link #getMeasuredState()} and the childState argument of
1059 * {@link #resolveSizeAndState(int, int, int)}.
1060 */
1061 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1062
1063 /**
1064 * Bit of {@link #getMeasuredWidthAndState()} and
1065 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1066 * is smaller that the space the view would like to have.
1067 */
1068 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1069
1070 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001071 * Base View state sets
1072 */
1073 // Singles
1074 /**
1075 * Indicates the view has no states set. States are used with
1076 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1077 * view depending on its state.
1078 *
1079 * @see android.graphics.drawable.Drawable
1080 * @see #getDrawableState()
1081 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001082 protected static final int[] EMPTY_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001083 /**
1084 * Indicates the view is enabled. States are used with
1085 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1086 * view depending on its state.
1087 *
1088 * @see android.graphics.drawable.Drawable
1089 * @see #getDrawableState()
1090 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001091 protected static final int[] ENABLED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001092 /**
1093 * Indicates the view is focused. States are used with
1094 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1095 * view depending on its state.
1096 *
1097 * @see android.graphics.drawable.Drawable
1098 * @see #getDrawableState()
1099 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001100 protected static final int[] FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001101 /**
1102 * Indicates the view is selected. States are used with
1103 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1104 * view depending on its state.
1105 *
1106 * @see android.graphics.drawable.Drawable
1107 * @see #getDrawableState()
1108 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001109 protected static final int[] SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001110 /**
1111 * Indicates the view is pressed. States are used with
1112 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1113 * view depending on its state.
1114 *
1115 * @see android.graphics.drawable.Drawable
1116 * @see #getDrawableState()
1117 * @hide
1118 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001119 protected static final int[] PRESSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001120 /**
1121 * Indicates the view's window has focus. States are used with
1122 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1123 * view depending on its state.
1124 *
1125 * @see android.graphics.drawable.Drawable
1126 * @see #getDrawableState()
1127 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001128 protected static final int[] WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001129 // Doubles
1130 /**
1131 * Indicates the view is enabled and has the focus.
1132 *
1133 * @see #ENABLED_STATE_SET
1134 * @see #FOCUSED_STATE_SET
1135 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001136 protected static final int[] ENABLED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001137 /**
1138 * Indicates the view is enabled and selected.
1139 *
1140 * @see #ENABLED_STATE_SET
1141 * @see #SELECTED_STATE_SET
1142 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001143 protected static final int[] ENABLED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001144 /**
1145 * Indicates the view is enabled and that its window has focus.
1146 *
1147 * @see #ENABLED_STATE_SET
1148 * @see #WINDOW_FOCUSED_STATE_SET
1149 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001150 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001151 /**
1152 * Indicates the view is focused and selected.
1153 *
1154 * @see #FOCUSED_STATE_SET
1155 * @see #SELECTED_STATE_SET
1156 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001157 protected static final int[] FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001158 /**
1159 * Indicates the view has the focus and that its window has the focus.
1160 *
1161 * @see #FOCUSED_STATE_SET
1162 * @see #WINDOW_FOCUSED_STATE_SET
1163 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001164 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001165 /**
1166 * Indicates the view is selected and that its window has the focus.
1167 *
1168 * @see #SELECTED_STATE_SET
1169 * @see #WINDOW_FOCUSED_STATE_SET
1170 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001171 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001172 // Triples
1173 /**
1174 * Indicates the view is enabled, focused and selected.
1175 *
1176 * @see #ENABLED_STATE_SET
1177 * @see #FOCUSED_STATE_SET
1178 * @see #SELECTED_STATE_SET
1179 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001180 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001181 /**
1182 * Indicates the view is enabled, focused and its window has the focus.
1183 *
1184 * @see #ENABLED_STATE_SET
1185 * @see #FOCUSED_STATE_SET
1186 * @see #WINDOW_FOCUSED_STATE_SET
1187 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001188 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001189 /**
1190 * Indicates the view is enabled, selected and its window has the focus.
1191 *
1192 * @see #ENABLED_STATE_SET
1193 * @see #SELECTED_STATE_SET
1194 * @see #WINDOW_FOCUSED_STATE_SET
1195 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001196 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001197 /**
1198 * Indicates the view is focused, selected and its window has the focus.
1199 *
1200 * @see #FOCUSED_STATE_SET
1201 * @see #SELECTED_STATE_SET
1202 * @see #WINDOW_FOCUSED_STATE_SET
1203 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001204 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001205 /**
1206 * Indicates the view is enabled, focused, selected and its window
1207 * has the focus.
1208 *
1209 * @see #ENABLED_STATE_SET
1210 * @see #FOCUSED_STATE_SET
1211 * @see #SELECTED_STATE_SET
1212 * @see #WINDOW_FOCUSED_STATE_SET
1213 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001214 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001215 /**
1216 * Indicates the view is pressed and its window has the focus.
1217 *
1218 * @see #PRESSED_STATE_SET
1219 * @see #WINDOW_FOCUSED_STATE_SET
1220 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001221 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001222 /**
1223 * Indicates the view is pressed and selected.
1224 *
1225 * @see #PRESSED_STATE_SET
1226 * @see #SELECTED_STATE_SET
1227 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001228 protected static final int[] PRESSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001229 /**
1230 * Indicates the view is pressed, selected and its window has the focus.
1231 *
1232 * @see #PRESSED_STATE_SET
1233 * @see #SELECTED_STATE_SET
1234 * @see #WINDOW_FOCUSED_STATE_SET
1235 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001236 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001237 /**
1238 * Indicates the view is pressed and focused.
1239 *
1240 * @see #PRESSED_STATE_SET
1241 * @see #FOCUSED_STATE_SET
1242 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001243 protected static final int[] PRESSED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001244 /**
1245 * Indicates the view is pressed, focused and its window has the focus.
1246 *
1247 * @see #PRESSED_STATE_SET
1248 * @see #FOCUSED_STATE_SET
1249 * @see #WINDOW_FOCUSED_STATE_SET
1250 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001251 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001252 /**
1253 * Indicates the view is pressed, focused and selected.
1254 *
1255 * @see #PRESSED_STATE_SET
1256 * @see #SELECTED_STATE_SET
1257 * @see #FOCUSED_STATE_SET
1258 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001259 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001260 /**
1261 * Indicates the view is pressed, focused, selected and its window has the focus.
1262 *
1263 * @see #PRESSED_STATE_SET
1264 * @see #FOCUSED_STATE_SET
1265 * @see #SELECTED_STATE_SET
1266 * @see #WINDOW_FOCUSED_STATE_SET
1267 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001268 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001269 /**
1270 * Indicates the view is pressed and enabled.
1271 *
1272 * @see #PRESSED_STATE_SET
1273 * @see #ENABLED_STATE_SET
1274 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001275 protected static final int[] PRESSED_ENABLED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001276 /**
1277 * Indicates the view is pressed, enabled and its window has the focus.
1278 *
1279 * @see #PRESSED_STATE_SET
1280 * @see #ENABLED_STATE_SET
1281 * @see #WINDOW_FOCUSED_STATE_SET
1282 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001283 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001284 /**
1285 * Indicates the view is pressed, enabled and selected.
1286 *
1287 * @see #PRESSED_STATE_SET
1288 * @see #ENABLED_STATE_SET
1289 * @see #SELECTED_STATE_SET
1290 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001291 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001292 /**
1293 * Indicates the view is pressed, enabled, selected and its window has the
1294 * focus.
1295 *
1296 * @see #PRESSED_STATE_SET
1297 * @see #ENABLED_STATE_SET
1298 * @see #SELECTED_STATE_SET
1299 * @see #WINDOW_FOCUSED_STATE_SET
1300 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001301 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001302 /**
1303 * Indicates the view is pressed, enabled and focused.
1304 *
1305 * @see #PRESSED_STATE_SET
1306 * @see #ENABLED_STATE_SET
1307 * @see #FOCUSED_STATE_SET
1308 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001309 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001310 /**
1311 * Indicates the view is pressed, enabled, focused and its window has the
1312 * focus.
1313 *
1314 * @see #PRESSED_STATE_SET
1315 * @see #ENABLED_STATE_SET
1316 * @see #FOCUSED_STATE_SET
1317 * @see #WINDOW_FOCUSED_STATE_SET
1318 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001319 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001320 /**
1321 * Indicates the view is pressed, enabled, focused and selected.
1322 *
1323 * @see #PRESSED_STATE_SET
1324 * @see #ENABLED_STATE_SET
1325 * @see #SELECTED_STATE_SET
1326 * @see #FOCUSED_STATE_SET
1327 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001328 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001329 /**
1330 * Indicates the view is pressed, enabled, focused, selected and its window
1331 * has the focus.
1332 *
1333 * @see #PRESSED_STATE_SET
1334 * @see #ENABLED_STATE_SET
1335 * @see #SELECTED_STATE_SET
1336 * @see #FOCUSED_STATE_SET
1337 * @see #WINDOW_FOCUSED_STATE_SET
1338 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001339 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001340
1341 /**
1342 * The order here is very important to {@link #getDrawableState()}
1343 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001344 private static final int[][] VIEW_STATE_SETS;
1345
Romain Guyb051e892010-09-28 19:09:36 -07001346 static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1347 static final int VIEW_STATE_SELECTED = 1 << 1;
1348 static final int VIEW_STATE_FOCUSED = 1 << 2;
1349 static final int VIEW_STATE_ENABLED = 1 << 3;
1350 static final int VIEW_STATE_PRESSED = 1 << 4;
1351 static final int VIEW_STATE_ACTIVATED = 1 << 5;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001352 static final int VIEW_STATE_ACCELERATED = 1 << 6;
PY Laligandc33d8d49e2011-03-14 18:22:53 -07001353 static final int VIEW_STATE_HOVERED = 1 << 7;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001354 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1355 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001356
1357 static final int[] VIEW_STATE_IDS = new int[] {
1358 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED,
1359 R.attr.state_selected, VIEW_STATE_SELECTED,
1360 R.attr.state_focused, VIEW_STATE_FOCUSED,
1361 R.attr.state_enabled, VIEW_STATE_ENABLED,
1362 R.attr.state_pressed, VIEW_STATE_PRESSED,
1363 R.attr.state_activated, VIEW_STATE_ACTIVATED,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001364 R.attr.state_accelerated, VIEW_STATE_ACCELERATED,
PY Laligandc33d8d49e2011-03-14 18:22:53 -07001365 R.attr.state_hovered, VIEW_STATE_HOVERED,
Christopher Tate3d4bf172011-03-28 16:16:46 -07001366 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT,
Svetoslav Ganov42138042012-03-20 11:51:39 -07001367 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001368 };
1369
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001370 static {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001371 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1372 throw new IllegalStateException(
1373 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1374 }
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001375 int[] orderedIds = new int[VIEW_STATE_IDS.length];
Romain Guyb051e892010-09-28 19:09:36 -07001376 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001377 int viewState = R.styleable.ViewDrawableStates[i];
Romain Guyb051e892010-09-28 19:09:36 -07001378 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001379 if (VIEW_STATE_IDS[j] == viewState) {
Romain Guyb051e892010-09-28 19:09:36 -07001380 orderedIds[i * 2] = viewState;
1381 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001382 }
1383 }
1384 }
Romain Guyb051e892010-09-28 19:09:36 -07001385 final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1386 VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1387 for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001388 int numBits = Integer.bitCount(i);
1389 int[] set = new int[numBits];
1390 int pos = 0;
Romain Guyb051e892010-09-28 19:09:36 -07001391 for (int j = 0; j < orderedIds.length; j += 2) {
1392 if ((i & orderedIds[j+1]) != 0) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001393 set[pos++] = orderedIds[j];
1394 }
1395 }
1396 VIEW_STATE_SETS[i] = set;
1397 }
1398
1399 EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1400 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1401 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1402 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1403 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1404 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1405 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1406 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1407 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1408 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1409 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1410 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1411 | VIEW_STATE_FOCUSED];
1412 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1413 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1414 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1415 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1416 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1417 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1418 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1419 | VIEW_STATE_ENABLED];
1420 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1421 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1422 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1423 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1424 | VIEW_STATE_ENABLED];
1425 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1426 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1427 | VIEW_STATE_ENABLED];
1428 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1429 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1430 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1431
1432 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1433 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1434 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1435 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1436 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1437 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1438 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1439 | VIEW_STATE_PRESSED];
1440 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1441 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1442 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1443 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1444 | VIEW_STATE_PRESSED];
1445 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1446 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1447 | VIEW_STATE_PRESSED];
1448 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1449 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1450 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1451 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1452 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1453 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1454 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1455 | VIEW_STATE_PRESSED];
1456 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1457 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1458 | VIEW_STATE_PRESSED];
1459 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1460 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1461 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1462 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1463 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1464 | VIEW_STATE_PRESSED];
1465 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1466 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1467 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1468 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1469 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1470 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1471 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1472 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1473 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1474 | VIEW_STATE_PRESSED];
1475 }
1476
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001477 /**
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07001478 * Accessibility event types that are dispatched for text population.
1479 */
1480 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1481 AccessibilityEvent.TYPE_VIEW_CLICKED
1482 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1483 | AccessibilityEvent.TYPE_VIEW_SELECTED
1484 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1485 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1486 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
Svetoslav Ganov9920f4f2011-10-07 18:39:11 -07001487 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
Svetoslav Ganov84dd52e2011-11-18 10:24:00 -08001488 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
Svetoslav Ganov42138042012-03-20 11:51:39 -07001489 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001490 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1491 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07001492
1493 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001494 * Temporary Rect currently for use in setBackground(). This will probably
1495 * be extended in the future to hold our own class with more than just
1496 * a Rect. :)
1497 */
1498 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
Romain Guyd90a3312009-05-06 14:54:28 -07001499
1500 /**
1501 * Map used to store views' tags.
1502 */
Adam Powell7db82ac2011-09-22 19:44:04 -07001503 private SparseArray<Object> mKeyedTags;
Romain Guyd90a3312009-05-06 14:54:28 -07001504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001505 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001506 * The next available accessiiblity id.
1507 */
1508 private static int sNextAccessibilityViewId;
1509
1510 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001511 * The animation currently associated with this view.
1512 * @hide
1513 */
1514 protected Animation mCurrentAnimation = null;
1515
1516 /**
1517 * Width as measured during measure pass.
1518 * {@hide}
1519 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001520 @ViewDebug.ExportedProperty(category = "measurement")
Romain Guy676b1732011-02-14 14:45:33 -08001521 int mMeasuredWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001522
1523 /**
1524 * Height as measured during measure pass.
1525 * {@hide}
1526 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001527 @ViewDebug.ExportedProperty(category = "measurement")
Romain Guy676b1732011-02-14 14:45:33 -08001528 int mMeasuredHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001529
1530 /**
Chet Haasedaf98e92011-01-10 14:10:36 -08001531 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1532 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1533 * its display list. This flag, used only when hw accelerated, allows us to clear the
1534 * flag while retaining this information until it's needed (at getDisplayList() time and
1535 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1536 *
1537 * {@hide}
1538 */
1539 boolean mRecreateDisplayList = false;
1540
1541 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001542 * The view's identifier.
1543 * {@hide}
1544 *
1545 * @see #setId(int)
1546 * @see #getId()
1547 */
1548 @ViewDebug.ExportedProperty(resolveId = true)
1549 int mID = NO_ID;
1550
1551 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07001552 * The stable ID of this view for accessibility purposes.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001553 */
1554 int mAccessibilityViewId = NO_ID;
1555
1556 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001557 * @hide
1558 */
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07001559 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001560
1561 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001562 * The view's tag.
1563 * {@hide}
1564 *
1565 * @see #setTag(Object)
1566 * @see #getTag()
1567 */
1568 protected Object mTag;
1569
1570 // for mPrivateFlags:
1571 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001572 static final int PFLAG_WANTS_FOCUS = 0x00000001;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001573 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001574 static final int PFLAG_FOCUSED = 0x00000002;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001575 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001576 static final int PFLAG_SELECTED = 0x00000004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001577 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001578 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001579 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001580 static final int PFLAG_HAS_BOUNDS = 0x00000010;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001581 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001582 static final int PFLAG_DRAWN = 0x00000020;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001583 /**
1584 * When this flag is set, this view is running an animation on behalf of its
1585 * children and should therefore not cancel invalidate requests, even if they
1586 * lie outside of this view's bounds.
1587 *
1588 * {@hide}
1589 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001590 static final int PFLAG_DRAW_ANIMATION = 0x00000040;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001591 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001592 static final int PFLAG_SKIP_DRAW = 0x00000080;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001593 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001594 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001595 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001596 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001597 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001598 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001599 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001600 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001601 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001602 static final int PFLAG_FORCE_LAYOUT = 0x00001000;
Konstantin Lopyrevc6dc4572010-08-06 15:01:52 -07001603 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001604 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001605
Dianne Hackborn4702a852012-08-17 15:18:29 -07001606 private static final int PFLAG_PRESSED = 0x00004000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001607
1608 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001609 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001610 /**
1611 * Flag used to indicate that this view should be drawn once more (and only once
1612 * more) after its animation has completed.
1613 * {@hide}
1614 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001615 static final int PFLAG_ANIMATION_STARTED = 0x00010000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001616
Dianne Hackborn4702a852012-08-17 15:18:29 -07001617 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001618
1619 /**
1620 * Indicates that the View returned true when onSetAlpha() was called and that
1621 * the alpha must be restored.
1622 * {@hide}
1623 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001624 static final int PFLAG_ALPHA_SET = 0x00040000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001625
1626 /**
1627 * Set by {@link #setScrollContainer(boolean)}.
1628 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001629 static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001630
1631 /**
1632 * Set by {@link #setScrollContainer(boolean)}.
1633 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001634 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001635
1636 /**
Romain Guy809a7f62009-05-14 15:44:42 -07001637 * View flag indicating whether this view was invalidated (fully or partially.)
1638 *
1639 * @hide
1640 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001641 static final int PFLAG_DIRTY = 0x00200000;
Romain Guy809a7f62009-05-14 15:44:42 -07001642
1643 /**
1644 * View flag indicating whether this view was invalidated by an opaque
1645 * invalidate request.
1646 *
1647 * @hide
1648 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001649 static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
Romain Guy809a7f62009-05-14 15:44:42 -07001650
1651 /**
Dianne Hackborn4702a852012-08-17 15:18:29 -07001652 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
Romain Guy809a7f62009-05-14 15:44:42 -07001653 *
1654 * @hide
1655 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001656 static final int PFLAG_DIRTY_MASK = 0x00600000;
Romain Guy809a7f62009-05-14 15:44:42 -07001657
1658 /**
Romain Guy8f1344f52009-05-15 16:03:59 -07001659 * Indicates whether the background is opaque.
1660 *
1661 * @hide
1662 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001663 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001664
1665 /**
1666 * Indicates whether the scrollbars are opaque.
1667 *
1668 * @hide
1669 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001670 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001671
1672 /**
1673 * Indicates whether the view is opaque.
1674 *
1675 * @hide
1676 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001677 static final int PFLAG_OPAQUE_MASK = 0x01800000;
Joe Malin32736f02011-01-19 16:14:20 -08001678
Adam Powelle14579b2009-12-16 18:39:52 -08001679 /**
1680 * Indicates a prepressed state;
1681 * the short time between ACTION_DOWN and recognizing
1682 * a 'real' press. Prepressed is used to recognize quick taps
1683 * even when they are shorter than ViewConfiguration.getTapTimeout().
Joe Malin32736f02011-01-19 16:14:20 -08001684 *
Adam Powelle14579b2009-12-16 18:39:52 -08001685 * @hide
1686 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001687 private static final int PFLAG_PREPRESSED = 0x02000000;
Joe Malin32736f02011-01-19 16:14:20 -08001688
Adam Powellc9fbaab2010-02-16 17:16:19 -08001689 /**
Romain Guy8afa5152010-02-26 11:56:30 -08001690 * Indicates whether the view is temporarily detached.
1691 *
1692 * @hide
1693 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001694 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
Joe Malin32736f02011-01-19 16:14:20 -08001695
Adam Powell8568c3a2010-04-19 14:26:11 -07001696 /**
1697 * Indicates that we should awaken scroll bars once attached
Joe Malin32736f02011-01-19 16:14:20 -08001698 *
Adam Powell8568c3a2010-04-19 14:26:11 -07001699 * @hide
1700 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001701 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001702
1703 /**
Jeff Browna032cc02011-03-07 16:56:21 -08001704 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1705 * @hide
1706 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001707 private static final int PFLAG_HOVERED = 0x10000000;
Jeff Browna032cc02011-03-07 16:56:21 -08001708
1709 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07001710 * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1711 * for transform operations
1712 *
1713 * @hide
1714 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001715 private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
Chet Haasefd2b0022010-08-06 13:08:56 -07001716
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001717 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001718 static final int PFLAG_ACTIVATED = 0x40000000;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001719
Chet Haasefd2b0022010-08-06 13:08:56 -07001720 /**
Chet Haasedaf98e92011-01-10 14:10:36 -08001721 * Indicates that this view was specifically invalidated, not just dirtied because some
1722 * child view was invalidated. The flag is used to determine when we need to recreate
1723 * a view's display list (as opposed to just returning a reference to its existing
1724 * display list).
1725 *
1726 * @hide
1727 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001728 static final int PFLAG_INVALIDATED = 0x80000000;
Chet Haasedaf98e92011-01-10 14:10:36 -08001729
Christopher Tate3d4bf172011-03-28 16:16:46 -07001730 /* Masks for mPrivateFlags2 */
1731
1732 /**
1733 * Indicates that this view has reported that it can accept the current drag's content.
1734 * Cleared when the drag operation concludes.
1735 * @hide
1736 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001737 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001738
1739 /**
1740 * Indicates that this view is currently directly under the drag location in a
1741 * drag-and-drop operation involving content that it can accept. Cleared when
1742 * the drag exits the view, or when the drag operation concludes.
1743 * @hide
1744 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001745 static final int PFLAG2_DRAG_HOVERED = 0x00000002;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001746
Cibu Johny86666632010-02-22 13:01:02 -08001747 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001748 * Horizontal layout direction of this view is from Left to Right.
1749 * Use with {@link #setLayoutDirection}.
Cibu Johny86666632010-02-22 13:01:02 -08001750 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001751 public static final int LAYOUT_DIRECTION_LTR = 0;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001752
1753 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001754 * Horizontal layout direction of this view is from Right to Left.
1755 * Use with {@link #setLayoutDirection}.
1756 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001757 public static final int LAYOUT_DIRECTION_RTL = 1;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001758
1759 /**
1760 * Horizontal layout direction of this view is inherited from its parent.
1761 * Use with {@link #setLayoutDirection}.
1762 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001763 public static final int LAYOUT_DIRECTION_INHERIT = 2;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001764
1765 /**
1766 * Horizontal layout direction of this view is from deduced from the default language
1767 * script for the locale. Use with {@link #setLayoutDirection}.
1768 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001769 public static final int LAYOUT_DIRECTION_LOCALE = 3;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001770
1771 /**
1772 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001773 * @hide
1774 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001775 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001776
1777 /**
1778 * Mask for use with private flags indicating bits used for horizontal layout direction.
1779 * @hide
1780 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001781 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001782
1783 /**
1784 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1785 * right-to-left direction.
1786 * @hide
1787 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001788 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001789
1790 /**
1791 * Indicates whether the view horizontal layout direction has been resolved.
1792 * @hide
1793 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001794 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001795
1796 /**
1797 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1798 * @hide
1799 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001800 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1801 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001802
1803 /*
1804 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1805 * flag value.
1806 * @hide
1807 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001808 private static final int[] LAYOUT_DIRECTION_FLAGS = {
1809 LAYOUT_DIRECTION_LTR,
1810 LAYOUT_DIRECTION_RTL,
1811 LAYOUT_DIRECTION_INHERIT,
1812 LAYOUT_DIRECTION_LOCALE
1813 };
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001814
1815 /**
1816 * Default horizontal layout direction.
1817 * @hide
1818 */
1819 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001820
Adam Powell539ee872012-02-03 19:00:49 -08001821 /**
1822 * Indicates that the view is tracking some sort of transient state
1823 * that the app should not need to be aware of, but that the framework
1824 * should take special care to preserve.
1825 *
1826 * @hide
1827 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001828 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100;
Adam Powell539ee872012-02-03 19:00:49 -08001829
1830
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001831 /**
1832 * Text direction is inherited thru {@link ViewGroup}
1833 */
1834 public static final int TEXT_DIRECTION_INHERIT = 0;
1835
1836 /**
1837 * Text direction is using "first strong algorithm". The first strong directional character
1838 * determines the paragraph direction. If there is no strong directional character, the
1839 * paragraph direction is the view's resolved layout direction.
1840 */
1841 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1842
1843 /**
1844 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1845 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1846 * If there are neither, the paragraph direction is the view's resolved layout direction.
1847 */
1848 public static final int TEXT_DIRECTION_ANY_RTL = 2;
1849
1850 /**
1851 * Text direction is forced to LTR.
1852 */
1853 public static final int TEXT_DIRECTION_LTR = 3;
1854
1855 /**
1856 * Text direction is forced to RTL.
1857 */
1858 public static final int TEXT_DIRECTION_RTL = 4;
1859
1860 /**
1861 * Text direction is coming from the system Locale.
1862 */
1863 public static final int TEXT_DIRECTION_LOCALE = 5;
1864
1865 /**
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001866 * Default text direction is inherited
1867 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001868 public static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001869
1870 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001871 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1872 * @hide
1873 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001874 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001875
1876 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001877 * Mask for use with private flags indicating bits used for text direction.
1878 * @hide
1879 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001880 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1881 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001882
1883 /**
1884 * Array of text direction flags for mapping attribute "textDirection" to correct
1885 * flag value.
1886 * @hide
1887 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001888 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1889 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1890 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1891 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1892 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1893 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1894 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001895 };
1896
1897 /**
1898 * Indicates whether the view text direction has been resolved.
1899 * @hide
1900 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001901 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
1902 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001903
1904 /**
1905 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1906 * @hide
1907 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001908 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001909
1910 /**
1911 * Mask for use with private flags indicating bits used for resolved text direction.
1912 * @hide
1913 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001914 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
1915 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001916
1917 /**
1918 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1919 * @hide
1920 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001921 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
1922 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001923
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001924 /*
1925 * Default text alignment. The text alignment of this View is inherited from its parent.
1926 * Use with {@link #setTextAlignment(int)}
1927 */
1928 public static final int TEXT_ALIGNMENT_INHERIT = 0;
1929
1930 /**
1931 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1932 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1933 *
1934 * Use with {@link #setTextAlignment(int)}
1935 */
1936 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1937
1938 /**
1939 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
1940 *
1941 * Use with {@link #setTextAlignment(int)}
1942 */
1943 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
1944
1945 /**
1946 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
1947 *
1948 * Use with {@link #setTextAlignment(int)}
1949 */
1950 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
1951
1952 /**
1953 * Center the paragraph, e.g. ALIGN_CENTER.
1954 *
1955 * Use with {@link #setTextAlignment(int)}
1956 */
1957 public static final int TEXT_ALIGNMENT_CENTER = 4;
1958
1959 /**
1960 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
1961 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
1962 *
1963 * Use with {@link #setTextAlignment(int)}
1964 */
1965 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
1966
1967 /**
1968 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
1969 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
1970 *
1971 * Use with {@link #setTextAlignment(int)}
1972 */
1973 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
1974
1975 /**
1976 * Default text alignment is inherited
1977 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001978 public static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001979
1980 /**
1981 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1982 * @hide
1983 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001984 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001985
1986 /**
1987 * Mask for use with private flags indicating bits used for text alignment.
1988 * @hide
1989 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001990 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001991
1992 /**
1993 * Array of text direction flags for mapping attribute "textAlignment" to correct
1994 * flag value.
1995 * @hide
1996 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001997 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
1998 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
1999 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2000 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2001 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2002 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2003 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2004 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002005 };
2006
2007 /**
2008 * Indicates whether the view text alignment has been resolved.
2009 * @hide
2010 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002011 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002012
2013 /**
2014 * Bit shift to get the resolved text alignment.
2015 * @hide
2016 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002017 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002018
2019 /**
2020 * Mask for use with private flags indicating bits used for text alignment.
2021 * @hide
2022 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002023 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2024 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002025
2026 /**
2027 * Indicates whether if the view text alignment has been resolved to gravity
2028 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002029 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2030 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002031
Svetoslav Ganov42138042012-03-20 11:51:39 -07002032 // Accessiblity constants for mPrivateFlags2
2033
2034 /**
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07002035 * Shift for the bits in {@link #mPrivateFlags2} related to the
2036 * "importantForAccessibility" attribute.
Svetoslav Ganov42138042012-03-20 11:51:39 -07002037 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002038 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002039
2040 /**
2041 * Automatically determine whether a view is important for accessibility.
2042 */
2043 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2044
2045 /**
2046 * The view is important for accessibility.
2047 */
2048 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2049
2050 /**
2051 * The view is not important for accessibility.
2052 */
2053 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2054
2055 /**
2056 * The default whether the view is important for accessiblity.
2057 */
2058 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2059
2060 /**
2061 * Mask for obtainig the bits which specify how to determine
2062 * whether a view is important for accessibility.
2063 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002064 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
Svetoslav Ganov42138042012-03-20 11:51:39 -07002065 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
Dianne Hackborn4702a852012-08-17 15:18:29 -07002066 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002067
2068 /**
2069 * Flag indicating whether a view has accessibility focus.
2070 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002071 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002072
2073 /**
2074 * Flag indicating whether a view state for accessibility has changed.
2075 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002076 static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
2077 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07002078
Chet Haaseafd5c3e2012-05-10 13:21:10 -07002079 /**
Chet Haase1a3ab172012-05-11 08:41:20 -07002080 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2081 * is used to check whether later changes to the view's transform should invalidate the
2082 * view to force the quickReject test to run again.
2083 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002084 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
Chet Haase1a3ab172012-05-11 08:41:20 -07002085
Adam Powell0090f202012-08-07 17:15:30 -07002086 /**
2087 * Flag indicating that start/end padding has been resolved into left/right padding
2088 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2089 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2090 * during measurement. In some special cases this is required such as when an adapter-based
2091 * view measures prospective children without attaching them to a window.
2092 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002093 static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
Adam Powell0090f202012-08-07 17:15:30 -07002094
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07002095 // There are a couple of flags left in mPrivateFlags2
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07002096
Christopher Tate3d4bf172011-03-28 16:16:46 -07002097 /* End of masks for mPrivateFlags2 */
2098
Chet Haase21433372012-06-05 07:54:09 -07002099 /* Masks for mPrivateFlags3 */
2100
2101 /**
2102 * Flag indicating that view has a transform animation set on it. This is used to track whether
2103 * an animation is cleared between successive frames, in order to tell the associated
2104 * DisplayList to clear its animation matrix.
2105 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002106 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
Chet Haase21433372012-06-05 07:54:09 -07002107
2108 /**
2109 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2110 * animation is cleared between successive frames, in order to tell the associated
2111 * DisplayList to restore its alpha value.
2112 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002113 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
Chet Haase21433372012-06-05 07:54:09 -07002114
2115
2116 /* End of masks for mPrivateFlags3 */
2117
Dianne Hackborn4702a852012-08-17 15:18:29 -07002118 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
Christopher Tate3d4bf172011-03-28 16:16:46 -07002119
Chet Haasedaf98e92011-01-10 14:10:36 -08002120 /**
Adam Powell637d3372010-08-25 14:37:03 -07002121 * Always allow a user to over-scroll this view, provided it is a
2122 * view that can scroll.
2123 *
2124 * @see #getOverScrollMode()
2125 * @see #setOverScrollMode(int)
2126 */
2127 public static final int OVER_SCROLL_ALWAYS = 0;
2128
2129 /**
2130 * Allow a user to over-scroll this view only if the content is large
2131 * enough to meaningfully scroll, provided it is a view that can scroll.
2132 *
2133 * @see #getOverScrollMode()
2134 * @see #setOverScrollMode(int)
2135 */
2136 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2137
2138 /**
2139 * Never allow a user to over-scroll this view.
2140 *
2141 * @see #getOverScrollMode()
2142 * @see #setOverScrollMode(int)
2143 */
2144 public static final int OVER_SCROLL_NEVER = 2;
2145
2146 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002147 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2148 * requested the system UI (status bar) to be visible (the default).
Joe Onorato664644d2011-01-23 17:53:23 -08002149 *
Joe Malin32736f02011-01-19 16:14:20 -08002150 * @see #setSystemUiVisibility(int)
Joe Onorato664644d2011-01-23 17:53:23 -08002151 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002152 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002153
2154 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002155 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2156 * system UI to enter an unobtrusive "low profile" mode.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002157 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002158 * <p>This is for use in games, book readers, video players, or any other
Philip Milne6c8ea062012-04-03 17:38:43 -07002159 * "immersive" application where the usual system chrome is deemed too distracting.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002160 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002161 * <p>In low profile mode, the status bar and/or navigation icons may dim.
Joe Onorato664644d2011-01-23 17:53:23 -08002162 *
Joe Malin32736f02011-01-19 16:14:20 -08002163 * @see #setSystemUiVisibility(int)
Joe Onorato664644d2011-01-23 17:53:23 -08002164 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002165 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2166
2167 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002168 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2169 * system navigation be temporarily hidden.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002170 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002171 * <p>This is an even less obtrusive state than that called for by
Daniel Sandler60ee2562011-07-22 12:34:33 -04002172 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2173 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2174 * those to disappear. This is useful (in conjunction with the
Philip Milne6c8ea062012-04-03 17:38:43 -07002175 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
Daniel Sandler60ee2562011-07-22 12:34:33 -04002176 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2177 * window flags) for displaying content using every last pixel on the display.
2178 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002179 * <p>There is a limitation: because navigation controls are so important, the least user
2180 * interaction will cause them to reappear immediately. When this happens, both
2181 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2182 * so that both elements reappear at the same time.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002183 *
2184 * @see #setSystemUiVisibility(int)
2185 */
2186 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2187
2188 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002189 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2190 * into the normal fullscreen mode so that its content can take over the screen
2191 * while still allowing the user to interact with the application.
2192 *
2193 * <p>This has the same visual effect as
2194 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2195 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2196 * meaning that non-critical screen decorations (such as the status bar) will be
2197 * hidden while the user is in the View's window, focusing the experience on
2198 * that content. Unlike the window flag, if you are using ActionBar in
2199 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2200 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2201 * hide the action bar.
2202 *
2203 * <p>This approach to going fullscreen is best used over the window flag when
2204 * it is a transient state -- that is, the application does this at certain
2205 * points in its user interaction where it wants to allow the user to focus
2206 * on content, but not as a continuous state. For situations where the application
2207 * would like to simply stay full screen the entire time (such as a game that
2208 * wants to take over the screen), the
2209 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2210 * is usually a better approach. The state set here will be removed by the system
2211 * in various situations (such as the user moving to another application) like
2212 * the other system UI states.
2213 *
2214 * <p>When using this flag, the application should provide some easy facility
2215 * for the user to go out of it. A common example would be in an e-book
2216 * reader, where tapping on the screen brings back whatever screen and UI
2217 * decorations that had been hidden while the user was immersed in reading
2218 * the book.
2219 *
2220 * @see #setSystemUiVisibility(int)
2221 */
2222 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2223
2224 /**
2225 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2226 * flags, we would like a stable view of the content insets given to
2227 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2228 * will always represent the worst case that the application can expect
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002229 * as a continuous state. In the stock Android UI this is the space for
2230 * the system bar, nav bar, and status bar, but not more transient elements
2231 * such as an input method.
2232 *
2233 * The stable layout your UI sees is based on the system UI modes you can
2234 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2235 * then you will get a stable layout for changes of the
2236 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2237 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2238 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2239 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2240 * with a stable layout. (Note that you should avoid using
2241 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2242 *
Jeff Smitha45746e2012-07-19 14:19:24 -05002243 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002244 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2245 * then a hidden status bar will be considered a "stable" state for purposes
2246 * here. This allows your UI to continually hide the status bar, while still
2247 * using the system UI flags to hide the action bar while still retaining
2248 * a stable layout. Note that changing the window fullscreen flag will never
2249 * provide a stable layout for a clean transition.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002250 *
2251 * <p>If you are using ActionBar in
2252 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2253 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2254 * insets it adds to those given to the application.
2255 */
2256 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2257
2258 /**
2259 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2260 * to be layed out as if it has requested
2261 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2262 * allows it to avoid artifacts when switching in and out of that mode, at
2263 * the expense that some of its user interface may be covered by screen
2264 * decorations when they are shown. You can perform layout of your inner
2265 * UI elements to account for the navagation system UI through the
2266 * {@link #fitSystemWindows(Rect)} method.
2267 */
2268 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2269
2270 /**
2271 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2272 * to be layed out as if it has requested
2273 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
2274 * allows it to avoid artifacts when switching in and out of that mode, at
2275 * the expense that some of its user interface may be covered by screen
2276 * decorations when they are shown. You can perform layout of your inner
2277 * UI elements to account for non-fullscreen system UI through the
2278 * {@link #fitSystemWindows(Rect)} method.
2279 */
2280 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2281
2282 /**
Daniel Sandler60ee2562011-07-22 12:34:33 -04002283 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2284 */
2285 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2286
2287 /**
2288 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2289 */
2290 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
Joe Onorato664644d2011-01-23 17:53:23 -08002291
2292 /**
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002293 * @hide
2294 *
2295 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2296 * out of the public fields to keep the undefined bits out of the developer's way.
2297 *
2298 * Flag to make the status bar not expandable. Unless you also
2299 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2300 */
2301 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2302
2303 /**
2304 * @hide
2305 *
2306 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2307 * out of the public fields to keep the undefined bits out of the developer's way.
2308 *
2309 * Flag to hide notification icons and scrolling ticker text.
2310 */
2311 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2312
2313 /**
2314 * @hide
2315 *
2316 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2317 * out of the public fields to keep the undefined bits out of the developer's way.
2318 *
2319 * Flag to disable incoming notification alerts. This will not block
2320 * icons, but it will block sound, vibrating and other visual or aural notifications.
2321 */
2322 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2323
2324 /**
2325 * @hide
2326 *
2327 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2328 * out of the public fields to keep the undefined bits out of the developer's way.
2329 *
2330 * Flag to hide only the scrolling ticker. Note that
2331 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2332 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2333 */
2334 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2335
2336 /**
2337 * @hide
2338 *
2339 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2340 * out of the public fields to keep the undefined bits out of the developer's way.
2341 *
2342 * Flag to hide the center system info area.
2343 */
2344 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2345
2346 /**
2347 * @hide
2348 *
2349 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2350 * out of the public fields to keep the undefined bits out of the developer's way.
2351 *
Daniel Sandlerdba93562011-10-06 16:39:58 -04002352 * Flag to hide only the home button. Don't use this
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002353 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2354 */
Daniel Sandlerdba93562011-10-06 16:39:58 -04002355 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002356
2357 /**
2358 * @hide
2359 *
2360 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2361 * out of the public fields to keep the undefined bits out of the developer's way.
2362 *
Daniel Sandlerdba93562011-10-06 16:39:58 -04002363 * Flag to hide only the back button. Don't use this
Joe Onorato6478adc2011-01-27 21:15:01 -08002364 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2365 */
2366 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2367
2368 /**
2369 * @hide
2370 *
2371 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2372 * out of the public fields to keep the undefined bits out of the developer's way.
2373 *
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002374 * Flag to hide only the clock. You might use this if your activity has
2375 * its own clock making the status bar's clock redundant.
2376 */
Joe Onorato6478adc2011-01-27 21:15:01 -08002377 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2378
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002379 /**
2380 * @hide
Daniel Sandlerdba93562011-10-06 16:39:58 -04002381 *
2382 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2383 * out of the public fields to keep the undefined bits out of the developer's way.
2384 *
2385 * Flag to hide only the recent apps button. Don't use this
2386 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2387 */
2388 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2389
2390 /**
2391 * @hide
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002392 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002393 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002394
2395 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -07002396 * These are the system UI flags that can be cleared by events outside
2397 * of an application. Currently this is just the ability to tap on the
2398 * screen while hiding the navigation bar to have it return.
2399 * @hide
2400 */
2401 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002402 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2403 | SYSTEM_UI_FLAG_FULLSCREEN;
2404
2405 /**
2406 * Flags that can impact the layout in relation to system UI.
2407 */
2408 public static final int SYSTEM_UI_LAYOUT_FLAGS =
2409 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2410 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
Dianne Hackborn9a230e02011-10-06 11:51:27 -07002411
2412 /**
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07002413 * Find views that render the specified text.
2414 *
2415 * @see #findViewsWithText(ArrayList, CharSequence, int)
2416 */
2417 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2418
2419 /**
2420 * Find find views that contain the specified content description.
2421 *
2422 * @see #findViewsWithText(ArrayList, CharSequence, int)
2423 */
2424 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2425
2426 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002427 * Find views that contain {@link AccessibilityNodeProvider}. Such
2428 * a View is a root of virtual view hierarchy and may contain the searched
2429 * text. If this flag is set Views with providers are automatically
2430 * added and it is a responsibility of the client to call the APIs of
2431 * the provider to determine whether the virtual tree rooted at this View
2432 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2433 * represeting the virtual views with this text.
2434 *
2435 * @see #findViewsWithText(ArrayList, CharSequence, int)
2436 *
2437 * @hide
2438 */
2439 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2440
2441 /**
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07002442 * The undefined cursor position.
2443 */
2444 private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2445
2446 /**
Romain Guybb9908b2012-03-08 11:14:07 -08002447 * Indicates that the screen has changed state and is now off.
2448 *
2449 * @see #onScreenStateChanged(int)
2450 */
2451 public static final int SCREEN_STATE_OFF = 0x0;
2452
2453 /**
2454 * Indicates that the screen has changed state and is now on.
2455 *
Romain Guy1e3d3132012-03-08 15:55:56 -08002456 * @see #onScreenStateChanged(int)
Romain Guybb9908b2012-03-08 11:14:07 -08002457 */
2458 public static final int SCREEN_STATE_ON = 0x1;
2459
2460 /**
Adam Powell637d3372010-08-25 14:37:03 -07002461 * Controls the over-scroll mode for this view.
2462 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2463 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2464 * and {@link #OVER_SCROLL_NEVER}.
2465 */
2466 private int mOverScrollMode;
2467
2468 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002469 * The parent this view is attached to.
2470 * {@hide}
2471 *
2472 * @see #getParent()
2473 */
2474 protected ViewParent mParent;
2475
2476 /**
2477 * {@hide}
2478 */
2479 AttachInfo mAttachInfo;
2480
2481 /**
2482 * {@hide}
2483 */
Romain Guy809a7f62009-05-14 15:44:42 -07002484 @ViewDebug.ExportedProperty(flagMapping = {
Dianne Hackborn4702a852012-08-17 15:18:29 -07002485 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
Romain Guy809a7f62009-05-14 15:44:42 -07002486 name = "FORCE_LAYOUT"),
Dianne Hackborn4702a852012-08-17 15:18:29 -07002487 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
Romain Guy809a7f62009-05-14 15:44:42 -07002488 name = "LAYOUT_REQUIRED"),
Dianne Hackborn4702a852012-08-17 15:18:29 -07002489 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
Romain Guy5bcdff42009-05-14 21:27:18 -07002490 name = "DRAWING_CACHE_INVALID", outputIf = false),
Dianne Hackborn4702a852012-08-17 15:18:29 -07002491 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2492 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2493 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2494 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
Romain Guy809a7f62009-05-14 15:44:42 -07002495 })
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002496 int mPrivateFlags;
Christopher Tate3d4bf172011-03-28 16:16:46 -07002497 int mPrivateFlags2;
Chet Haase21433372012-06-05 07:54:09 -07002498 int mPrivateFlags3;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002499
2500 /**
Joe Onorato664644d2011-01-23 17:53:23 -08002501 * This view's request for the visibility of the status bar.
2502 * @hide
2503 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002504 @ViewDebug.ExportedProperty(flagMapping = {
2505 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2506 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2507 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2508 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2509 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2510 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2511 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2512 equals = SYSTEM_UI_FLAG_VISIBLE,
2513 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2514 })
Joe Onorato664644d2011-01-23 17:53:23 -08002515 int mSystemUiVisibility;
2516
2517 /**
Chet Haase563d4f22012-04-18 16:20:08 -07002518 * Reference count for transient state.
2519 * @see #setHasTransientState(boolean)
2520 */
2521 int mTransientStateCount = 0;
2522
2523 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002524 * Count of how many windows this view has been attached to.
2525 */
2526 int mWindowAttachCount;
2527
2528 /**
2529 * The layout parameters associated with this view and used by the parent
2530 * {@link android.view.ViewGroup} to determine how this view should be
2531 * laid out.
2532 * {@hide}
2533 */
2534 protected ViewGroup.LayoutParams mLayoutParams;
2535
2536 /**
2537 * The view flags hold various views states.
2538 * {@hide}
2539 */
2540 @ViewDebug.ExportedProperty
2541 int mViewFlags;
2542
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002543 static class TransformationInfo {
2544 /**
2545 * The transform matrix for the View. This transform is calculated internally
2546 * based on the rotation, scaleX, and scaleY properties. The identity matrix
2547 * is used by default. Do *not* use this variable directly; instead call
2548 * getMatrix(), which will automatically recalculate the matrix if necessary
2549 * to get the correct matrix based on the latest rotation and scale properties.
2550 */
2551 private final Matrix mMatrix = new Matrix();
Chet Haasec3aa3612010-06-17 08:50:37 -07002552
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002553 /**
2554 * The transform matrix for the View. This transform is calculated internally
2555 * based on the rotation, scaleX, and scaleY properties. The identity matrix
2556 * is used by default. Do *not* use this variable directly; instead call
2557 * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2558 * to get the correct matrix based on the latest rotation and scale properties.
2559 */
2560 private Matrix mInverseMatrix;
Chet Haasec3aa3612010-06-17 08:50:37 -07002561
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002562 /**
2563 * An internal variable that tracks whether we need to recalculate the
2564 * transform matrix, based on whether the rotation or scaleX/Y properties
2565 * have changed since the matrix was last calculated.
2566 */
2567 boolean mMatrixDirty = false;
Chet Haasec3aa3612010-06-17 08:50:37 -07002568
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002569 /**
2570 * An internal variable that tracks whether we need to recalculate the
2571 * transform matrix, based on whether the rotation or scaleX/Y properties
2572 * have changed since the matrix was last calculated.
2573 */
2574 private boolean mInverseMatrixDirty = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07002575
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002576 /**
2577 * A variable that tracks whether we need to recalculate the
2578 * transform matrix, based on whether the rotation or scaleX/Y properties
2579 * have changed since the matrix was last calculated. This variable
2580 * is only valid after a call to updateMatrix() or to a function that
2581 * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2582 */
2583 private boolean mMatrixIsIdentity = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07002584
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002585 /**
2586 * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2587 */
2588 private Camera mCamera = null;
Chet Haasefd2b0022010-08-06 13:08:56 -07002589
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002590 /**
2591 * This matrix is used when computing the matrix for 3D rotations.
2592 */
2593 private Matrix matrix3D = null;
Chet Haasefd2b0022010-08-06 13:08:56 -07002594
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002595 /**
2596 * These prev values are used to recalculate a centered pivot point when necessary. The
2597 * pivot point is only used in matrix operations (when rotation, scale, or translation are
2598 * set), so thes values are only used then as well.
2599 */
2600 private int mPrevWidth = -1;
2601 private int mPrevHeight = -1;
Philip Milne6c8ea062012-04-03 17:38:43 -07002602
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002603 /**
2604 * The degrees rotation around the vertical axis through the pivot point.
2605 */
2606 @ViewDebug.ExportedProperty
2607 float mRotationY = 0f;
2608
2609 /**
2610 * The degrees rotation around the horizontal axis through the pivot point.
2611 */
2612 @ViewDebug.ExportedProperty
2613 float mRotationX = 0f;
2614
2615 /**
2616 * The degrees rotation around the pivot point.
2617 */
2618 @ViewDebug.ExportedProperty
2619 float mRotation = 0f;
2620
2621 /**
2622 * The amount of translation of the object away from its left property (post-layout).
2623 */
2624 @ViewDebug.ExportedProperty
2625 float mTranslationX = 0f;
2626
2627 /**
2628 * The amount of translation of the object away from its top property (post-layout).
2629 */
2630 @ViewDebug.ExportedProperty
2631 float mTranslationY = 0f;
2632
2633 /**
2634 * The amount of scale in the x direction around the pivot point. A
2635 * value of 1 means no scaling is applied.
2636 */
2637 @ViewDebug.ExportedProperty
2638 float mScaleX = 1f;
2639
2640 /**
2641 * The amount of scale in the y direction around the pivot point. A
2642 * value of 1 means no scaling is applied.
2643 */
2644 @ViewDebug.ExportedProperty
2645 float mScaleY = 1f;
2646
2647 /**
Chet Haasea33de552012-02-03 16:28:24 -08002648 * The x location of the point around which the view is rotated and scaled.
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002649 */
2650 @ViewDebug.ExportedProperty
2651 float mPivotX = 0f;
2652
2653 /**
Chet Haasea33de552012-02-03 16:28:24 -08002654 * The y location of the point around which the view is rotated and scaled.
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002655 */
2656 @ViewDebug.ExportedProperty
2657 float mPivotY = 0f;
2658
2659 /**
2660 * The opacity of the View. This is a value from 0 to 1, where 0 means
2661 * completely transparent and 1 means completely opaque.
2662 */
2663 @ViewDebug.ExportedProperty
2664 float mAlpha = 1f;
2665 }
2666
2667 TransformationInfo mTransformationInfo;
Chet Haasefd2b0022010-08-06 13:08:56 -07002668
Joe Malin32736f02011-01-19 16:14:20 -08002669 private boolean mLastIsOpaque;
2670
Chet Haasefd2b0022010-08-06 13:08:56 -07002671 /**
2672 * Convenience value to check for float values that are close enough to zero to be considered
2673 * zero.
2674 */
Romain Guy2542d192010-08-18 11:47:12 -07002675 private static final float NONZERO_EPSILON = .001f;
Chet Haasefd2b0022010-08-06 13:08:56 -07002676
2677 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002678 * The distance in pixels from the left edge of this view's parent
2679 * to the left edge of this view.
2680 * {@hide}
2681 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002682 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002683 protected int mLeft;
2684 /**
2685 * The distance in pixels from the left edge of this view's parent
2686 * to the right edge of this view.
2687 * {@hide}
2688 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002689 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002690 protected int mRight;
2691 /**
2692 * The distance in pixels from the top edge of this view's parent
2693 * to the top edge of this view.
2694 * {@hide}
2695 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002696 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002697 protected int mTop;
2698 /**
2699 * The distance in pixels from the top edge of this view's parent
2700 * to the bottom edge of this view.
2701 * {@hide}
2702 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002703 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002704 protected int mBottom;
2705
2706 /**
2707 * The offset, in pixels, by which the content of this view is scrolled
2708 * horizontally.
2709 * {@hide}
2710 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002711 @ViewDebug.ExportedProperty(category = "scrolling")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002712 protected int mScrollX;
2713 /**
2714 * The offset, in pixels, by which the content of this view is scrolled
2715 * vertically.
2716 * {@hide}
2717 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002718 @ViewDebug.ExportedProperty(category = "scrolling")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002719 protected int mScrollY;
2720
2721 /**
2722 * The left padding in pixels, that is the distance in pixels between the
2723 * left edge of this view and the left edge of its content.
2724 * {@hide}
2725 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002726 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002727 protected int mPaddingLeft;
2728 /**
2729 * The right padding in pixels, that is the distance in pixels between the
2730 * right edge of this view and the right edge of its content.
2731 * {@hide}
2732 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002733 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002734 protected int mPaddingRight;
2735 /**
2736 * The top padding in pixels, that is the distance in pixels between the
2737 * top edge of this view and the top edge of its content.
2738 * {@hide}
2739 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002740 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002741 protected int mPaddingTop;
2742 /**
2743 * The bottom padding in pixels, that is the distance in pixels between the
2744 * bottom edge of this view and the bottom edge of its content.
2745 * {@hide}
2746 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002747 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002748 protected int mPaddingBottom;
2749
2750 /**
Philip Milne1557fd72012-04-04 23:41:34 -07002751 * The layout insets in pixels, that is the distance in pixels between the
2752 * visible edges of this view its bounds.
2753 */
2754 private Insets mLayoutInsets;
2755
2756 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07002757 * Briefly describes the view and is primarily used for accessibility support.
2758 */
2759 private CharSequence mContentDescription;
2760
2761 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002762 * Cache the paddingRight set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002763 *
2764 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002765 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002766 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002767 protected int mUserPaddingRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002768
2769 /**
2770 * Cache the paddingBottom set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002771 *
2772 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002773 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002774 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002775 protected int mUserPaddingBottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002776
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002777 /**
Adam Powell20232d02010-12-08 21:08:53 -08002778 * Cache the paddingLeft set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002779 *
2780 * @hide
Adam Powell20232d02010-12-08 21:08:53 -08002781 */
2782 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002783 protected int mUserPaddingLeft;
Adam Powell20232d02010-12-08 21:08:53 -08002784
2785 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07002786 * Cache the paddingStart set by the user to append to the scrollbar's size.
2787 *
2788 */
2789 @ViewDebug.ExportedProperty(category = "padding")
2790 int mUserPaddingStart;
2791
2792 /**
2793 * Cache the paddingEnd set by the user to append to the scrollbar's size.
2794 *
2795 */
2796 @ViewDebug.ExportedProperty(category = "padding")
2797 int mUserPaddingEnd;
2798
2799 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07002800 * Whether a left padding has been defined during layout inflation.
2801 *
2802 * @hide
2803 */
2804 boolean mUserPaddingLeftDefined = false;
2805
2806 /**
2807 * Whether a right padding has been defined during layout inflation.
2808 *
2809 * @hide
2810 */
2811 boolean mUserPaddingRightDefined = false;
2812
2813 /**
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07002814 * Default undefined padding
2815 */
2816 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2817
2818 /**
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002819 * @hide
2820 */
2821 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2822 /**
2823 * @hide
2824 */
2825 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002826
Philip Milne6c8ea062012-04-03 17:38:43 -07002827 private Drawable mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002828
2829 private int mBackgroundResource;
2830 private boolean mBackgroundSizeChanged;
2831
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002832 static class ListenerInfo {
2833 /**
2834 * Listener used to dispatch focus change events.
2835 * This field should be made private, so it is hidden from the SDK.
2836 * {@hide}
2837 */
2838 protected OnFocusChangeListener mOnFocusChangeListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002839
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002840 /**
2841 * Listeners for layout change events.
2842 */
2843 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
Chet Haase21cd1382010-09-01 17:42:29 -07002844
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002845 /**
2846 * Listeners for attach events.
2847 */
2848 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
Adam Powell4afd62b2011-02-18 15:02:18 -08002849
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002850 /**
2851 * Listener used to dispatch click events.
2852 * This field should be made private, so it is hidden from the SDK.
2853 * {@hide}
2854 */
2855 public OnClickListener mOnClickListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002856
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002857 /**
2858 * Listener used to dispatch long click events.
2859 * This field should be made private, so it is hidden from the SDK.
2860 * {@hide}
2861 */
2862 protected OnLongClickListener mOnLongClickListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002863
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002864 /**
2865 * Listener used to build the context menu.
2866 * This field should be made private, so it is hidden from the SDK.
2867 * {@hide}
2868 */
2869 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002870
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002871 private OnKeyListener mOnKeyListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002872
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002873 private OnTouchListener mOnTouchListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002874
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002875 private OnHoverListener mOnHoverListener;
Jeff Brown10b62902011-06-20 16:40:37 -07002876
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002877 private OnGenericMotionListener mOnGenericMotionListener;
Jeff Brown33bbfd22011-02-24 20:55:35 -08002878
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002879 private OnDragListener mOnDragListener;
Chris Tate32affef2010-10-18 15:29:21 -07002880
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002881 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2882 }
2883
2884 ListenerInfo mListenerInfo;
Joe Onorato664644d2011-01-23 17:53:23 -08002885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002886 /**
2887 * The application environment this view lives in.
2888 * This field should be made private, so it is hidden from the SDK.
2889 * {@hide}
2890 */
2891 protected Context mContext;
2892
Dianne Hackbornab0f4852011-09-12 16:59:06 -07002893 private final Resources mResources;
2894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002895 private ScrollabilityCache mScrollCache;
2896
2897 private int[] mDrawableState = null;
2898
Romain Guy0211a0a2011-02-14 16:34:59 -08002899 /**
2900 * Set to true when drawing cache is enabled and cannot be created.
Philip Milne6c8ea062012-04-03 17:38:43 -07002901 *
Romain Guy0211a0a2011-02-14 16:34:59 -08002902 * @hide
2903 */
2904 public boolean mCachingFailed;
2905
Romain Guy02890fd2010-08-06 17:58:44 -07002906 private Bitmap mDrawingCache;
2907 private Bitmap mUnscaledDrawingCache;
Romain Guy6c319ca2011-01-11 14:29:25 -08002908 private HardwareLayer mHardwareLayer;
Romain Guy65b345f2011-07-27 18:51:50 -07002909 DisplayList mDisplayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002910
2911 /**
2912 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2913 * the user may specify which view to go to next.
2914 */
2915 private int mNextFocusLeftId = View.NO_ID;
2916
2917 /**
2918 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2919 * the user may specify which view to go to next.
2920 */
2921 private int mNextFocusRightId = View.NO_ID;
2922
2923 /**
2924 * When this view has focus and the next focus is {@link #FOCUS_UP},
2925 * the user may specify which view to go to next.
2926 */
2927 private int mNextFocusUpId = View.NO_ID;
2928
2929 /**
2930 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2931 * the user may specify which view to go to next.
2932 */
2933 private int mNextFocusDownId = View.NO_ID;
2934
Jeff Brown4e6319b2010-12-13 10:36:51 -08002935 /**
2936 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2937 * the user may specify which view to go to next.
2938 */
2939 int mNextFocusForwardId = View.NO_ID;
2940
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002941 private CheckForLongPress mPendingCheckForLongPress;
Adam Powelle14579b2009-12-16 18:39:52 -08002942 private CheckForTap mPendingCheckForTap = null;
Adam Powella35d7682010-03-12 14:48:13 -08002943 private PerformClick mPerformClick;
Svetoslav Ganova0156172011-06-26 17:55:44 -07002944 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
Joe Malin32736f02011-01-19 16:14:20 -08002945
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002946 private UnsetPressedState mUnsetPressedState;
2947
2948 /**
2949 * Whether the long press's action has been invoked. The tap's action is invoked on the
2950 * up event while a long press is invoked as soon as the long press duration is reached, so
2951 * a long press could be performed before the tap is checked, in which case the tap's action
2952 * should not be invoked.
2953 */
2954 private boolean mHasPerformedLongPress;
2955
2956 /**
2957 * The minimum height of the view. We'll try our best to have the height
2958 * of this view to at least this amount.
2959 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002960 @ViewDebug.ExportedProperty(category = "measurement")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002961 private int mMinHeight;
2962
2963 /**
2964 * The minimum width of the view. We'll try our best to have the width
2965 * of this view to at least this amount.
2966 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002967 @ViewDebug.ExportedProperty(category = "measurement")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002968 private int mMinWidth;
2969
2970 /**
2971 * The delegate to handle touch events that are physically in this view
2972 * but should be handled by another view.
2973 */
2974 private TouchDelegate mTouchDelegate = null;
2975
2976 /**
2977 * Solid color to use as a background when creating the drawing cache. Enables
2978 * the cache to use 16 bit bitmaps instead of 32 bit.
2979 */
2980 private int mDrawingCacheBackgroundColor = 0;
2981
2982 /**
2983 * Special tree observer used when mAttachInfo is null.
2984 */
2985 private ViewTreeObserver mFloatingTreeObserver;
Joe Malin32736f02011-01-19 16:14:20 -08002986
Adam Powelle14579b2009-12-16 18:39:52 -08002987 /**
2988 * Cache the touch slop from the context that created the view.
2989 */
2990 private int mTouchSlop;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002991
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992 /**
Chet Haasea00f3862011-02-22 06:34:40 -08002993 * Object that handles automatic animation of view properties.
2994 */
2995 private ViewPropertyAnimator mAnimator = null;
2996
2997 /**
Christopher Tate251602f2011-01-28 17:54:12 -08002998 * Flag indicating that a drag can cross window boundaries. When
2999 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3000 * with this flag set, all visible applications will be able to participate
3001 * in the drag operation and receive the dragged content.
Christopher Tate7f9ff9d2011-02-14 17:31:13 -08003002 *
3003 * @hide
Christopher Tate02d2b3b2011-01-10 20:43:53 -08003004 */
3005 public static final int DRAG_FLAG_GLOBAL = 1;
3006
3007 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08003008 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3009 */
3010 private float mVerticalScrollFactor;
3011
3012 /**
Adam Powell20232d02010-12-08 21:08:53 -08003013 * Position of the vertical scroll bar.
3014 */
3015 private int mVerticalScrollbarPosition;
3016
3017 /**
3018 * Position the scroll bar at the default position as determined by the system.
3019 */
3020 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3021
3022 /**
3023 * Position the scroll bar along the left edge.
3024 */
3025 public static final int SCROLLBAR_POSITION_LEFT = 1;
3026
3027 /**
3028 * Position the scroll bar along the right edge.
3029 */
3030 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3031
3032 /**
Romain Guy171c5922011-01-06 10:04:23 -08003033 * Indicates that the view does not have a layer.
Joe Malin32736f02011-01-19 16:14:20 -08003034 *
3035 * @see #getLayerType()
3036 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy171c5922011-01-06 10:04:23 -08003037 * @see #LAYER_TYPE_SOFTWARE
Joe Malin32736f02011-01-19 16:14:20 -08003038 * @see #LAYER_TYPE_HARDWARE
Romain Guy171c5922011-01-06 10:04:23 -08003039 */
3040 public static final int LAYER_TYPE_NONE = 0;
3041
3042 /**
3043 * <p>Indicates that the view has a software layer. A software layer is backed
3044 * by a bitmap and causes the view to be rendered using Android's software
3045 * rendering pipeline, even if hardware acceleration is enabled.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003046 *
Romain Guy171c5922011-01-06 10:04:23 -08003047 * <p>Software layers have various usages:</p>
3048 * <p>When the application is not using hardware acceleration, a software layer
3049 * is useful to apply a specific color filter and/or blending mode and/or
3050 * translucency to a view and all its children.</p>
3051 * <p>When the application is using hardware acceleration, a software layer
3052 * is useful to render drawing primitives not supported by the hardware
3053 * accelerated pipeline. It can also be used to cache a complex view tree
3054 * into a texture and reduce the complexity of drawing operations. For instance,
3055 * when animating a complex view tree with a translation, a software layer can
3056 * be used to render the view tree only once.</p>
3057 * <p>Software layers should be avoided when the affected view tree updates
3058 * often. Every update will require to re-render the software layer, which can
3059 * potentially be slow (particularly when hardware acceleration is turned on
3060 * since the layer will have to be uploaded into a hardware texture after every
3061 * update.)</p>
Joe Malin32736f02011-01-19 16:14:20 -08003062 *
3063 * @see #getLayerType()
3064 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy171c5922011-01-06 10:04:23 -08003065 * @see #LAYER_TYPE_NONE
Joe Malin32736f02011-01-19 16:14:20 -08003066 * @see #LAYER_TYPE_HARDWARE
Romain Guy171c5922011-01-06 10:04:23 -08003067 */
3068 public static final int LAYER_TYPE_SOFTWARE = 1;
3069
3070 /**
3071 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3072 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3073 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3074 * rendering pipeline, but only if hardware acceleration is turned on for the
3075 * view hierarchy. When hardware acceleration is turned off, hardware layers
3076 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003077 *
Romain Guy171c5922011-01-06 10:04:23 -08003078 * <p>A hardware layer is useful to apply a specific color filter and/or
3079 * blending mode and/or translucency to a view and all its children.</p>
Romain Guy6c319ca2011-01-11 14:29:25 -08003080 * <p>A hardware layer can be used to cache a complex view tree into a
3081 * texture and reduce the complexity of drawing operations. For instance,
3082 * when animating a complex view tree with a translation, a hardware layer can
3083 * be used to render the view tree only once.</p>
Romain Guy171c5922011-01-06 10:04:23 -08003084 * <p>A hardware layer can also be used to increase the rendering quality when
3085 * rotation transformations are applied on a view. It can also be used to
3086 * prevent potential clipping issues when applying 3D transforms on a view.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003087 *
3088 * @see #getLayerType()
Romain Guy171c5922011-01-06 10:04:23 -08003089 * @see #setLayerType(int, android.graphics.Paint)
3090 * @see #LAYER_TYPE_NONE
3091 * @see #LAYER_TYPE_SOFTWARE
3092 */
3093 public static final int LAYER_TYPE_HARDWARE = 2;
Joe Malin32736f02011-01-19 16:14:20 -08003094
Romain Guy3aaff3a2011-01-12 14:18:47 -08003095 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3096 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3097 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3098 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3099 })
Romain Guy171c5922011-01-06 10:04:23 -08003100 int mLayerType = LAYER_TYPE_NONE;
3101 Paint mLayerPaint;
Romain Guy3a3133d2011-02-01 22:59:58 -08003102 Rect mLocalDirtyRect;
Romain Guy171c5922011-01-06 10:04:23 -08003103
3104 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07003105 * Set to true when the view is sending hover accessibility events because it
3106 * is the innermost hovered view.
3107 */
3108 private boolean mSendingHoverAccessibilityEvents;
3109
Dianne Hackborn4702a852012-08-17 15:18:29 -07003110 /**
3111 * Delegate for injecting accessiblity functionality.
3112 */
3113 AccessibilityDelegate mAccessibilityDelegate;
3114
3115 /**
3116 * Consistency verifier for debugging purposes.
3117 * @hide
3118 */
3119 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3120 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3121 new InputEventConsistencyVerifier(this, 0) : null;
3122
Adam Powella9108a22012-07-18 11:18:09 -07003123 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3124
Jeff Brown87b7f802011-06-21 18:35:45 -07003125 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003126 * Simple constructor to use when creating a view from code.
3127 *
3128 * @param context The Context the view is running in, through which it can
3129 * access the current theme, resources, etc.
3130 */
3131 public View(Context context) {
3132 mContext = context;
3133 mResources = context != null ? context.getResources() : null;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003134 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003135 // Set layout and text direction defaults
Dianne Hackborn4702a852012-08-17 15:18:29 -07003136 mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3137 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3138 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3139 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
Adam Powelle14579b2009-12-16 18:39:52 -08003140 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
Adam Powell637d3372010-08-25 14:37:03 -07003141 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003142 mUserPaddingStart = UNDEFINED_PADDING;
3143 mUserPaddingEnd = UNDEFINED_PADDING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003144 }
3145
3146 /**
3147 * Constructor that is called when inflating a view from XML. This is called
3148 * when a view is being constructed from an XML file, supplying attributes
3149 * that were specified in the XML file. This version uses a default style of
3150 * 0, so the only attribute values applied are those in the Context's Theme
3151 * and the given AttributeSet.
3152 *
3153 * <p>
3154 * The method onFinishInflate() will be called after all children have been
3155 * added.
3156 *
3157 * @param context The Context the view is running in, through which it can
3158 * access the current theme, resources, etc.
3159 * @param attrs The attributes of the XML tag that is inflating the view.
3160 * @see #View(Context, AttributeSet, int)
3161 */
3162 public View(Context context, AttributeSet attrs) {
3163 this(context, attrs, 0);
3164 }
3165
3166 /**
3167 * Perform inflation from XML and apply a class-specific base style. This
3168 * constructor of View allows subclasses to use their own base style when
3169 * they are inflating. For example, a Button class's constructor would call
3170 * this version of the super class constructor and supply
3171 * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3172 * the theme's button style to modify all of the base view attributes (in
3173 * particular its background) as well as the Button class's attributes.
3174 *
3175 * @param context The Context the view is running in, through which it can
3176 * access the current theme, resources, etc.
3177 * @param attrs The attributes of the XML tag that is inflating the view.
3178 * @param defStyle The default style to apply to this view. If 0, no style
3179 * will be applied (beyond what is included in the theme). This may
3180 * either be an attribute resource, whose value will be retrieved
3181 * from the current theme, or an explicit style resource.
3182 * @see #View(Context, AttributeSet)
3183 */
3184 public View(Context context, AttributeSet attrs, int defStyle) {
3185 this(context);
3186
3187 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3188 defStyle, 0);
3189
3190 Drawable background = null;
3191
3192 int leftPadding = -1;
3193 int topPadding = -1;
3194 int rightPadding = -1;
3195 int bottomPadding = -1;
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003196 int startPadding = UNDEFINED_PADDING;
3197 int endPadding = UNDEFINED_PADDING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003198
3199 int padding = -1;
3200
3201 int viewFlagValues = 0;
3202 int viewFlagMasks = 0;
3203
3204 boolean setScrollContainer = false;
Romain Guy8506ab42009-06-11 17:35:47 -07003205
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003206 int x = 0;
3207 int y = 0;
3208
Chet Haase73066682010-11-29 15:55:32 -08003209 float tx = 0;
3210 float ty = 0;
3211 float rotation = 0;
3212 float rotationX = 0;
3213 float rotationY = 0;
3214 float sx = 1f;
3215 float sy = 1f;
3216 boolean transformSet = false;
3217
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003218 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
Adam Powell637d3372010-08-25 14:37:03 -07003219 int overScrollMode = mOverScrollMode;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003220 boolean initializeScrollbars = false;
3221
3222 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3223
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003224 final int N = a.getIndexCount();
3225 for (int i = 0; i < N; i++) {
3226 int attr = a.getIndex(i);
3227 switch (attr) {
3228 case com.android.internal.R.styleable.View_background:
3229 background = a.getDrawable(attr);
3230 break;
3231 case com.android.internal.R.styleable.View_padding:
3232 padding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003233 mUserPaddingLeftDefined = true;
3234 mUserPaddingRightDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003235 break;
3236 case com.android.internal.R.styleable.View_paddingLeft:
3237 leftPadding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003238 mUserPaddingLeftDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003239 break;
3240 case com.android.internal.R.styleable.View_paddingTop:
3241 topPadding = a.getDimensionPixelSize(attr, -1);
3242 break;
3243 case com.android.internal.R.styleable.View_paddingRight:
3244 rightPadding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003245 mUserPaddingRightDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003246 break;
3247 case com.android.internal.R.styleable.View_paddingBottom:
3248 bottomPadding = a.getDimensionPixelSize(attr, -1);
3249 break;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003250 case com.android.internal.R.styleable.View_paddingStart:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003251 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003252 break;
3253 case com.android.internal.R.styleable.View_paddingEnd:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003254 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003255 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003256 case com.android.internal.R.styleable.View_scrollX:
3257 x = a.getDimensionPixelOffset(attr, 0);
3258 break;
3259 case com.android.internal.R.styleable.View_scrollY:
3260 y = a.getDimensionPixelOffset(attr, 0);
3261 break;
Chet Haase73066682010-11-29 15:55:32 -08003262 case com.android.internal.R.styleable.View_alpha:
3263 setAlpha(a.getFloat(attr, 1f));
3264 break;
3265 case com.android.internal.R.styleable.View_transformPivotX:
3266 setPivotX(a.getDimensionPixelOffset(attr, 0));
3267 break;
3268 case com.android.internal.R.styleable.View_transformPivotY:
3269 setPivotY(a.getDimensionPixelOffset(attr, 0));
3270 break;
3271 case com.android.internal.R.styleable.View_translationX:
3272 tx = a.getDimensionPixelOffset(attr, 0);
3273 transformSet = true;
3274 break;
3275 case com.android.internal.R.styleable.View_translationY:
3276 ty = a.getDimensionPixelOffset(attr, 0);
3277 transformSet = true;
3278 break;
3279 case com.android.internal.R.styleable.View_rotation:
3280 rotation = a.getFloat(attr, 0);
3281 transformSet = true;
3282 break;
3283 case com.android.internal.R.styleable.View_rotationX:
3284 rotationX = a.getFloat(attr, 0);
3285 transformSet = true;
3286 break;
3287 case com.android.internal.R.styleable.View_rotationY:
3288 rotationY = a.getFloat(attr, 0);
3289 transformSet = true;
3290 break;
3291 case com.android.internal.R.styleable.View_scaleX:
3292 sx = a.getFloat(attr, 1f);
3293 transformSet = true;
3294 break;
3295 case com.android.internal.R.styleable.View_scaleY:
3296 sy = a.getFloat(attr, 1f);
3297 transformSet = true;
3298 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003299 case com.android.internal.R.styleable.View_id:
3300 mID = a.getResourceId(attr, NO_ID);
3301 break;
3302 case com.android.internal.R.styleable.View_tag:
3303 mTag = a.getText(attr);
3304 break;
3305 case com.android.internal.R.styleable.View_fitsSystemWindows:
3306 if (a.getBoolean(attr, false)) {
3307 viewFlagValues |= FITS_SYSTEM_WINDOWS;
3308 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3309 }
3310 break;
3311 case com.android.internal.R.styleable.View_focusable:
3312 if (a.getBoolean(attr, false)) {
3313 viewFlagValues |= FOCUSABLE;
3314 viewFlagMasks |= FOCUSABLE_MASK;
3315 }
3316 break;
3317 case com.android.internal.R.styleable.View_focusableInTouchMode:
3318 if (a.getBoolean(attr, false)) {
3319 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3320 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3321 }
3322 break;
3323 case com.android.internal.R.styleable.View_clickable:
3324 if (a.getBoolean(attr, false)) {
3325 viewFlagValues |= CLICKABLE;
3326 viewFlagMasks |= CLICKABLE;
3327 }
3328 break;
3329 case com.android.internal.R.styleable.View_longClickable:
3330 if (a.getBoolean(attr, false)) {
3331 viewFlagValues |= LONG_CLICKABLE;
3332 viewFlagMasks |= LONG_CLICKABLE;
3333 }
3334 break;
3335 case com.android.internal.R.styleable.View_saveEnabled:
3336 if (!a.getBoolean(attr, true)) {
3337 viewFlagValues |= SAVE_DISABLED;
3338 viewFlagMasks |= SAVE_DISABLED_MASK;
3339 }
3340 break;
3341 case com.android.internal.R.styleable.View_duplicateParentState:
3342 if (a.getBoolean(attr, false)) {
3343 viewFlagValues |= DUPLICATE_PARENT_STATE;
3344 viewFlagMasks |= DUPLICATE_PARENT_STATE;
3345 }
3346 break;
3347 case com.android.internal.R.styleable.View_visibility:
3348 final int visibility = a.getInt(attr, 0);
3349 if (visibility != 0) {
3350 viewFlagValues |= VISIBILITY_FLAGS[visibility];
3351 viewFlagMasks |= VISIBILITY_MASK;
3352 }
3353 break;
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07003354 case com.android.internal.R.styleable.View_layoutDirection:
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003355 // Clear any layout direction flags (included resolved bits) already set
Dianne Hackborn4702a852012-08-17 15:18:29 -07003356 mPrivateFlags2 &= ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003357 // Set the layout direction flags depending on the value of the attribute
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07003358 final int layoutDirection = a.getInt(attr, -1);
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003359 final int value = (layoutDirection != -1) ?
3360 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
Dianne Hackborn4702a852012-08-17 15:18:29 -07003361 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -07003362 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003363 case com.android.internal.R.styleable.View_drawingCacheQuality:
3364 final int cacheQuality = a.getInt(attr, 0);
3365 if (cacheQuality != 0) {
3366 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3367 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3368 }
3369 break;
svetoslavganov75986cf2009-05-14 22:28:01 -07003370 case com.android.internal.R.styleable.View_contentDescription:
Svetoslav Ganove47957a2012-06-05 14:46:50 -07003371 setContentDescription(a.getString(attr));
svetoslavganov75986cf2009-05-14 22:28:01 -07003372 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003373 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3374 if (!a.getBoolean(attr, true)) {
3375 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3376 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3377 }
Karl Rosaen61ab2702009-06-23 11:10:25 -07003378 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003379 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3380 if (!a.getBoolean(attr, true)) {
3381 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3382 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3383 }
Karl Rosaen61ab2702009-06-23 11:10:25 -07003384 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003385 case R.styleable.View_scrollbars:
3386 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3387 if (scrollbars != SCROLLBARS_NONE) {
3388 viewFlagValues |= scrollbars;
3389 viewFlagMasks |= SCROLLBARS_MASK;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003390 initializeScrollbars = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003391 }
3392 break;
Romain Guy2a9fa892011-09-28 16:50:02 -07003393 //noinspection deprecation
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003394 case R.styleable.View_fadingEdge:
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003395 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
Romain Guy1ef3fdb2011-09-09 15:30:30 -07003396 // Ignore the attribute starting with ICS
3397 break;
3398 }
3399 // With builds < ICS, fall through and apply fading edges
3400 case R.styleable.View_requiresFadingEdge:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003401 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3402 if (fadingEdge != FADING_EDGE_NONE) {
3403 viewFlagValues |= fadingEdge;
3404 viewFlagMasks |= FADING_EDGE_MASK;
3405 initializeFadingEdge(a);
3406 }
3407 break;
3408 case R.styleable.View_scrollbarStyle:
3409 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3410 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3411 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3412 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3413 }
3414 break;
3415 case R.styleable.View_isScrollContainer:
3416 setScrollContainer = true;
3417 if (a.getBoolean(attr, false)) {
3418 setScrollContainer(true);
3419 }
3420 break;
3421 case com.android.internal.R.styleable.View_keepScreenOn:
3422 if (a.getBoolean(attr, false)) {
3423 viewFlagValues |= KEEP_SCREEN_ON;
3424 viewFlagMasks |= KEEP_SCREEN_ON;
3425 }
3426 break;
Jeff Brown85a31762010-09-01 17:01:00 -07003427 case R.styleable.View_filterTouchesWhenObscured:
3428 if (a.getBoolean(attr, false)) {
3429 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3430 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3431 }
3432 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003433 case R.styleable.View_nextFocusLeft:
3434 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3435 break;
3436 case R.styleable.View_nextFocusRight:
3437 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3438 break;
3439 case R.styleable.View_nextFocusUp:
3440 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3441 break;
3442 case R.styleable.View_nextFocusDown:
3443 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3444 break;
Jeff Brown4e6319b2010-12-13 10:36:51 -08003445 case R.styleable.View_nextFocusForward:
3446 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3447 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003448 case R.styleable.View_minWidth:
3449 mMinWidth = a.getDimensionPixelSize(attr, 0);
3450 break;
3451 case R.styleable.View_minHeight:
3452 mMinHeight = a.getDimensionPixelSize(attr, 0);
3453 break;
Romain Guy9a817362009-05-01 10:57:14 -07003454 case R.styleable.View_onClick:
Romain Guy870e09f2009-07-06 16:35:25 -07003455 if (context.isRestricted()) {
Joe Malin32736f02011-01-19 16:14:20 -08003456 throw new IllegalStateException("The android:onClick attribute cannot "
Romain Guy870e09f2009-07-06 16:35:25 -07003457 + "be used within a restricted context");
3458 }
3459
Romain Guy9a817362009-05-01 10:57:14 -07003460 final String handlerName = a.getString(attr);
3461 if (handlerName != null) {
3462 setOnClickListener(new OnClickListener() {
3463 private Method mHandler;
3464
3465 public void onClick(View v) {
3466 if (mHandler == null) {
3467 try {
3468 mHandler = getContext().getClass().getMethod(handlerName,
3469 View.class);
3470 } catch (NoSuchMethodException e) {
Joe Onorato42e14d72010-03-11 14:51:17 -08003471 int id = getId();
3472 String idText = id == NO_ID ? "" : " with id '"
3473 + getContext().getResources().getResourceEntryName(
3474 id) + "'";
Romain Guy9a817362009-05-01 10:57:14 -07003475 throw new IllegalStateException("Could not find a method " +
Joe Onorato42e14d72010-03-11 14:51:17 -08003476 handlerName + "(View) in the activity "
3477 + getContext().getClass() + " for onClick handler"
3478 + " on view " + View.this.getClass() + idText, e);
Romain Guy9a817362009-05-01 10:57:14 -07003479 }
3480 }
3481
3482 try {
3483 mHandler.invoke(getContext(), View.this);
3484 } catch (IllegalAccessException e) {
3485 throw new IllegalStateException("Could not execute non "
3486 + "public method of the activity", e);
3487 } catch (InvocationTargetException e) {
3488 throw new IllegalStateException("Could not execute "
3489 + "method of the activity", e);
3490 }
3491 }
3492 });
3493 }
3494 break;
Adam Powell637d3372010-08-25 14:37:03 -07003495 case R.styleable.View_overScrollMode:
3496 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3497 break;
Adam Powell20232d02010-12-08 21:08:53 -08003498 case R.styleable.View_verticalScrollbarPosition:
3499 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3500 break;
Romain Guy171c5922011-01-06 10:04:23 -08003501 case R.styleable.View_layerType:
3502 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3503 break;
Fabrice Di Meglio22268862011-06-27 18:13:18 -07003504 case R.styleable.View_textDirection:
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003505 // Clear any text direction flag already set
Dianne Hackborn4702a852012-08-17 15:18:29 -07003506 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003507 // Set the text direction flags depending on the value of the attribute
3508 final int textDirection = a.getInt(attr, -1);
3509 if (textDirection != -1) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07003510 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003511 }
Fabrice Di Meglio22268862011-06-27 18:13:18 -07003512 break;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003513 case R.styleable.View_textAlignment:
3514 // Clear any text alignment flag already set
Dianne Hackborn4702a852012-08-17 15:18:29 -07003515 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003516 // Set the text alignment flag depending on the value of the attribute
3517 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
Dianne Hackborn4702a852012-08-17 15:18:29 -07003518 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003519 break;
Svetoslav Ganov42138042012-03-20 11:51:39 -07003520 case R.styleable.View_importantForAccessibility:
3521 setImportantForAccessibility(a.getInt(attr,
3522 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
Svetoslav Ganov86783472012-06-06 21:12:20 -07003523 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003524 }
3525 }
3526
Adam Powell637d3372010-08-25 14:37:03 -07003527 setOverScrollMode(overScrollMode);
3528
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003529 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3530 // the resolved layout direction). Those cached values will be used later during padding
3531 // resolution.
Fabrice Di Megliof9e36502011-06-21 18:41:48 -07003532 mUserPaddingStart = startPadding;
3533 mUserPaddingEnd = endPadding;
3534
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003535 if (background != null) {
3536 setBackground(background);
3537 }
Fabrice Di Meglio509708d2012-03-06 15:41:11 -08003538
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003539 if (padding >= 0) {
3540 leftPadding = padding;
3541 topPadding = padding;
3542 rightPadding = padding;
3543 bottomPadding = padding;
3544 }
3545
3546 // If the user specified the padding (either with android:padding or
3547 // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3548 // use the default padding or the padding from the background drawable
3549 // (stored at this point in mPadding*)
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003550 internalSetPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003551 topPadding >= 0 ? topPadding : mPaddingTop,
3552 rightPadding >= 0 ? rightPadding : mPaddingRight,
3553 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3554
3555 if (viewFlagMasks != 0) {
3556 setFlags(viewFlagValues, viewFlagMasks);
3557 }
3558
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003559 if (initializeScrollbars) {
3560 initializeScrollbars(a);
3561 }
3562
3563 a.recycle();
3564
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003565 // Needs to be called after mViewFlags is set
3566 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3567 recomputePadding();
3568 }
3569
3570 if (x != 0 || y != 0) {
3571 scrollTo(x, y);
3572 }
3573
Chet Haase73066682010-11-29 15:55:32 -08003574 if (transformSet) {
3575 setTranslationX(tx);
3576 setTranslationY(ty);
3577 setRotation(rotation);
3578 setRotationX(rotationX);
3579 setRotationY(rotationY);
3580 setScaleX(sx);
3581 setScaleY(sy);
3582 }
3583
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003584 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3585 setScrollContainer(true);
3586 }
Romain Guy8f1344f52009-05-15 16:03:59 -07003587
3588 computeOpaqueFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003589 }
3590
3591 /**
3592 * Non-public constructor for use in testing
3593 */
3594 View() {
Dianne Hackbornab0f4852011-09-12 16:59:06 -07003595 mResources = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003596 }
3597
Dianne Hackborn4702a852012-08-17 15:18:29 -07003598 public String toString() {
3599 StringBuilder out = new StringBuilder(128);
3600 out.append(getClass().getName());
3601 out.append('{');
3602 out.append(Integer.toHexString(System.identityHashCode(this)));
3603 out.append(' ');
3604 switch (mViewFlags&VISIBILITY_MASK) {
3605 case VISIBLE: out.append('V'); break;
3606 case INVISIBLE: out.append('I'); break;
3607 case GONE: out.append('G'); break;
3608 default: out.append('.'); break;
3609 }
3610 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
3611 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
3612 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
3613 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
3614 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
3615 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
3616 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
3617 out.append(' ');
3618 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
3619 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
3620 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
3621 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
3622 out.append('p');
3623 } else {
3624 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
3625 }
3626 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
3627 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
3628 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
3629 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
3630 out.append(' ');
3631 out.append(mLeft);
3632 out.append(',');
3633 out.append(mTop);
3634 out.append('-');
3635 out.append(mRight);
3636 out.append(',');
3637 out.append(mBottom);
3638 final int id = getId();
3639 if (id != NO_ID) {
3640 out.append(" #");
3641 out.append(Integer.toHexString(id));
3642 final Resources r = mResources;
3643 if (id != 0 && r != null) {
3644 try {
3645 String pkgname;
3646 switch (id&0xff000000) {
3647 case 0x7f000000:
3648 pkgname="app";
3649 break;
3650 case 0x01000000:
3651 pkgname="android";
3652 break;
3653 default:
3654 pkgname = r.getResourcePackageName(id);
3655 break;
3656 }
3657 String typename = r.getResourceTypeName(id);
3658 String entryname = r.getResourceEntryName(id);
3659 out.append(" ");
3660 out.append(pkgname);
3661 out.append(":");
3662 out.append(typename);
3663 out.append("/");
3664 out.append(entryname);
3665 } catch (Resources.NotFoundException e) {
3666 }
3667 }
3668 }
3669 out.append("}");
3670 return out.toString();
3671 }
3672
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003673 /**
3674 * <p>
3675 * Initializes the fading edges from a given set of styled attributes. This
3676 * method should be called by subclasses that need fading edges and when an
3677 * instance of these subclasses is created programmatically rather than
3678 * being inflated from XML. This method is automatically called when the XML
3679 * is inflated.
3680 * </p>
3681 *
3682 * @param a the styled attributes set to initialize the fading edges from
3683 */
3684 protected void initializeFadingEdge(TypedArray a) {
3685 initScrollCache();
3686
3687 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3688 R.styleable.View_fadingEdgeLength,
3689 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3690 }
3691
3692 /**
3693 * Returns the size of the vertical faded edges used to indicate that more
3694 * content in this view is visible.
3695 *
3696 * @return The size in pixels of the vertical faded edge or 0 if vertical
3697 * faded edges are not enabled for this view.
3698 * @attr ref android.R.styleable#View_fadingEdgeLength
3699 */
3700 public int getVerticalFadingEdgeLength() {
3701 if (isVerticalFadingEdgeEnabled()) {
3702 ScrollabilityCache cache = mScrollCache;
3703 if (cache != null) {
3704 return cache.fadingEdgeLength;
3705 }
3706 }
3707 return 0;
3708 }
3709
3710 /**
3711 * Set the size of the faded edge used to indicate that more content in this
3712 * view is available. Will not change whether the fading edge is enabled; use
Romain Guy5c22a8c2011-05-13 11:48:45 -07003713 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3714 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3715 * for the vertical or horizontal fading edges.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003716 *
3717 * @param length The size in pixels of the faded edge used to indicate that more
3718 * content in this view is visible.
3719 */
3720 public void setFadingEdgeLength(int length) {
3721 initScrollCache();
3722 mScrollCache.fadingEdgeLength = length;
3723 }
3724
3725 /**
3726 * Returns the size of the horizontal faded edges used to indicate that more
3727 * content in this view is visible.
3728 *
3729 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3730 * faded edges are not enabled for this view.
3731 * @attr ref android.R.styleable#View_fadingEdgeLength
3732 */
3733 public int getHorizontalFadingEdgeLength() {
3734 if (isHorizontalFadingEdgeEnabled()) {
3735 ScrollabilityCache cache = mScrollCache;
3736 if (cache != null) {
3737 return cache.fadingEdgeLength;
3738 }
3739 }
3740 return 0;
3741 }
3742
3743 /**
3744 * Returns the width of the vertical scrollbar.
3745 *
3746 * @return The width in pixels of the vertical scrollbar or 0 if there
3747 * is no vertical scrollbar.
3748 */
3749 public int getVerticalScrollbarWidth() {
3750 ScrollabilityCache cache = mScrollCache;
3751 if (cache != null) {
3752 ScrollBarDrawable scrollBar = cache.scrollBar;
3753 if (scrollBar != null) {
3754 int size = scrollBar.getSize(true);
3755 if (size <= 0) {
3756 size = cache.scrollBarSize;
3757 }
3758 return size;
3759 }
3760 return 0;
3761 }
3762 return 0;
3763 }
3764
3765 /**
3766 * Returns the height of the horizontal scrollbar.
3767 *
3768 * @return The height in pixels of the horizontal scrollbar or 0 if
3769 * there is no horizontal scrollbar.
3770 */
3771 protected int getHorizontalScrollbarHeight() {
3772 ScrollabilityCache cache = mScrollCache;
3773 if (cache != null) {
3774 ScrollBarDrawable scrollBar = cache.scrollBar;
3775 if (scrollBar != null) {
3776 int size = scrollBar.getSize(false);
3777 if (size <= 0) {
3778 size = cache.scrollBarSize;
3779 }
3780 return size;
3781 }
3782 return 0;
3783 }
3784 return 0;
3785 }
3786
3787 /**
3788 * <p>
3789 * Initializes the scrollbars from a given set of styled attributes. This
3790 * method should be called by subclasses that need scrollbars and when an
3791 * instance of these subclasses is created programmatically rather than
3792 * being inflated from XML. This method is automatically called when the XML
3793 * is inflated.
3794 * </p>
3795 *
3796 * @param a the styled attributes set to initialize the scrollbars from
3797 */
3798 protected void initializeScrollbars(TypedArray a) {
3799 initScrollCache();
3800
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003801 final ScrollabilityCache scrollabilityCache = mScrollCache;
Joe Malin32736f02011-01-19 16:14:20 -08003802
Mike Cleronf116bf82009-09-27 19:14:12 -07003803 if (scrollabilityCache.scrollBar == null) {
3804 scrollabilityCache.scrollBar = new ScrollBarDrawable();
3805 }
Joe Malin32736f02011-01-19 16:14:20 -08003806
Romain Guy8bda2482010-03-02 11:42:11 -08003807 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003808
Mike Cleronf116bf82009-09-27 19:14:12 -07003809 if (!fadeScrollbars) {
3810 scrollabilityCache.state = ScrollabilityCache.ON;
3811 }
3812 scrollabilityCache.fadeScrollBars = fadeScrollbars;
Joe Malin32736f02011-01-19 16:14:20 -08003813
3814
Mike Cleronf116bf82009-09-27 19:14:12 -07003815 scrollabilityCache.scrollBarFadeDuration = a.getInt(
3816 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3817 .getScrollBarFadeDuration());
3818 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3819 R.styleable.View_scrollbarDefaultDelayBeforeFade,
3820 ViewConfiguration.getScrollDefaultDelay());
3821
Joe Malin32736f02011-01-19 16:14:20 -08003822
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003823 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3824 com.android.internal.R.styleable.View_scrollbarSize,
3825 ViewConfiguration.get(mContext).getScaledScrollBarSize());
3826
3827 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3828 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3829
3830 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3831 if (thumb != null) {
3832 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3833 }
3834
3835 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3836 false);
3837 if (alwaysDraw) {
3838 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3839 }
3840
3841 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3842 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3843
3844 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3845 if (thumb != null) {
3846 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3847 }
3848
3849 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3850 false);
3851 if (alwaysDraw) {
3852 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3853 }
3854
Fabrice Di Megliob03b4342012-06-04 12:55:30 -07003855 // Apply layout direction to the new Drawables if needed
3856 final int layoutDirection = getResolvedLayoutDirection();
3857 if (track != null) {
3858 track.setLayoutDirection(layoutDirection);
3859 }
3860 if (thumb != null) {
3861 thumb.setLayoutDirection(layoutDirection);
3862 }
3863
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003864 // Re-apply user/background padding so that scrollbar(s) get added
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003865 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003866 }
3867
3868 /**
3869 * <p>
3870 * Initalizes the scrollability cache if necessary.
3871 * </p>
3872 */
3873 private void initScrollCache() {
3874 if (mScrollCache == null) {
Mike Cleronf116bf82009-09-27 19:14:12 -07003875 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003876 }
3877 }
3878
Philip Milne6c8ea062012-04-03 17:38:43 -07003879 private ScrollabilityCache getScrollCache() {
3880 initScrollCache();
3881 return mScrollCache;
3882 }
3883
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003884 /**
Adam Powell20232d02010-12-08 21:08:53 -08003885 * Set the position of the vertical scroll bar. Should be one of
3886 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3887 * {@link #SCROLLBAR_POSITION_RIGHT}.
3888 *
3889 * @param position Where the vertical scroll bar should be positioned.
3890 */
3891 public void setVerticalScrollbarPosition(int position) {
3892 if (mVerticalScrollbarPosition != position) {
3893 mVerticalScrollbarPosition = position;
3894 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003895 resolvePadding();
Adam Powell20232d02010-12-08 21:08:53 -08003896 }
3897 }
3898
3899 /**
3900 * @return The position where the vertical scroll bar will show, if applicable.
3901 * @see #setVerticalScrollbarPosition(int)
3902 */
3903 public int getVerticalScrollbarPosition() {
3904 return mVerticalScrollbarPosition;
3905 }
3906
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003907 ListenerInfo getListenerInfo() {
3908 if (mListenerInfo != null) {
3909 return mListenerInfo;
3910 }
3911 mListenerInfo = new ListenerInfo();
3912 return mListenerInfo;
3913 }
3914
Adam Powell20232d02010-12-08 21:08:53 -08003915 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003916 * Register a callback to be invoked when focus of this view changed.
3917 *
3918 * @param l The callback that will run.
3919 */
3920 public void setOnFocusChangeListener(OnFocusChangeListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003921 getListenerInfo().mOnFocusChangeListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003922 }
3923
3924 /**
Chet Haase21cd1382010-09-01 17:42:29 -07003925 * Add a listener that will be called when the bounds of the view change due to
3926 * layout processing.
3927 *
3928 * @param listener The listener that will be called when layout bounds change.
3929 */
3930 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003931 ListenerInfo li = getListenerInfo();
3932 if (li.mOnLayoutChangeListeners == null) {
3933 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
Chet Haase21cd1382010-09-01 17:42:29 -07003934 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003935 if (!li.mOnLayoutChangeListeners.contains(listener)) {
3936 li.mOnLayoutChangeListeners.add(listener);
Chet Haase1a76dcd2011-10-06 11:16:40 -07003937 }
Chet Haase21cd1382010-09-01 17:42:29 -07003938 }
3939
3940 /**
3941 * Remove a listener for layout changes.
3942 *
3943 * @param listener The listener for layout bounds change.
3944 */
3945 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003946 ListenerInfo li = mListenerInfo;
3947 if (li == null || li.mOnLayoutChangeListeners == null) {
Chet Haase21cd1382010-09-01 17:42:29 -07003948 return;
3949 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003950 li.mOnLayoutChangeListeners.remove(listener);
Chet Haase21cd1382010-09-01 17:42:29 -07003951 }
3952
3953 /**
Adam Powell4afd62b2011-02-18 15:02:18 -08003954 * Add a listener for attach state changes.
3955 *
3956 * This listener will be called whenever this view is attached or detached
3957 * from a window. Remove the listener using
3958 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3959 *
3960 * @param listener Listener to attach
3961 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3962 */
3963 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003964 ListenerInfo li = getListenerInfo();
3965 if (li.mOnAttachStateChangeListeners == null) {
3966 li.mOnAttachStateChangeListeners
3967 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
Adam Powell4afd62b2011-02-18 15:02:18 -08003968 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003969 li.mOnAttachStateChangeListeners.add(listener);
Adam Powell4afd62b2011-02-18 15:02:18 -08003970 }
3971
3972 /**
3973 * Remove a listener for attach state changes. The listener will receive no further
3974 * notification of window attach/detach events.
3975 *
3976 * @param listener Listener to remove
3977 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3978 */
3979 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003980 ListenerInfo li = mListenerInfo;
3981 if (li == null || li.mOnAttachStateChangeListeners == null) {
Adam Powell4afd62b2011-02-18 15:02:18 -08003982 return;
3983 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003984 li.mOnAttachStateChangeListeners.remove(listener);
Adam Powell4afd62b2011-02-18 15:02:18 -08003985 }
3986
3987 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003988 * Returns the focus-change callback registered for this view.
3989 *
3990 * @return The callback, or null if one is not registered.
3991 */
3992 public OnFocusChangeListener getOnFocusChangeListener() {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003993 ListenerInfo li = mListenerInfo;
3994 return li != null ? li.mOnFocusChangeListener : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003995 }
3996
3997 /**
3998 * Register a callback to be invoked when this view is clicked. If this view is not
3999 * clickable, it becomes clickable.
4000 *
4001 * @param l The callback that will run
4002 *
4003 * @see #setClickable(boolean)
4004 */
4005 public void setOnClickListener(OnClickListener l) {
4006 if (!isClickable()) {
4007 setClickable(true);
4008 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004009 getListenerInfo().mOnClickListener = l;
4010 }
4011
4012 /**
4013 * Return whether this view has an attached OnClickListener. Returns
4014 * true if there is a listener, false if there is none.
4015 */
4016 public boolean hasOnClickListeners() {
4017 ListenerInfo li = mListenerInfo;
4018 return (li != null && li.mOnClickListener != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004019 }
4020
4021 /**
4022 * Register a callback to be invoked when this view is clicked and held. If this view is not
4023 * long clickable, it becomes long clickable.
4024 *
4025 * @param l The callback that will run
4026 *
4027 * @see #setLongClickable(boolean)
4028 */
4029 public void setOnLongClickListener(OnLongClickListener l) {
4030 if (!isLongClickable()) {
4031 setLongClickable(true);
4032 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004033 getListenerInfo().mOnLongClickListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004034 }
4035
4036 /**
4037 * Register a callback to be invoked when the context menu for this view is
4038 * being built. If this view is not long clickable, it becomes long clickable.
4039 *
4040 * @param l The callback that will run
4041 *
4042 */
4043 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4044 if (!isLongClickable()) {
4045 setLongClickable(true);
4046 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004047 getListenerInfo().mOnCreateContextMenuListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004048 }
4049
4050 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004051 * Call this view's OnClickListener, if it is defined. Performs all normal
4052 * actions associated with clicking: reporting accessibility event, playing
4053 * a sound, etc.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004054 *
4055 * @return True there was an assigned OnClickListener that was called, false
4056 * otherwise is returned.
4057 */
4058 public boolean performClick() {
svetoslavganov75986cf2009-05-14 22:28:01 -07004059 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4060
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004061 ListenerInfo li = mListenerInfo;
4062 if (li != null && li.mOnClickListener != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004063 playSoundEffect(SoundEffectConstants.CLICK);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004064 li.mOnClickListener.onClick(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004065 return true;
4066 }
4067
4068 return false;
4069 }
4070
4071 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004072 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
4073 * this only calls the listener, and does not do any associated clicking
4074 * actions like reporting an accessibility event.
4075 *
4076 * @return True there was an assigned OnClickListener that was called, false
4077 * otherwise is returned.
4078 */
4079 public boolean callOnClick() {
4080 ListenerInfo li = mListenerInfo;
4081 if (li != null && li.mOnClickListener != null) {
4082 li.mOnClickListener.onClick(this);
4083 return true;
4084 }
4085 return false;
4086 }
4087
4088 /**
Gilles Debunnef788a9f2010-07-22 10:17:23 -07004089 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4090 * OnLongClickListener did not consume the event.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004091 *
Gilles Debunnef788a9f2010-07-22 10:17:23 -07004092 * @return True if one of the above receivers consumed the event, false otherwise.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004093 */
4094 public boolean performLongClick() {
svetoslavganov75986cf2009-05-14 22:28:01 -07004095 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4096
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004097 boolean handled = false;
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004098 ListenerInfo li = mListenerInfo;
4099 if (li != null && li.mOnLongClickListener != null) {
4100 handled = li.mOnLongClickListener.onLongClick(View.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004101 }
4102 if (!handled) {
4103 handled = showContextMenu();
4104 }
4105 if (handled) {
4106 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4107 }
4108 return handled;
4109 }
4110
4111 /**
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004112 * Performs button-related actions during a touch down event.
4113 *
4114 * @param event The event.
4115 * @return True if the down was consumed.
4116 *
4117 * @hide
4118 */
4119 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4120 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4121 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4122 return true;
4123 }
4124 }
4125 return false;
4126 }
4127
4128 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004129 * Bring up the context menu for this view.
4130 *
4131 * @return Whether a context menu was displayed.
4132 */
4133 public boolean showContextMenu() {
4134 return getParent().showContextMenuForChild(this);
4135 }
4136
4137 /**
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004138 * Bring up the context menu for this view, referring to the item under the specified point.
4139 *
4140 * @param x The referenced x coordinate.
4141 * @param y The referenced y coordinate.
4142 * @param metaState The keyboard modifiers that were pressed.
4143 * @return Whether a context menu was displayed.
4144 *
4145 * @hide
4146 */
4147 public boolean showContextMenu(float x, float y, int metaState) {
4148 return showContextMenu();
4149 }
4150
4151 /**
Adam Powell6e346362010-07-23 10:18:23 -07004152 * Start an action mode.
4153 *
4154 * @param callback Callback that will control the lifecycle of the action mode
4155 * @return The new action mode if it is started, null otherwise
4156 *
4157 * @see ActionMode
4158 */
4159 public ActionMode startActionMode(ActionMode.Callback callback) {
John Reck5160e2a2012-02-22 09:35:12 -08004160 ViewParent parent = getParent();
4161 if (parent == null) return null;
4162 return parent.startActionModeForChild(this, callback);
Adam Powell6e346362010-07-23 10:18:23 -07004163 }
4164
4165 /**
Jean Chalard405bc512012-05-29 19:12:34 +09004166 * Register a callback to be invoked when a hardware key is pressed in this view.
4167 * Key presses in software input methods will generally not trigger the methods of
4168 * this listener.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004169 * @param l the key listener to attach to this view
4170 */
4171 public void setOnKeyListener(OnKeyListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004172 getListenerInfo().mOnKeyListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004173 }
4174
4175 /**
4176 * Register a callback to be invoked when a touch event is sent to this view.
4177 * @param l the touch listener to attach to this view
4178 */
4179 public void setOnTouchListener(OnTouchListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004180 getListenerInfo().mOnTouchListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004181 }
4182
4183 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08004184 * Register a callback to be invoked when a generic motion event is sent to this view.
4185 * @param l the generic motion listener to attach to this view
4186 */
4187 public void setOnGenericMotionListener(OnGenericMotionListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004188 getListenerInfo().mOnGenericMotionListener = l;
Jeff Brown33bbfd22011-02-24 20:55:35 -08004189 }
4190
4191 /**
Jeff Brown53ca3f12011-06-27 18:36:00 -07004192 * Register a callback to be invoked when a hover event is sent to this view.
4193 * @param l the hover listener to attach to this view
4194 */
4195 public void setOnHoverListener(OnHoverListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004196 getListenerInfo().mOnHoverListener = l;
Jeff Brown53ca3f12011-06-27 18:36:00 -07004197 }
4198
4199 /**
Joe Malin32736f02011-01-19 16:14:20 -08004200 * Register a drag event listener callback object for this View. The parameter is
4201 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4202 * View, the system calls the
4203 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4204 * @param l An implementation of {@link android.view.View.OnDragListener}.
Chris Tate32affef2010-10-18 15:29:21 -07004205 */
4206 public void setOnDragListener(OnDragListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004207 getListenerInfo().mOnDragListener = l;
Chris Tate32affef2010-10-18 15:29:21 -07004208 }
4209
4210 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07004211 * Give this view focus. This will cause
4212 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004213 *
4214 * Note: this does not check whether this {@link View} should get focus, it just
4215 * gives it focus no matter what. It should only be called internally by framework
4216 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4217 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08004218 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4219 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004220 * focus moved when requestFocus() is called. It may not always
4221 * apply, in which case use the default View.FOCUS_DOWN.
4222 * @param previouslyFocusedRect The rectangle of the view that had focus
4223 * prior in this View's coordinate system.
4224 */
4225 void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4226 if (DBG) {
4227 System.out.println(this + " requestFocus()");
4228 }
4229
Dianne Hackborn4702a852012-08-17 15:18:29 -07004230 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4231 mPrivateFlags |= PFLAG_FOCUSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004232
4233 if (mParent != null) {
4234 mParent.requestChildFocus(this, this);
4235 }
4236
4237 onFocusChanged(true, direction, previouslyFocusedRect);
4238 refreshDrawableState();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004239
4240 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4241 notifyAccessibilityStateChanged();
4242 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004243 }
4244 }
4245
4246 /**
4247 * Request that a rectangle of this view be visible on the screen,
4248 * scrolling if necessary just enough.
4249 *
4250 * <p>A View should call this if it maintains some notion of which part
4251 * of its content is interesting. For example, a text editing view
4252 * should call this when its cursor moves.
4253 *
4254 * @param rectangle The rectangle.
4255 * @return Whether any parent scrolled.
4256 */
4257 public boolean requestRectangleOnScreen(Rect rectangle) {
4258 return requestRectangleOnScreen(rectangle, false);
4259 }
4260
4261 /**
4262 * Request that a rectangle of this view be visible on the screen,
4263 * scrolling if necessary just enough.
4264 *
4265 * <p>A View should call this if it maintains some notion of which part
4266 * of its content is interesting. For example, a text editing view
4267 * should call this when its cursor moves.
4268 *
4269 * <p>When <code>immediate</code> is set to true, scrolling will not be
4270 * animated.
4271 *
4272 * @param rectangle The rectangle.
4273 * @param immediate True to forbid animated scrolling, false otherwise
4274 * @return Whether any parent scrolled.
4275 */
4276 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
Svetoslav Ganovee6c6ae2012-09-10 19:56:06 -07004277 if (mAttachInfo == null) {
4278 return false;
4279 }
4280
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004281 View child = this;
Svetoslav Ganovee6c6ae2012-09-10 19:56:06 -07004282
4283 RectF position = mAttachInfo.mTmpTransformRect;
4284 position.set(rectangle);
4285
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004286 ViewParent parent = mParent;
4287 boolean scrolled = false;
4288 while (parent != null) {
Svetoslav Ganovee6c6ae2012-09-10 19:56:06 -07004289 rectangle.set((int) position.left, (int) position.top,
4290 (int) position.right, (int) position.bottom);
4291
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004292 scrolled |= parent.requestChildRectangleOnScreen(child,
4293 rectangle, immediate);
4294
Svetoslav Ganovee6c6ae2012-09-10 19:56:06 -07004295 if (!child.hasIdentityMatrix()) {
4296 child.getMatrix().mapRect(position);
4297 }
4298
4299 position.offset(child.mLeft, child.mTop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004300
4301 if (!(parent instanceof View)) {
4302 break;
4303 }
Romain Guy8506ab42009-06-11 17:35:47 -07004304
Svetoslav Ganovee6c6ae2012-09-10 19:56:06 -07004305 View parentView = (View) parent;
4306
4307 position.offset(-parentView.getScrollX(), -parentView.getScrollY());
4308
4309 child = parentView;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 parent = child.getParent();
4311 }
Svetoslav Ganovee6c6ae2012-09-10 19:56:06 -07004312
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004313 return scrolled;
4314 }
4315
4316 /**
Svetoslav Ganov13fd5612012-02-01 17:01:12 -08004317 * Called when this view wants to give up focus. If focus is cleared
4318 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4319 * <p>
4320 * <strong>Note:</strong> When a View clears focus the framework is trying
4321 * to give focus to the first focusable View from the top. Hence, if this
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004322 * View is the first from the top that can take focus, then all callbacks
4323 * related to clearing focus will be invoked after wich the framework will
4324 * give focus to this view.
Svetoslav Ganov13fd5612012-02-01 17:01:12 -08004325 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004326 */
4327 public void clearFocus() {
4328 if (DBG) {
4329 System.out.println(this + " clearFocus()");
4330 }
4331
Dianne Hackborn4702a852012-08-17 15:18:29 -07004332 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4333 mPrivateFlags &= ~PFLAG_FOCUSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004334
4335 if (mParent != null) {
4336 mParent.clearChildFocus(this);
4337 }
4338
4339 onFocusChanged(false, 0, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07004340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004341 refreshDrawableState();
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004342
4343 ensureInputFocusOnFirstFocusable();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004344
4345 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4346 notifyAccessibilityStateChanged();
4347 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004348 }
4349 }
4350
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004351 void ensureInputFocusOnFirstFocusable() {
4352 View root = getRootView();
4353 if (root != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004354 root.requestFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004355 }
4356 }
4357
4358 /**
4359 * Called internally by the view system when a new view is getting focus.
4360 * This is what clears the old focus.
4361 */
4362 void unFocus() {
4363 if (DBG) {
4364 System.out.println(this + " unFocus()");
4365 }
4366
Dianne Hackborn4702a852012-08-17 15:18:29 -07004367 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4368 mPrivateFlags &= ~PFLAG_FOCUSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004369
4370 onFocusChanged(false, 0, null);
4371 refreshDrawableState();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004372
4373 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4374 notifyAccessibilityStateChanged();
4375 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004376 }
4377 }
4378
4379 /**
4380 * Returns true if this view has focus iteself, or is the ancestor of the
4381 * view that has focus.
4382 *
4383 * @return True if this view has or contains focus, false otherwise.
4384 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07004385 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004386 public boolean hasFocus() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07004387 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004388 }
4389
4390 /**
4391 * Returns true if this view is focusable or if it contains a reachable View
4392 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4393 * is a View whose parents do not block descendants focus.
4394 *
4395 * Only {@link #VISIBLE} views are considered focusable.
4396 *
4397 * @return True if the view is focusable or if the view contains a focusable
4398 * View, false otherwise.
4399 *
4400 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4401 */
4402 public boolean hasFocusable() {
4403 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4404 }
4405
4406 /**
4407 * Called by the view system when the focus state of this view changes.
4408 * When the focus change event is caused by directional navigation, direction
4409 * and previouslyFocusedRect provide insight into where the focus is coming from.
4410 * When overriding, be sure to call up through to the super class so that
4411 * the standard focus handling will occur.
Romain Guy8506ab42009-06-11 17:35:47 -07004412 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004413 * @param gainFocus True if the View has focus; false otherwise.
4414 * @param direction The direction focus has moved when requestFocus()
4415 * is called to give this view focus. Values are
Jeff Brown4e6319b2010-12-13 10:36:51 -08004416 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4417 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4418 * It may not always apply, in which case use the default.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004419 * @param previouslyFocusedRect The rectangle, in this view's coordinate
4420 * system, of the previously focused view. If applicable, this will be
4421 * passed in as finer grained information about where the focus is coming
4422 * from (in addition to direction). Will be <code>null</code> otherwise.
4423 */
4424 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
svetoslavganov75986cf2009-05-14 22:28:01 -07004425 if (gainFocus) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004426 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4427 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07004428 }
svetoslavganov75986cf2009-05-14 22:28:01 -07004429 }
4430
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004431 InputMethodManager imm = InputMethodManager.peekInstance();
4432 if (!gainFocus) {
4433 if (isPressed()) {
4434 setPressed(false);
4435 }
4436 if (imm != null && mAttachInfo != null
4437 && mAttachInfo.mHasWindowFocus) {
4438 imm.focusOut(this);
4439 }
Romain Guya2431d02009-04-30 16:30:00 -07004440 onFocusLost();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004441 } else if (imm != null && mAttachInfo != null
4442 && mAttachInfo.mHasWindowFocus) {
4443 imm.focusIn(this);
4444 }
Romain Guy8506ab42009-06-11 17:35:47 -07004445
Romain Guy0fd89bf2011-01-26 15:41:30 -08004446 invalidate(true);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004447 ListenerInfo li = mListenerInfo;
4448 if (li != null && li.mOnFocusChangeListener != null) {
4449 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004450 }
Joe Malin32736f02011-01-19 16:14:20 -08004451
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07004452 if (mAttachInfo != null) {
4453 mAttachInfo.mKeyDispatchState.reset(this);
4454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004455 }
4456
4457 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004458 * Sends an accessibility event of the given type. If accessiiblity is
4459 * not enabled this method has no effect. The default implementation calls
4460 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4461 * to populate information about the event source (this View), then calls
4462 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4463 * populate the text content of the event source including its descendants,
4464 * and last calls
4465 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4466 * on its parent to resuest sending of the event to interested parties.
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004467 * <p>
4468 * If an {@link AccessibilityDelegate} has been specified via calling
4469 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4470 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4471 * responsible for handling this call.
4472 * </p>
Svetoslav Ganov30401322011-05-12 18:53:45 -07004473 *
Scott Mainb303d832011-10-12 16:45:18 -07004474 * @param eventType The type of the event to send, as defined by several types from
4475 * {@link android.view.accessibility.AccessibilityEvent}, such as
4476 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4477 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004478 *
4479 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4480 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4481 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004482 * @see AccessibilityDelegate
svetoslavganov75986cf2009-05-14 22:28:01 -07004483 */
4484 public void sendAccessibilityEvent(int eventType) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004485 if (mAccessibilityDelegate != null) {
4486 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4487 } else {
4488 sendAccessibilityEventInternal(eventType);
4489 }
4490 }
4491
4492 /**
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004493 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4494 * {@link AccessibilityEvent} to make an announcement which is related to some
4495 * sort of a context change for which none of the events representing UI transitions
4496 * is a good fit. For example, announcing a new page in a book. If accessibility
4497 * is not enabled this method does nothing.
4498 *
4499 * @param text The announcement text.
4500 */
4501 public void announceForAccessibility(CharSequence text) {
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004502 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004503 AccessibilityEvent event = AccessibilityEvent.obtain(
4504 AccessibilityEvent.TYPE_ANNOUNCEMENT);
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004505 onInitializeAccessibilityEvent(event);
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004506 event.getText().add(text);
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004507 event.setContentDescription(null);
4508 mParent.requestSendAccessibilityEvent(this, event);
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004509 }
4510 }
4511
4512 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004513 * @see #sendAccessibilityEvent(int)
4514 *
4515 * Note: Called from the default {@link AccessibilityDelegate}.
4516 */
4517 void sendAccessibilityEventInternal(int eventType) {
svetoslavganov75986cf2009-05-14 22:28:01 -07004518 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4519 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4520 }
4521 }
4522
4523 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004524 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4525 * takes as an argument an empty {@link AccessibilityEvent} and does not
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004526 * perform a check whether accessibility is enabled.
4527 * <p>
4528 * If an {@link AccessibilityDelegate} has been specified via calling
4529 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4530 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4531 * is responsible for handling this call.
4532 * </p>
Svetoslav Ganov30401322011-05-12 18:53:45 -07004533 *
4534 * @param event The event to send.
4535 *
4536 * @see #sendAccessibilityEvent(int)
svetoslavganov75986cf2009-05-14 22:28:01 -07004537 */
4538 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004539 if (mAccessibilityDelegate != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004540 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004541 } else {
4542 sendAccessibilityEventUncheckedInternal(event);
4543 }
4544 }
4545
4546 /**
4547 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4548 *
4549 * Note: Called from the default {@link AccessibilityDelegate}.
4550 */
4551 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
Svetoslav Ganov9cd1eca2011-01-13 14:24:02 -08004552 if (!isShown()) {
4553 return;
4554 }
Svetoslav Ganov30401322011-05-12 18:53:45 -07004555 onInitializeAccessibilityEvent(event);
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07004556 // Only a subset of accessibility events populates text content.
4557 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4558 dispatchPopulateAccessibilityEvent(event);
4559 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004560 // In the beginning we called #isShown(), so we know that getParent() is not null.
4561 getParent().requestSendAccessibilityEvent(this, event);
svetoslavganov75986cf2009-05-14 22:28:01 -07004562 }
4563
4564 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004565 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4566 * to its children for adding their text content to the event. Note that the
4567 * event text is populated in a separate dispatch path since we add to the
4568 * event not only the text of the source but also the text of all its descendants.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004569 * A typical implementation will call
4570 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4571 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4572 * on each child. Override this method if custom population of the event text
4573 * content is required.
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004574 * <p>
4575 * If an {@link AccessibilityDelegate} has been specified via calling
4576 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4577 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4578 * is responsible for handling this call.
4579 * </p>
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07004580 * <p>
4581 * <em>Note:</em> Accessibility events of certain types are not dispatched for
4582 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4583 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -07004584 *
4585 * @param event The event.
4586 *
4587 * @return True if the event population was completed.
4588 */
4589 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004590 if (mAccessibilityDelegate != null) {
4591 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4592 } else {
4593 return dispatchPopulateAccessibilityEventInternal(event);
4594 }
4595 }
4596
4597 /**
4598 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4599 *
4600 * Note: Called from the default {@link AccessibilityDelegate}.
4601 */
4602 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004603 onPopulateAccessibilityEvent(event);
svetoslavganov75986cf2009-05-14 22:28:01 -07004604 return false;
4605 }
4606
4607 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004608 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
Svetoslav Ganov30401322011-05-12 18:53:45 -07004609 * giving a chance to this View to populate the accessibility event with its
Scott Mainb303d832011-10-12 16:45:18 -07004610 * text content. While this method is free to modify event
4611 * attributes other than text content, doing so should normally be performed in
Svetoslav Ganov30401322011-05-12 18:53:45 -07004612 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4613 * <p>
4614 * Example: Adding formatted date string to an accessibility event in addition
Scott Mainb303d832011-10-12 16:45:18 -07004615 * to the text added by the super implementation:
4616 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov30401322011-05-12 18:53:45 -07004617 * super.onPopulateAccessibilityEvent(event);
4618 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4619 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4620 * mCurrentDate.getTimeInMillis(), flags);
4621 * event.getText().add(selectedDateUtterance);
Scott Mainb303d832011-10-12 16:45:18 -07004622 * }</pre>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004623 * <p>
4624 * If an {@link AccessibilityDelegate} has been specified via calling
4625 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4626 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4627 * is responsible for handling this call.
4628 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07004629 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4630 * information to the event, in case the default implementation has basic information to add.
4631 * </p>
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004632 *
4633 * @param event The accessibility event which to populate.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004634 *
4635 * @see #sendAccessibilityEvent(int)
4636 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004637 */
4638 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004639 if (mAccessibilityDelegate != null) {
4640 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4641 } else {
4642 onPopulateAccessibilityEventInternal(event);
4643 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004644 }
4645
4646 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004647 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4648 *
4649 * Note: Called from the default {@link AccessibilityDelegate}.
4650 */
4651 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4652
4653 }
4654
4655 /**
4656 * Initializes an {@link AccessibilityEvent} with information about
4657 * this View which is the event source. In other words, the source of
4658 * an accessibility event is the view whose state change triggered firing
4659 * the event.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004660 * <p>
4661 * Example: Setting the password property of an event in addition
Scott Mainb303d832011-10-12 16:45:18 -07004662 * to properties set by the super implementation:
4663 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4664 * super.onInitializeAccessibilityEvent(event);
4665 * event.setPassword(true);
4666 * }</pre>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004667 * <p>
4668 * If an {@link AccessibilityDelegate} has been specified via calling
4669 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4670 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4671 * is responsible for handling this call.
4672 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07004673 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4674 * information to the event, in case the default implementation has basic information to add.
4675 * </p>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004676 * @param event The event to initialize.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004677 *
4678 * @see #sendAccessibilityEvent(int)
4679 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4680 */
4681 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004682 if (mAccessibilityDelegate != null) {
4683 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4684 } else {
4685 onInitializeAccessibilityEventInternal(event);
4686 }
4687 }
4688
4689 /**
4690 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4691 *
4692 * Note: Called from the default {@link AccessibilityDelegate}.
4693 */
4694 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004695 event.setSource(this);
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08004696 event.setClassName(View.class.getName());
Svetoslav Ganov30401322011-05-12 18:53:45 -07004697 event.setPackageName(getContext().getPackageName());
4698 event.setEnabled(isEnabled());
4699 event.setContentDescription(mContentDescription);
4700
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -07004701 if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004702 ArrayList<View> focusablesTempList = mAttachInfo.mTempArrayList;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -07004703 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4704 FOCUSABLES_ALL);
4705 event.setItemCount(focusablesTempList.size());
4706 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4707 focusablesTempList.clear();
Svetoslav Ganov30401322011-05-12 18:53:45 -07004708 }
4709 }
4710
4711 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004712 * Returns an {@link AccessibilityNodeInfo} representing this view from the
4713 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4714 * This method is responsible for obtaining an accessibility node info from a
4715 * pool of reusable instances and calling
4716 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4717 * initialize the former.
4718 * <p>
4719 * Note: The client is responsible for recycling the obtained instance by calling
4720 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4721 * </p>
Svetoslav Ganov02107852011-10-03 17:06:56 -07004722 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004723 * @return A populated {@link AccessibilityNodeInfo}.
4724 *
4725 * @see AccessibilityNodeInfo
4726 */
4727 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
Svetoslav Ganov02107852011-10-03 17:06:56 -07004728 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4729 if (provider != null) {
4730 return provider.createAccessibilityNodeInfo(View.NO_ID);
4731 } else {
4732 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4733 onInitializeAccessibilityNodeInfo(info);
4734 return info;
4735 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004736 }
4737
4738 /**
4739 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4740 * The base implementation sets:
4741 * <ul>
4742 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004743 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4744 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004745 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4746 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4747 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4748 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4749 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4750 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4751 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4752 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4753 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4754 * </ul>
4755 * <p>
4756 * Subclasses should override this method, call the super implementation,
4757 * and set additional attributes.
4758 * </p>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004759 * <p>
4760 * If an {@link AccessibilityDelegate} has been specified via calling
4761 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4762 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4763 * is responsible for handling this call.
4764 * </p>
4765 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004766 * @param info The instance to initialize.
4767 */
4768 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004769 if (mAccessibilityDelegate != null) {
4770 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4771 } else {
4772 onInitializeAccessibilityNodeInfoInternal(info);
4773 }
4774 }
4775
4776 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004777 * Gets the location of this view in screen coordintates.
4778 *
4779 * @param outRect The output location
4780 */
4781 private void getBoundsOnScreen(Rect outRect) {
4782 if (mAttachInfo == null) {
4783 return;
4784 }
4785
4786 RectF position = mAttachInfo.mTmpTransformRect;
Svetoslav Ganov14b2b742012-05-08 16:36:34 -07004787 position.set(0, 0, mRight - mLeft, mBottom - mTop);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004788
4789 if (!hasIdentityMatrix()) {
4790 getMatrix().mapRect(position);
4791 }
4792
Svetoslav Ganov14b2b742012-05-08 16:36:34 -07004793 position.offset(mLeft, mTop);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004794
4795 ViewParent parent = mParent;
4796 while (parent instanceof View) {
4797 View parentView = (View) parent;
4798
4799 position.offset(-parentView.mScrollX, -parentView.mScrollY);
4800
4801 if (!parentView.hasIdentityMatrix()) {
4802 parentView.getMatrix().mapRect(position);
4803 }
4804
4805 position.offset(parentView.mLeft, parentView.mTop);
4806
4807 parent = parentView.mParent;
4808 }
4809
4810 if (parent instanceof ViewRootImpl) {
4811 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
4812 position.offset(0, -viewRootImpl.mCurScrollY);
4813 }
4814
4815 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
4816
4817 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
4818 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
4819 }
4820
4821 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004822 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4823 *
4824 * Note: Called from the default {@link AccessibilityDelegate}.
4825 */
4826 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004827 Rect bounds = mAttachInfo.mTmpInvalRect;
Svetoslav Ganov983119a2012-07-03 21:04:10 -07004828
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004829 getDrawingRect(bounds);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004830 info.setBoundsInParent(bounds);
4831
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004832 getBoundsOnScreen(bounds);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004833 info.setBoundsInScreen(bounds);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004834
Svetoslav Ganovc406be92012-05-11 16:12:32 -07004835 ViewParent parent = getParentForAccessibility();
4836 if (parent instanceof View) {
4837 info.setParent((View) parent);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004838 }
4839
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004840 info.setVisibleToUser(isVisibleToUser());
4841
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004842 info.setPackageName(mContext.getPackageName());
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08004843 info.setClassName(View.class.getName());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004844 info.setContentDescription(getContentDescription());
4845
4846 info.setEnabled(isEnabled());
4847 info.setClickable(isClickable());
4848 info.setFocusable(isFocusable());
4849 info.setFocused(isFocused());
Svetoslav Ganov42138042012-03-20 11:51:39 -07004850 info.setAccessibilityFocused(isAccessibilityFocused());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004851 info.setSelected(isSelected());
4852 info.setLongClickable(isLongClickable());
4853
4854 // TODO: These make sense only if we are in an AdapterView but all
4855 // views can be selected. Maybe from accessiiblity perspective
4856 // we should report as selectable view in an AdapterView.
4857 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4858 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4859
4860 if (isFocusable()) {
4861 if (isFocused()) {
4862 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4863 } else {
4864 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4865 }
4866 }
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004867
Svetoslav Ganov02afe2c2012-05-07 17:51:59 -07004868 if (!isAccessibilityFocused()) {
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07004869 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Svetoslav Ganov02afe2c2012-05-07 17:51:59 -07004870 } else {
4871 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
4872 }
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004873
Svetoslav Ganovfb1e80a2012-05-16 17:33:19 -07004874 if (isClickable() && isEnabled()) {
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004875 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
4876 }
4877
Svetoslav Ganovfb1e80a2012-05-16 17:33:19 -07004878 if (isLongClickable() && isEnabled()) {
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004879 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
4880 }
4881
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07004882 if (mContentDescription != null && mContentDescription.length() > 0) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07004883 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
4884 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
4885 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07004886 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
4887 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004888 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004889 }
4890
4891 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004892 * Computes whether this view is visible to the user. Such a view is
4893 * attached, visible, all its predecessors are visible, it is not clipped
4894 * entirely by its predecessors, and has an alpha greater than zero.
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004895 *
4896 * @return Whether the view is visible on the screen.
Guang Zhu0d607fb2012-05-11 19:34:56 -07004897 *
4898 * @hide
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004899 */
Guang Zhu0d607fb2012-05-11 19:34:56 -07004900 protected boolean isVisibleToUser() {
4901 return isVisibleToUser(null);
4902 }
4903
4904 /**
Romain Guyf0af1d52012-07-11 18:31:21 -07004905 * Computes whether the given portion of this view is visible to the user.
4906 * Such a view is attached, visible, all its predecessors are visible,
4907 * has an alpha greater than zero, and the specified portion is not
4908 * clipped entirely by its predecessors.
Guang Zhu0d607fb2012-05-11 19:34:56 -07004909 *
4910 * @param boundInView the portion of the view to test; coordinates should be relative; may be
4911 * <code>null</code>, and the entire view will be tested in this case.
4912 * When <code>true</code> is returned by the function, the actual visible
4913 * region will be stored in this parameter; that is, if boundInView is fully
4914 * contained within the view, no modification will be made, otherwise regions
4915 * outside of the visible area of the view will be clipped.
4916 *
4917 * @return Whether the specified portion of the view is visible on the screen.
4918 *
4919 * @hide
4920 */
4921 protected boolean isVisibleToUser(Rect boundInView) {
Romain Guyf0af1d52012-07-11 18:31:21 -07004922 if (mAttachInfo != null) {
4923 Rect visibleRect = mAttachInfo.mTmpInvalRect;
4924 Point offset = mAttachInfo.mPoint;
4925 // The first two checks are made also made by isShown() which
4926 // however traverses the tree up to the parent to catch that.
4927 // Therefore, we do some fail fast check to minimize the up
4928 // tree traversal.
4929 boolean isVisible = mAttachInfo.mWindowVisibility == View.VISIBLE
4930 && getAlpha() > 0
4931 && isShown()
4932 && getGlobalVisibleRect(visibleRect, offset);
Guang Zhu0d607fb2012-05-11 19:34:56 -07004933 if (isVisible && boundInView != null) {
4934 visibleRect.offset(-offset.x, -offset.y);
Romain Guyf0af1d52012-07-11 18:31:21 -07004935 // isVisible is always true here, use a simple assignment
4936 isVisible = boundInView.intersect(visibleRect);
Guang Zhu0d607fb2012-05-11 19:34:56 -07004937 }
4938 return isVisible;
Romain Guyf0af1d52012-07-11 18:31:21 -07004939 }
4940
4941 return false;
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004942 }
4943
4944 /**
alanvb72fe7a2012-08-27 16:44:25 -07004945 * Returns the delegate for implementing accessibility support via
4946 * composition. For more details see {@link AccessibilityDelegate}.
4947 *
4948 * @return The delegate, or null if none set.
4949 *
4950 * @hide
4951 */
4952 public AccessibilityDelegate getAccessibilityDelegate() {
4953 return mAccessibilityDelegate;
4954 }
4955
4956 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004957 * Sets a delegate for implementing accessibility support via compositon as
4958 * opposed to inheritance. The delegate's primary use is for implementing
4959 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4960 *
4961 * @param delegate The delegate instance.
4962 *
4963 * @see AccessibilityDelegate
4964 */
4965 public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4966 mAccessibilityDelegate = delegate;
4967 }
4968
4969 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07004970 * Gets the provider for managing a virtual view hierarchy rooted at this View
4971 * and reported to {@link android.accessibilityservice.AccessibilityService}s
4972 * that explore the window content.
4973 * <p>
4974 * If this method returns an instance, this instance is responsible for managing
4975 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
4976 * View including the one representing the View itself. Similarly the returned
4977 * instance is responsible for performing accessibility actions on any virtual
4978 * view or the root view itself.
4979 * </p>
4980 * <p>
4981 * If an {@link AccessibilityDelegate} has been specified via calling
4982 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4983 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
4984 * is responsible for handling this call.
4985 * </p>
4986 *
4987 * @return The provider.
4988 *
4989 * @see AccessibilityNodeProvider
4990 */
4991 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
4992 if (mAccessibilityDelegate != null) {
4993 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
4994 } else {
4995 return null;
4996 }
4997 }
4998
4999 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07005000 * Gets the unique identifier of this view on the screen for accessibility purposes.
5001 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
5002 *
5003 * @return The view accessibility id.
5004 *
5005 * @hide
5006 */
5007 public int getAccessibilityViewId() {
5008 if (mAccessibilityViewId == NO_ID) {
5009 mAccessibilityViewId = sNextAccessibilityViewId++;
5010 }
5011 return mAccessibilityViewId;
5012 }
5013
5014 /**
5015 * Gets the unique identifier of the window in which this View reseides.
5016 *
5017 * @return The window accessibility id.
5018 *
5019 * @hide
5020 */
5021 public int getAccessibilityWindowId() {
5022 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
5023 }
5024
5025 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07005026 * Gets the {@link View} description. It briefly describes the view and is
5027 * primarily used for accessibility support. Set this property to enable
5028 * better accessibility support for your application. This is especially
5029 * true for views that do not have textual representation (For example,
5030 * ImageButton).
5031 *
Svetoslav Ganov42138042012-03-20 11:51:39 -07005032 * @return The content description.
svetoslavganov75986cf2009-05-14 22:28:01 -07005033 *
5034 * @attr ref android.R.styleable#View_contentDescription
5035 */
Svetoslav Ganov42138042012-03-20 11:51:39 -07005036 @ViewDebug.ExportedProperty(category = "accessibility")
svetoslavganov75986cf2009-05-14 22:28:01 -07005037 public CharSequence getContentDescription() {
5038 return mContentDescription;
5039 }
5040
5041 /**
5042 * Sets the {@link View} description. It briefly describes the view and is
5043 * primarily used for accessibility support. Set this property to enable
5044 * better accessibility support for your application. This is especially
5045 * true for views that do not have textual representation (For example,
5046 * ImageButton).
5047 *
5048 * @param contentDescription The content description.
5049 *
5050 * @attr ref android.R.styleable#View_contentDescription
5051 */
Svetoslav Ganove261e282011-10-18 17:47:04 -07005052 @RemotableViewMethod
svetoslavganov75986cf2009-05-14 22:28:01 -07005053 public void setContentDescription(CharSequence contentDescription) {
5054 mContentDescription = contentDescription;
Svetoslav Ganove47957a2012-06-05 14:46:50 -07005055 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5056 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5057 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5058 }
svetoslavganov75986cf2009-05-14 22:28:01 -07005059 }
5060
5061 /**
Romain Guya2431d02009-04-30 16:30:00 -07005062 * Invoked whenever this view loses focus, either by losing window focus or by losing
5063 * focus within its window. This method can be used to clear any state tied to the
5064 * focus. For instance, if a button is held pressed with the trackball and the window
5065 * loses focus, this method can be used to cancel the press.
5066 *
5067 * Subclasses of View overriding this method should always call super.onFocusLost().
5068 *
5069 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
Romain Guy8506ab42009-06-11 17:35:47 -07005070 * @see #onWindowFocusChanged(boolean)
Romain Guya2431d02009-04-30 16:30:00 -07005071 *
5072 * @hide pending API council approval
5073 */
5074 protected void onFocusLost() {
5075 resetPressedState();
5076 }
5077
5078 private void resetPressedState() {
5079 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5080 return;
5081 }
5082
5083 if (isPressed()) {
5084 setPressed(false);
5085
5086 if (!mHasPerformedLongPress) {
Maryam Garrett1549dd12009-12-15 16:06:36 -05005087 removeLongPressCallback();
Romain Guya2431d02009-04-30 16:30:00 -07005088 }
5089 }
5090 }
5091
5092 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005093 * Returns true if this view has focus
5094 *
5095 * @return True if this view has focus, false otherwise.
5096 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005097 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005098 public boolean isFocused() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005099 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005100 }
5101
5102 /**
5103 * Find the view in the hierarchy rooted at this view that currently has
5104 * focus.
5105 *
5106 * @return The view that currently has focus, or null if no focused view can
5107 * be found.
5108 */
5109 public View findFocus() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005110 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005111 }
5112
5113 /**
Philip Milne6c8ea062012-04-03 17:38:43 -07005114 * Indicates whether this view is one of the set of scrollable containers in
5115 * its window.
5116 *
5117 * @return whether this view is one of the set of scrollable containers in
5118 * its window
5119 *
5120 * @attr ref android.R.styleable#View_isScrollContainer
5121 */
5122 public boolean isScrollContainer() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005123 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
Philip Milne6c8ea062012-04-03 17:38:43 -07005124 }
5125
5126 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005127 * Change whether this view is one of the set of scrollable containers in
5128 * its window. This will be used to determine whether the window can
5129 * resize or must pan when a soft input area is open -- scrollable
5130 * containers allow the window to use resize mode since the container
5131 * will appropriately shrink.
Philip Milne6c8ea062012-04-03 17:38:43 -07005132 *
5133 * @attr ref android.R.styleable#View_isScrollContainer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005134 */
5135 public void setScrollContainer(boolean isScrollContainer) {
5136 if (isScrollContainer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005137 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005138 mAttachInfo.mScrollContainers.add(this);
Dianne Hackborn4702a852012-08-17 15:18:29 -07005139 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005140 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07005141 mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005142 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005143 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005144 mAttachInfo.mScrollContainers.remove(this);
5145 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07005146 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005147 }
5148 }
5149
5150 /**
5151 * Returns the quality of the drawing cache.
5152 *
5153 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5154 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5155 *
5156 * @see #setDrawingCacheQuality(int)
5157 * @see #setDrawingCacheEnabled(boolean)
5158 * @see #isDrawingCacheEnabled()
5159 *
5160 * @attr ref android.R.styleable#View_drawingCacheQuality
5161 */
5162 public int getDrawingCacheQuality() {
5163 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5164 }
5165
5166 /**
5167 * Set the drawing cache quality of this view. This value is used only when the
5168 * drawing cache is enabled
5169 *
5170 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5171 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5172 *
5173 * @see #getDrawingCacheQuality()
5174 * @see #setDrawingCacheEnabled(boolean)
5175 * @see #isDrawingCacheEnabled()
5176 *
5177 * @attr ref android.R.styleable#View_drawingCacheQuality
5178 */
5179 public void setDrawingCacheQuality(int quality) {
5180 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5181 }
5182
5183 /**
5184 * Returns whether the screen should remain on, corresponding to the current
5185 * value of {@link #KEEP_SCREEN_ON}.
5186 *
5187 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5188 *
5189 * @see #setKeepScreenOn(boolean)
5190 *
5191 * @attr ref android.R.styleable#View_keepScreenOn
5192 */
5193 public boolean getKeepScreenOn() {
5194 return (mViewFlags & KEEP_SCREEN_ON) != 0;
5195 }
5196
5197 /**
5198 * Controls whether the screen should remain on, modifying the
5199 * value of {@link #KEEP_SCREEN_ON}.
5200 *
5201 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5202 *
5203 * @see #getKeepScreenOn()
5204 *
5205 * @attr ref android.R.styleable#View_keepScreenOn
5206 */
5207 public void setKeepScreenOn(boolean keepScreenOn) {
5208 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5209 }
5210
5211 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005212 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5213 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005214 *
5215 * @attr ref android.R.styleable#View_nextFocusLeft
5216 */
5217 public int getNextFocusLeftId() {
5218 return mNextFocusLeftId;
5219 }
5220
5221 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005222 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5223 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5224 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005225 *
5226 * @attr ref android.R.styleable#View_nextFocusLeft
5227 */
5228 public void setNextFocusLeftId(int nextFocusLeftId) {
5229 mNextFocusLeftId = nextFocusLeftId;
5230 }
5231
5232 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005233 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5234 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005235 *
5236 * @attr ref android.R.styleable#View_nextFocusRight
5237 */
5238 public int getNextFocusRightId() {
5239 return mNextFocusRightId;
5240 }
5241
5242 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005243 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5244 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5245 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005246 *
5247 * @attr ref android.R.styleable#View_nextFocusRight
5248 */
5249 public void setNextFocusRightId(int nextFocusRightId) {
5250 mNextFocusRightId = nextFocusRightId;
5251 }
5252
5253 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005254 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5255 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005256 *
5257 * @attr ref android.R.styleable#View_nextFocusUp
5258 */
5259 public int getNextFocusUpId() {
5260 return mNextFocusUpId;
5261 }
5262
5263 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005264 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5265 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5266 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005267 *
5268 * @attr ref android.R.styleable#View_nextFocusUp
5269 */
5270 public void setNextFocusUpId(int nextFocusUpId) {
5271 mNextFocusUpId = nextFocusUpId;
5272 }
5273
5274 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005275 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5276 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005277 *
5278 * @attr ref android.R.styleable#View_nextFocusDown
5279 */
5280 public int getNextFocusDownId() {
5281 return mNextFocusDownId;
5282 }
5283
5284 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005285 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5286 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5287 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005288 *
5289 * @attr ref android.R.styleable#View_nextFocusDown
5290 */
5291 public void setNextFocusDownId(int nextFocusDownId) {
5292 mNextFocusDownId = nextFocusDownId;
5293 }
5294
5295 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005296 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5297 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5298 *
5299 * @attr ref android.R.styleable#View_nextFocusForward
5300 */
5301 public int getNextFocusForwardId() {
5302 return mNextFocusForwardId;
5303 }
5304
5305 /**
5306 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5307 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5308 * decide automatically.
5309 *
5310 * @attr ref android.R.styleable#View_nextFocusForward
5311 */
5312 public void setNextFocusForwardId(int nextFocusForwardId) {
5313 mNextFocusForwardId = nextFocusForwardId;
5314 }
5315
5316 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005317 * Returns the visibility of this view and all of its ancestors
5318 *
5319 * @return True if this view and all of its ancestors are {@link #VISIBLE}
5320 */
5321 public boolean isShown() {
5322 View current = this;
5323 //noinspection ConstantConditions
5324 do {
5325 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5326 return false;
5327 }
5328 ViewParent parent = current.mParent;
5329 if (parent == null) {
5330 return false; // We are not attached to the view root
5331 }
5332 if (!(parent instanceof View)) {
5333 return true;
5334 }
5335 current = (View) parent;
5336 } while (current != null);
5337
5338 return false;
5339 }
5340
5341 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005342 * Called by the view hierarchy when the content insets for a window have
5343 * changed, to allow it to adjust its content to fit within those windows.
5344 * The content insets tell you the space that the status bar, input method,
5345 * and other system windows infringe on the application's window.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005346 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005347 * <p>You do not normally need to deal with this function, since the default
5348 * window decoration given to applications takes care of applying it to the
5349 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5350 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5351 * and your content can be placed under those system elements. You can then
5352 * use this method within your view hierarchy if you have parts of your UI
5353 * which you would like to ensure are not being covered.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005354 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005355 * <p>The default implementation of this method simply applies the content
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005356 * inset's to the view's padding, consuming that content (modifying the
5357 * insets to be 0), and returning true. This behavior is off by default, but can
5358 * be enabled through {@link #setFitsSystemWindows(boolean)}.
5359 *
5360 * <p>This function's traversal down the hierarchy is depth-first. The same content
5361 * insets object is propagated down the hierarchy, so any changes made to it will
5362 * be seen by all following views (including potentially ones above in
5363 * the hierarchy since this is a depth-first traversal). The first view
5364 * that returns true will abort the entire traversal.
5365 *
5366 * <p>The default implementation works well for a situation where it is
5367 * used with a container that covers the entire window, allowing it to
5368 * apply the appropriate insets to its content on all edges. If you need
5369 * a more complicated layout (such as two different views fitting system
5370 * windows, one on the top of the window, and one on the bottom),
5371 * you can override the method and handle the insets however you would like.
5372 * Note that the insets provided by the framework are always relative to the
5373 * far edges of the window, not accounting for the location of the called view
5374 * within that window. (In fact when this method is called you do not yet know
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005375 * where the layout will place the view, as it is done before layout happens.)
5376 *
5377 * <p>Note: unlike many View methods, there is no dispatch phase to this
5378 * call. If you are overriding it in a ViewGroup and want to allow the
5379 * call to continue to your children, you must be sure to call the super
5380 * implementation.
5381 *
Dianne Hackborncf675782012-05-10 15:07:24 -07005382 * <p>Here is a sample layout that makes use of fitting system windows
5383 * to have controls for a video view placed inside of the window decorations
5384 * that it hides and shows. This can be used with code like the second
5385 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5386 *
5387 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5388 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005389 * @param insets Current content insets of the window. Prior to
5390 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5391 * the insets or else you and Android will be unhappy.
5392 *
5393 * @return Return true if this view applied the insets and it should not
5394 * continue propagating further down the hierarchy, false otherwise.
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005395 * @see #getFitsSystemWindows()
Romain Guyf0af1d52012-07-11 18:31:21 -07005396 * @see #setFitsSystemWindows(boolean)
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005397 * @see #setSystemUiVisibility(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005398 */
5399 protected boolean fitSystemWindows(Rect insets) {
5400 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07005401 mUserPaddingStart = UNDEFINED_PADDING;
5402 mUserPaddingEnd = UNDEFINED_PADDING;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005403 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5404 || mAttachInfo == null
5405 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
5406 internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
5407 return true;
5408 } else {
5409 internalSetPadding(0, 0, 0, 0);
5410 return false;
5411 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005412 }
5413 return false;
5414 }
5415
5416 /**
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005417 * Sets whether or not this view should account for system screen decorations
5418 * such as the status bar and inset its content; that is, controlling whether
5419 * the default implementation of {@link #fitSystemWindows(Rect)} will be
5420 * executed. See that method for more details.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005421 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005422 * <p>Note that if you are providing your own implementation of
5423 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5424 * flag to true -- your implementation will be overriding the default
5425 * implementation that checks this flag.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005426 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005427 * @param fitSystemWindows If true, then the default implementation of
5428 * {@link #fitSystemWindows(Rect)} will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005429 *
5430 * @attr ref android.R.styleable#View_fitsSystemWindows
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005431 * @see #getFitsSystemWindows()
5432 * @see #fitSystemWindows(Rect)
5433 * @see #setSystemUiVisibility(int)
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005434 */
5435 public void setFitsSystemWindows(boolean fitSystemWindows) {
5436 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5437 }
5438
5439 /**
Dianne Hackborncf675782012-05-10 15:07:24 -07005440 * Check for state of {@link #setFitsSystemWindows(boolean). If this method
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005441 * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5442 * will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005443 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005444 * @return Returns true if the default implementation of
5445 * {@link #fitSystemWindows(Rect)} will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005446 *
5447 * @attr ref android.R.styleable#View_fitsSystemWindows
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005448 * @see #setFitsSystemWindows()
5449 * @see #fitSystemWindows(Rect)
5450 * @see #setSystemUiVisibility(int)
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005451 */
Dianne Hackborncf675782012-05-10 15:07:24 -07005452 public boolean getFitsSystemWindows() {
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005453 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5454 }
5455
Dianne Hackbornb1b55e62012-05-10 16:25:54 -07005456 /** @hide */
5457 public boolean fitsSystemWindows() {
5458 return getFitsSystemWindows();
5459 }
5460
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005461 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005462 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5463 */
5464 public void requestFitSystemWindows() {
5465 if (mParent != null) {
5466 mParent.requestFitSystemWindows();
5467 }
5468 }
5469
5470 /**
5471 * For use by PhoneWindow to make its own system window fitting optional.
5472 * @hide
5473 */
5474 public void makeOptionalFitsSystemWindows() {
5475 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5476 }
5477
5478 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005479 * Returns the visibility status for this view.
5480 *
5481 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5482 * @attr ref android.R.styleable#View_visibility
5483 */
5484 @ViewDebug.ExportedProperty(mapping = {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07005485 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
5486 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5487 @ViewDebug.IntToString(from = GONE, to = "GONE")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005488 })
5489 public int getVisibility() {
5490 return mViewFlags & VISIBILITY_MASK;
5491 }
5492
5493 /**
5494 * Set the enabled state of this view.
5495 *
5496 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5497 * @attr ref android.R.styleable#View_visibility
5498 */
5499 @RemotableViewMethod
5500 public void setVisibility(int visibility) {
5501 setFlags(visibility, VISIBILITY_MASK);
Philip Milne6c8ea062012-04-03 17:38:43 -07005502 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005503 }
5504
5505 /**
5506 * Returns the enabled status for this view. The interpretation of the
5507 * enabled state varies by subclass.
5508 *
5509 * @return True if this view is enabled, false otherwise.
5510 */
5511 @ViewDebug.ExportedProperty
5512 public boolean isEnabled() {
5513 return (mViewFlags & ENABLED_MASK) == ENABLED;
5514 }
5515
5516 /**
5517 * Set the enabled state of this view. The interpretation of the enabled
5518 * state varies by subclass.
5519 *
5520 * @param enabled True if this view is enabled, false otherwise.
5521 */
Jeff Sharkey2b95c242010-02-08 17:40:30 -08005522 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005523 public void setEnabled(boolean enabled) {
Amith Yamasania2ef00b2009-07-30 16:14:34 -07005524 if (enabled == isEnabled()) return;
5525
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005526 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5527
5528 /*
5529 * The View most likely has to change its appearance, so refresh
5530 * the drawable state.
5531 */
5532 refreshDrawableState();
5533
5534 // Invalidate too, since the default behavior for views is to be
5535 // be drawn at 50% alpha rather than to change the drawable.
Romain Guy0fd89bf2011-01-26 15:41:30 -08005536 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005537 }
5538
5539 /**
5540 * Set whether this view can receive the focus.
5541 *
5542 * Setting this to false will also ensure that this view is not focusable
5543 * in touch mode.
5544 *
5545 * @param focusable If true, this view can receive the focus.
5546 *
5547 * @see #setFocusableInTouchMode(boolean)
5548 * @attr ref android.R.styleable#View_focusable
5549 */
5550 public void setFocusable(boolean focusable) {
5551 if (!focusable) {
5552 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5553 }
5554 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5555 }
5556
5557 /**
5558 * Set whether this view can receive focus while in touch mode.
5559 *
5560 * Setting this to true will also ensure that this view is focusable.
5561 *
5562 * @param focusableInTouchMode If true, this view can receive the focus while
5563 * in touch mode.
5564 *
5565 * @see #setFocusable(boolean)
5566 * @attr ref android.R.styleable#View_focusableInTouchMode
5567 */
5568 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5569 // Focusable in touch mode should always be set before the focusable flag
5570 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5571 // which, in touch mode, will not successfully request focus on this view
5572 // because the focusable in touch mode flag is not set
5573 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5574 if (focusableInTouchMode) {
5575 setFlags(FOCUSABLE, FOCUSABLE_MASK);
5576 }
5577 }
5578
5579 /**
5580 * Set whether this view should have sound effects enabled for events such as
5581 * clicking and touching.
5582 *
5583 * <p>You may wish to disable sound effects for a view if you already play sounds,
5584 * for instance, a dial key that plays dtmf tones.
5585 *
5586 * @param soundEffectsEnabled whether sound effects are enabled for this view.
5587 * @see #isSoundEffectsEnabled()
5588 * @see #playSoundEffect(int)
5589 * @attr ref android.R.styleable#View_soundEffectsEnabled
5590 */
5591 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5592 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5593 }
5594
5595 /**
5596 * @return whether this view should have sound effects enabled for events such as
5597 * clicking and touching.
5598 *
5599 * @see #setSoundEffectsEnabled(boolean)
5600 * @see #playSoundEffect(int)
5601 * @attr ref android.R.styleable#View_soundEffectsEnabled
5602 */
5603 @ViewDebug.ExportedProperty
5604 public boolean isSoundEffectsEnabled() {
5605 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5606 }
5607
5608 /**
5609 * Set whether this view should have haptic feedback for events such as
5610 * long presses.
5611 *
5612 * <p>You may wish to disable haptic feedback if your view already controls
5613 * its own haptic feedback.
5614 *
5615 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5616 * @see #isHapticFeedbackEnabled()
5617 * @see #performHapticFeedback(int)
5618 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5619 */
5620 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5621 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5622 }
5623
5624 /**
5625 * @return whether this view should have haptic feedback enabled for events
5626 * long presses.
5627 *
5628 * @see #setHapticFeedbackEnabled(boolean)
5629 * @see #performHapticFeedback(int)
5630 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5631 */
5632 @ViewDebug.ExportedProperty
5633 public boolean isHapticFeedbackEnabled() {
5634 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5635 }
5636
5637 /**
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005638 * Returns the layout direction for this view.
Cibu Johny7632cb92010-02-22 13:01:02 -08005639 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005640 * @return One of {@link #LAYOUT_DIRECTION_LTR},
5641 * {@link #LAYOUT_DIRECTION_RTL},
5642 * {@link #LAYOUT_DIRECTION_INHERIT} or
5643 * {@link #LAYOUT_DIRECTION_LOCALE}.
5644 * @attr ref android.R.styleable#View_layoutDirection
Cibu Johny7632cb92010-02-22 13:01:02 -08005645 */
Fabrice Di Megliobce84d22011-06-02 15:57:01 -07005646 @ViewDebug.ExportedProperty(category = "layout", mapping = {
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005647 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
5648 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
5649 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5650 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
Cibu Johny7632cb92010-02-22 13:01:02 -08005651 })
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005652 public int getLayoutDirection() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005653 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Cibu Johny7632cb92010-02-22 13:01:02 -08005654 }
5655
5656 /**
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005657 * Set the layout direction for this view. This will propagate a reset of layout direction
5658 * resolution to the view's children and resolve layout direction for this view.
Cibu Johny7632cb92010-02-22 13:01:02 -08005659 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005660 * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
5661 * {@link #LAYOUT_DIRECTION_RTL},
5662 * {@link #LAYOUT_DIRECTION_INHERIT} or
5663 * {@link #LAYOUT_DIRECTION_LOCALE}.
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005664 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005665 * @attr ref android.R.styleable#View_layoutDirection
Cibu Johny7632cb92010-02-22 13:01:02 -08005666 */
5667 @RemotableViewMethod
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005668 public void setLayoutDirection(int layoutDirection) {
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005669 if (getLayoutDirection() != layoutDirection) {
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -07005670 // Reset the current layout direction and the resolved one
Dianne Hackborn4702a852012-08-17 15:18:29 -07005671 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
Fabrice Di Meglio7f86c802011-07-01 15:09:24 -07005672 resetResolvedLayoutDirection();
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005673 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -07005674 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005675 // Set the new layout direction (filtered)
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005676 mPrivateFlags2 |=
Dianne Hackborn4702a852012-08-17 15:18:29 -07005677 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005678 resolveRtlProperties();
5679 // ... and ask for a layout pass
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005680 requestLayout();
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005681 }
Cibu Johny7632cb92010-02-22 13:01:02 -08005682 }
5683
5684 /**
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005685 * Returns the resolved layout direction for this view.
5686 *
5687 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005688 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005689 */
5690 @ViewDebug.ExportedProperty(category = "layout", mapping = {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005691 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
5692 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005693 })
5694 public int getResolvedLayoutDirection() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005695 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5696 if (targetSdkVersion < JELLY_BEAN_MR1) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005697 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005698 return LAYOUT_DIRECTION_LTR;
5699 }
Fabrice Di Megliob93911f2012-06-26 19:43:15 -07005700 // The layout direction will be resolved only if needed
Dianne Hackborn4702a852012-08-17 15:18:29 -07005701 if ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) != PFLAG2_LAYOUT_DIRECTION_RESOLVED) {
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -07005702 resolveLayoutDirection();
5703 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07005704 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ?
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005705 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
5706 }
5707
5708 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005709 * Indicates whether or not this view's layout is right-to-left. This is resolved from
5710 * layout attribute and/or the inherited value from the parent
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005711 *
5712 * @return true if the layout is right-to-left.
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005713 */
5714 @ViewDebug.ExportedProperty(category = "layout")
5715 public boolean isLayoutRtl() {
5716 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
5717 }
5718
5719 /**
Adam Powell539ee872012-02-03 19:00:49 -08005720 * Indicates whether the view is currently tracking transient state that the
5721 * app should not need to concern itself with saving and restoring, but that
5722 * the framework should take special note to preserve when possible.
5723 *
Adam Powell785c4472012-05-02 21:25:39 -07005724 * <p>A view with transient state cannot be trivially rebound from an external
5725 * data source, such as an adapter binding item views in a list. This may be
5726 * because the view is performing an animation, tracking user selection
5727 * of content, or similar.</p>
5728 *
Adam Powell539ee872012-02-03 19:00:49 -08005729 * @return true if the view has transient state
Adam Powell539ee872012-02-03 19:00:49 -08005730 */
5731 @ViewDebug.ExportedProperty(category = "layout")
5732 public boolean hasTransientState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005733 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
Adam Powell539ee872012-02-03 19:00:49 -08005734 }
5735
5736 /**
5737 * Set whether this view is currently tracking transient state that the
Chet Haase563d4f22012-04-18 16:20:08 -07005738 * framework should attempt to preserve when possible. This flag is reference counted,
5739 * so every call to setHasTransientState(true) should be paired with a later call
5740 * to setHasTransientState(false).
Adam Powell539ee872012-02-03 19:00:49 -08005741 *
Adam Powell785c4472012-05-02 21:25:39 -07005742 * <p>A view with transient state cannot be trivially rebound from an external
5743 * data source, such as an adapter binding item views in a list. This may be
5744 * because the view is performing an animation, tracking user selection
5745 * of content, or similar.</p>
5746 *
Adam Powell539ee872012-02-03 19:00:49 -08005747 * @param hasTransientState true if this view has transient state
Adam Powell539ee872012-02-03 19:00:49 -08005748 */
5749 public void setHasTransientState(boolean hasTransientState) {
Chet Haase563d4f22012-04-18 16:20:08 -07005750 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
5751 mTransientStateCount - 1;
5752 if (mTransientStateCount < 0) {
5753 mTransientStateCount = 0;
5754 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
5755 "unmatched pair of setHasTransientState calls");
5756 }
5757 if ((hasTransientState && mTransientStateCount == 1) ||
Adam Powell057a5852012-05-11 10:28:38 -07005758 (!hasTransientState && mTransientStateCount == 0)) {
Chet Haase563d4f22012-04-18 16:20:08 -07005759 // update flag if we've just incremented up from 0 or decremented down to 0
Dianne Hackborn4702a852012-08-17 15:18:29 -07005760 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
5761 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
Chet Haase563d4f22012-04-18 16:20:08 -07005762 if (mParent != null) {
5763 try {
5764 mParent.childHasTransientStateChanged(this, hasTransientState);
5765 } catch (AbstractMethodError e) {
5766 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
5767 " does not fully implement ViewParent", e);
5768 }
Adam Powell539ee872012-02-03 19:00:49 -08005769 }
5770 }
5771 }
5772
5773 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005774 * If this view doesn't do any drawing on its own, set this flag to
5775 * allow further optimizations. By default, this flag is not set on
5776 * View, but could be set on some View subclasses such as ViewGroup.
5777 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07005778 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
5779 * you should clear this flag.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005780 *
5781 * @param willNotDraw whether or not this View draw on its own
5782 */
5783 public void setWillNotDraw(boolean willNotDraw) {
5784 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
5785 }
5786
5787 /**
5788 * Returns whether or not this View draws on its own.
5789 *
5790 * @return true if this view has nothing to draw, false otherwise
5791 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005792 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005793 public boolean willNotDraw() {
5794 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
5795 }
5796
5797 /**
5798 * When a View's drawing cache is enabled, drawing is redirected to an
5799 * offscreen bitmap. Some views, like an ImageView, must be able to
5800 * bypass this mechanism if they already draw a single bitmap, to avoid
5801 * unnecessary usage of the memory.
5802 *
5803 * @param willNotCacheDrawing true if this view does not cache its
5804 * drawing, false otherwise
5805 */
5806 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
5807 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
5808 }
5809
5810 /**
5811 * Returns whether or not this View can cache its drawing or not.
5812 *
5813 * @return true if this view does not cache its drawing, false otherwise
5814 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005815 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005816 public boolean willNotCacheDrawing() {
5817 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
5818 }
5819
5820 /**
5821 * Indicates whether this view reacts to click events or not.
5822 *
5823 * @return true if the view is clickable, false otherwise
5824 *
5825 * @see #setClickable(boolean)
5826 * @attr ref android.R.styleable#View_clickable
5827 */
5828 @ViewDebug.ExportedProperty
5829 public boolean isClickable() {
5830 return (mViewFlags & CLICKABLE) == CLICKABLE;
5831 }
5832
5833 /**
5834 * Enables or disables click events for this view. When a view
5835 * is clickable it will change its state to "pressed" on every click.
5836 * Subclasses should set the view clickable to visually react to
5837 * user's clicks.
5838 *
5839 * @param clickable true to make the view clickable, false otherwise
5840 *
5841 * @see #isClickable()
5842 * @attr ref android.R.styleable#View_clickable
5843 */
5844 public void setClickable(boolean clickable) {
5845 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
5846 }
5847
5848 /**
5849 * Indicates whether this view reacts to long click events or not.
5850 *
5851 * @return true if the view is long clickable, false otherwise
5852 *
5853 * @see #setLongClickable(boolean)
5854 * @attr ref android.R.styleable#View_longClickable
5855 */
5856 public boolean isLongClickable() {
5857 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
5858 }
5859
5860 /**
5861 * Enables or disables long click events for this view. When a view is long
5862 * clickable it reacts to the user holding down the button for a longer
5863 * duration than a tap. This event can either launch the listener or a
5864 * context menu.
5865 *
5866 * @param longClickable true to make the view long clickable, false otherwise
5867 * @see #isLongClickable()
5868 * @attr ref android.R.styleable#View_longClickable
5869 */
5870 public void setLongClickable(boolean longClickable) {
5871 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
5872 }
5873
5874 /**
Chet Haase49afa5b2010-08-23 11:39:53 -07005875 * Sets the pressed state for this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005876 *
5877 * @see #isClickable()
5878 * @see #setClickable(boolean)
5879 *
5880 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
5881 * the View's internal state from a previously set "pressed" state.
5882 */
5883 public void setPressed(boolean pressed) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005884 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
Adam Powell4d6f0662012-02-21 15:11:11 -08005885
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 if (pressed) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005887 mPrivateFlags |= PFLAG_PRESSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005888 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005889 mPrivateFlags &= ~PFLAG_PRESSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005890 }
Adam Powell035a1fc2012-02-27 15:23:50 -08005891
5892 if (needsRefresh) {
5893 refreshDrawableState();
5894 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005895 dispatchSetPressed(pressed);
5896 }
5897
5898 /**
5899 * Dispatch setPressed to all of this View's children.
5900 *
5901 * @see #setPressed(boolean)
5902 *
5903 * @param pressed The new pressed state
5904 */
5905 protected void dispatchSetPressed(boolean pressed) {
5906 }
5907
5908 /**
5909 * Indicates whether the view is currently in pressed state. Unless
5910 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
5911 * the pressed state.
5912 *
Philip Milne6c8ea062012-04-03 17:38:43 -07005913 * @see #setPressed(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005914 * @see #isClickable()
5915 * @see #setClickable(boolean)
5916 *
5917 * @return true if the view is currently pressed, false otherwise
5918 */
5919 public boolean isPressed() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005920 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005921 }
5922
5923 /**
5924 * Indicates whether this view will save its state (that is,
5925 * whether its {@link #onSaveInstanceState} method will be called).
5926 *
5927 * @return Returns true if the view state saving is enabled, else false.
5928 *
5929 * @see #setSaveEnabled(boolean)
5930 * @attr ref android.R.styleable#View_saveEnabled
5931 */
5932 public boolean isSaveEnabled() {
5933 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
5934 }
5935
5936 /**
5937 * Controls whether the saving of this view's state is
5938 * enabled (that is, whether its {@link #onSaveInstanceState} method
5939 * will be called). Note that even if freezing is enabled, the
Romain Guy5c22a8c2011-05-13 11:48:45 -07005940 * view still must have an id assigned to it (via {@link #setId(int)})
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005941 * for its state to be saved. This flag can only disable the
5942 * saving of this view; any child views may still have their state saved.
5943 *
5944 * @param enabled Set to false to <em>disable</em> state saving, or true
5945 * (the default) to allow it.
5946 *
5947 * @see #isSaveEnabled()
5948 * @see #setId(int)
5949 * @see #onSaveInstanceState()
5950 * @attr ref android.R.styleable#View_saveEnabled
5951 */
5952 public void setSaveEnabled(boolean enabled) {
5953 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
5954 }
5955
Jeff Brown85a31762010-09-01 17:01:00 -07005956 /**
5957 * Gets whether the framework should discard touches when the view's
5958 * window is obscured by another visible window.
5959 * Refer to the {@link View} security documentation for more details.
5960 *
5961 * @return True if touch filtering is enabled.
5962 *
5963 * @see #setFilterTouchesWhenObscured(boolean)
5964 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5965 */
5966 @ViewDebug.ExportedProperty
5967 public boolean getFilterTouchesWhenObscured() {
5968 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
5969 }
5970
5971 /**
5972 * Sets whether the framework should discard touches when the view's
5973 * window is obscured by another visible window.
5974 * Refer to the {@link View} security documentation for more details.
5975 *
5976 * @param enabled True if touch filtering should be enabled.
5977 *
5978 * @see #getFilterTouchesWhenObscured
5979 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5980 */
5981 public void setFilterTouchesWhenObscured(boolean enabled) {
5982 setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
5983 FILTER_TOUCHES_WHEN_OBSCURED);
5984 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005985
5986 /**
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07005987 * Indicates whether the entire hierarchy under this view will save its
5988 * state when a state saving traversal occurs from its parent. The default
5989 * is true; if false, these views will not be saved unless
5990 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5991 *
5992 * @return Returns true if the view state saving from parent is enabled, else false.
5993 *
5994 * @see #setSaveFromParentEnabled(boolean)
5995 */
5996 public boolean isSaveFromParentEnabled() {
5997 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
5998 }
5999
6000 /**
6001 * Controls whether the entire hierarchy under this view will save its
6002 * state when a state saving traversal occurs from its parent. The default
6003 * is true; if false, these views will not be saved unless
6004 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
6005 *
6006 * @param enabled Set to false to <em>disable</em> state saving, or true
6007 * (the default) to allow it.
6008 *
6009 * @see #isSaveFromParentEnabled()
6010 * @see #setId(int)
6011 * @see #onSaveInstanceState()
6012 */
6013 public void setSaveFromParentEnabled(boolean enabled) {
6014 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
6015 }
6016
6017
6018 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006019 * Returns whether this View is able to take focus.
6020 *
6021 * @return True if this view can take focus, or false otherwise.
6022 * @attr ref android.R.styleable#View_focusable
6023 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07006024 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006025 public final boolean isFocusable() {
6026 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
6027 }
6028
6029 /**
6030 * When a view is focusable, it may not want to take focus when in touch mode.
6031 * For example, a button would like focus when the user is navigating via a D-pad
6032 * so that the user can click on it, but once the user starts touching the screen,
6033 * the button shouldn't take focus
6034 * @return Whether the view is focusable in touch mode.
6035 * @attr ref android.R.styleable#View_focusableInTouchMode
6036 */
6037 @ViewDebug.ExportedProperty
6038 public final boolean isFocusableInTouchMode() {
6039 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6040 }
6041
6042 /**
6043 * Find the nearest view in the specified direction that can take focus.
6044 * This does not actually give focus to that view.
6045 *
6046 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6047 *
6048 * @return The nearest focusable in the specified direction, or null if none
6049 * can be found.
6050 */
6051 public View focusSearch(int direction) {
6052 if (mParent != null) {
6053 return mParent.focusSearch(this, direction);
6054 } else {
6055 return null;
6056 }
6057 }
6058
6059 /**
6060 * This method is the last chance for the focused view and its ancestors to
6061 * respond to an arrow key. This is called when the focused view did not
6062 * consume the key internally, nor could the view system find a new view in
6063 * the requested direction to give focus to.
6064 *
6065 * @param focused The currently focused view.
6066 * @param direction The direction focus wants to move. One of FOCUS_UP,
6067 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6068 * @return True if the this view consumed this unhandled move.
6069 */
6070 public boolean dispatchUnhandledMove(View focused, int direction) {
6071 return false;
6072 }
6073
6074 /**
6075 * If a user manually specified the next view id for a particular direction,
Jeff Brown4e6319b2010-12-13 10:36:51 -08006076 * use the root to look up the view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006077 * @param root The root view of the hierarchy containing this view.
Jeff Brown4e6319b2010-12-13 10:36:51 -08006078 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6079 * or FOCUS_BACKWARD.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006080 * @return The user specified next view, or null if there is none.
6081 */
6082 View findUserSetNextFocus(View root, int direction) {
6083 switch (direction) {
6084 case FOCUS_LEFT:
6085 if (mNextFocusLeftId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006086 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006087 case FOCUS_RIGHT:
6088 if (mNextFocusRightId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006089 return findViewInsideOutShouldExist(root, mNextFocusRightId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006090 case FOCUS_UP:
6091 if (mNextFocusUpId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006092 return findViewInsideOutShouldExist(root, mNextFocusUpId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 case FOCUS_DOWN:
6094 if (mNextFocusDownId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006095 return findViewInsideOutShouldExist(root, mNextFocusDownId);
Jeff Brown4e6319b2010-12-13 10:36:51 -08006096 case FOCUS_FORWARD:
6097 if (mNextFocusForwardId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006098 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
Jeff Brown4e6319b2010-12-13 10:36:51 -08006099 case FOCUS_BACKWARD: {
John Reck1ecebbb2012-03-06 16:08:54 -08006100 if (mID == View.NO_ID) return null;
Jeff Brown4e6319b2010-12-13 10:36:51 -08006101 final int id = mID;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006102 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
Jeff Brown4e6319b2010-12-13 10:36:51 -08006103 @Override
6104 public boolean apply(View t) {
6105 return t.mNextFocusForwardId == id;
6106 }
6107 });
6108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006109 }
6110 return null;
6111 }
6112
Jeff Brown4dfbec22011-08-15 14:55:37 -07006113 private View findViewInsideOutShouldExist(View root, final int childViewId) {
6114 View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6115 @Override
6116 public boolean apply(View t) {
6117 return t.mID == childViewId;
6118 }
6119 });
6120
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006121 if (result == null) {
6122 Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
6123 + "by user for id " + childViewId);
6124 }
6125 return result;
6126 }
6127
6128 /**
6129 * Find and return all focusable views that are descendants of this view,
6130 * possibly including this view if it is focusable itself.
6131 *
6132 * @param direction The direction of the focus
6133 * @return A list of focusable views
6134 */
6135 public ArrayList<View> getFocusables(int direction) {
6136 ArrayList<View> result = new ArrayList<View>(24);
6137 addFocusables(result, direction);
6138 return result;
6139 }
6140
6141 /**
6142 * Add any focusable views that are descendants of this view (possibly
6143 * including this view if it is focusable itself) to views. If we are in touch mode,
6144 * only add views that are also focusable in touch mode.
6145 *
6146 * @param views Focusable views found so far
6147 * @param direction The direction of the focus
6148 */
6149 public void addFocusables(ArrayList<View> views, int direction) {
svetoslavganov75986cf2009-05-14 22:28:01 -07006150 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6151 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006152
svetoslavganov75986cf2009-05-14 22:28:01 -07006153 /**
6154 * Adds any focusable views that are descendants of this view (possibly
6155 * including this view if it is focusable itself) to views. This method
6156 * adds all focusable views regardless if we are in touch mode or
Svetoslav Ganov42138042012-03-20 11:51:39 -07006157 * only views focusable in touch mode if we are in touch mode or
6158 * only views that can take accessibility focus if accessibility is enabeld
6159 * depending on the focusable mode paramater.
svetoslavganov75986cf2009-05-14 22:28:01 -07006160 *
6161 * @param views Focusable views found so far or null if all we are interested is
6162 * the number of focusables.
6163 * @param direction The direction of the focus.
6164 * @param focusableMode The type of focusables to be added.
6165 *
6166 * @see #FOCUSABLES_ALL
6167 * @see #FOCUSABLES_TOUCH_MODE
6168 */
6169 public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006170 if (views == null) {
svetoslavganov75986cf2009-05-14 22:28:01 -07006171 return;
6172 }
Svetoslav Ganov3cb889c2012-04-16 19:10:30 -07006173 if (!isFocusable()) {
6174 return;
svetoslavganov75986cf2009-05-14 22:28:01 -07006175 }
Svetoslav Ganov3cb889c2012-04-16 19:10:30 -07006176 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6177 && isInTouchMode() && !isFocusableInTouchMode()) {
6178 return;
6179 }
6180 views.add(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006181 }
6182
6183 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006184 * Finds the Views that contain given text. The containment is case insensitive.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006185 * The search is performed by either the text that the View renders or the content
6186 * description that describes the view for accessibility purposes and the view does
6187 * not render or both. Clients can specify how the search is to be performed via
6188 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6189 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006190 *
6191 * @param outViews The output list of matching Views.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006192 * @param searched The text to match against.
Svetoslav Ganov02107852011-10-03 17:06:56 -07006193 *
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006194 * @see #FIND_VIEWS_WITH_TEXT
6195 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6196 * @see #setContentDescription(CharSequence)
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006197 */
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006198 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07006199 if (getAccessibilityNodeProvider() != null) {
6200 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6201 outViews.add(this);
6202 }
6203 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006204 && (searched != null && searched.length() > 0)
6205 && (mContentDescription != null && mContentDescription.length() > 0)) {
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006206 String searchedLowerCase = searched.toString().toLowerCase();
6207 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6208 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6209 outViews.add(this);
6210 }
6211 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006212 }
6213
6214 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006215 * Find and return all touchable views that are descendants of this view,
6216 * possibly including this view if it is touchable itself.
6217 *
6218 * @return A list of touchable views
6219 */
6220 public ArrayList<View> getTouchables() {
6221 ArrayList<View> result = new ArrayList<View>();
6222 addTouchables(result);
6223 return result;
6224 }
6225
6226 /**
6227 * Add any touchable views that are descendants of this view (possibly
6228 * including this view if it is touchable itself) to views.
6229 *
6230 * @param views Touchable views found so far
6231 */
6232 public void addTouchables(ArrayList<View> views) {
6233 final int viewFlags = mViewFlags;
6234
6235 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6236 && (viewFlags & ENABLED_MASK) == ENABLED) {
6237 views.add(this);
6238 }
6239 }
6240
6241 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07006242 * Returns whether this View is accessibility focused.
6243 *
6244 * @return True if this View is accessibility focused.
6245 */
6246 boolean isAccessibilityFocused() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006247 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006248 }
6249
6250 /**
6251 * Call this to try to give accessibility focus to this view.
6252 *
6253 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6254 * returns false or the view is no visible or the view already has accessibility
6255 * focus.
6256 *
6257 * See also {@link #focusSearch(int)}, which is what you call to say that you
6258 * have focus, and you want your parent to look for the next one.
6259 *
6260 * @return Whether this view actually took accessibility focus.
6261 *
6262 * @hide
6263 */
6264 public boolean requestAccessibilityFocus() {
Svetoslav Ganov07b726c2012-04-30 12:24:57 -07006265 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6266 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006267 return false;
6268 }
6269 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6270 return false;
6271 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07006272 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
6273 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006274 ViewRootImpl viewRootImpl = getViewRootImpl();
6275 if (viewRootImpl != null) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006276 viewRootImpl.setAccessibilityFocus(this, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07006277 }
Svetoslav Ganov1cf70bb2012-08-06 10:53:34 -07006278 if (mAttachInfo != null) {
6279 Rect rectangle = mAttachInfo.mTmpInvalRect;
6280 getDrawingRect(rectangle);
6281 requestRectangleOnScreen(rectangle);
6282 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006283 invalidate();
6284 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6285 notifyAccessibilityStateChanged();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006286 return true;
6287 }
6288 return false;
6289 }
6290
6291 /**
6292 * Call this to try to clear accessibility focus of this view.
6293 *
6294 * See also {@link #focusSearch(int)}, which is what you call to say that you
6295 * have focus, and you want your parent to look for the next one.
6296 *
6297 * @hide
6298 */
6299 public void clearAccessibilityFocus() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006300 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6301 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006302 invalidate();
6303 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6304 notifyAccessibilityStateChanged();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006305 }
Svetoslav Ganovc00d0082012-05-22 18:37:49 -07006306 // Clear the global reference of accessibility focus if this
6307 // view or any of its descendants had accessibility focus.
6308 ViewRootImpl viewRootImpl = getViewRootImpl();
6309 if (viewRootImpl != null) {
6310 View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6311 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006312 viewRootImpl.setAccessibilityFocus(null, null);
Svetoslav Ganovc00d0082012-05-22 18:37:49 -07006313 }
6314 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006315 }
6316
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07006317 private void sendAccessibilityHoverEvent(int eventType) {
6318 // Since we are not delivering to a client accessibility events from not
6319 // important views (unless the clinet request that) we need to fire the
6320 // event from the deepest view exposed to the client. As a consequence if
6321 // the user crosses a not exposed view the client will see enter and exit
6322 // of the exposed predecessor followed by and enter and exit of that same
6323 // predecessor when entering and exiting the not exposed descendant. This
6324 // is fine since the client has a clear idea which view is hovered at the
6325 // price of a couple more events being sent. This is a simple and
6326 // working solution.
6327 View source = this;
6328 while (true) {
6329 if (source.includeForAccessibility()) {
6330 source.sendAccessibilityEvent(eventType);
6331 return;
6332 }
6333 ViewParent parent = source.getParent();
6334 if (parent instanceof View) {
6335 source = (View) parent;
6336 } else {
6337 return;
6338 }
6339 }
6340 }
6341
Svetoslav Ganov42138042012-03-20 11:51:39 -07006342 /**
6343 * Clears accessibility focus without calling any callback methods
6344 * normally invoked in {@link #clearAccessibilityFocus()}. This method
6345 * is used for clearing accessibility focus when giving this focus to
6346 * another view.
6347 */
6348 void clearAccessibilityFocusNoCallbacks() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006349 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6350 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006351 invalidate();
6352 }
6353 }
6354
6355 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006356 * Call this to try to give focus to a specific view or to one of its
6357 * descendants.
6358 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006359 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6360 * false), or if it is focusable and it is not focusable in touch mode
6361 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006362 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006363 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006364 * have focus, and you want your parent to look for the next one.
6365 *
6366 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6367 * {@link #FOCUS_DOWN} and <code>null</code>.
6368 *
6369 * @return Whether this view or one of its descendants actually took focus.
6370 */
6371 public final boolean requestFocus() {
6372 return requestFocus(View.FOCUS_DOWN);
6373 }
6374
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006375 /**
6376 * Call this to try to give focus to a specific view or to one of its
6377 * descendants and give it a hint about what direction focus is heading.
6378 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006379 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6380 * false), or if it is focusable and it is not focusable in touch mode
6381 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006382 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006383 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006384 * have focus, and you want your parent to look for the next one.
6385 *
6386 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6387 * <code>null</code> set for the previously focused rectangle.
6388 *
6389 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6390 * @return Whether this view or one of its descendants actually took focus.
6391 */
6392 public final boolean requestFocus(int direction) {
6393 return requestFocus(direction, null);
6394 }
6395
6396 /**
6397 * Call this to try to give focus to a specific view or to one of its descendants
6398 * and give it hints about the direction and a specific rectangle that the focus
6399 * is coming from. The rectangle can help give larger views a finer grained hint
6400 * about where focus is coming from, and therefore, where to show selection, or
6401 * forward focus change internally.
6402 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006403 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6404 * false), or if it is focusable and it is not focusable in touch mode
6405 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006406 *
6407 * A View will not take focus if it is not visible.
6408 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006409 * A View will not take focus if one of its parents has
6410 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6411 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006412 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006413 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006414 * have focus, and you want your parent to look for the next one.
6415 *
6416 * You may wish to override this method if your custom {@link View} has an internal
6417 * {@link View} that it wishes to forward the request to.
6418 *
6419 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6420 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6421 * to give a finer grained hint about where focus is coming from. May be null
6422 * if there is no hint.
6423 * @return Whether this view or one of its descendants actually took focus.
6424 */
6425 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006426 return requestFocusNoSearch(direction, previouslyFocusedRect);
6427 }
6428
6429 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006430 // need to be focusable
6431 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6432 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6433 return false;
6434 }
6435
6436 // need to be focusable in touch mode if in touch mode
6437 if (isInTouchMode() &&
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006438 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6439 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006440 }
6441
6442 // need to not have any parents blocking us
6443 if (hasAncestorThatBlocksDescendantFocus()) {
6444 return false;
6445 }
6446
6447 handleFocusGainInternal(direction, previouslyFocusedRect);
6448 return true;
6449 }
6450
6451 /**
6452 * Call this to try to give focus to a specific view or to one of its descendants. This is a
6453 * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6454 * touch mode to request focus when they are touched.
6455 *
6456 * @return Whether this view or one of its descendants actually took focus.
6457 *
6458 * @see #isInTouchMode()
6459 *
6460 */
6461 public final boolean requestFocusFromTouch() {
6462 // Leave touch mode if we need to
6463 if (isInTouchMode()) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006464 ViewRootImpl viewRoot = getViewRootImpl();
Christopher Tate2c095f32010-10-04 14:13:40 -07006465 if (viewRoot != null) {
6466 viewRoot.ensureTouchMode(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006467 }
6468 }
6469 return requestFocus(View.FOCUS_DOWN);
6470 }
6471
6472 /**
6473 * @return Whether any ancestor of this view blocks descendant focus.
6474 */
6475 private boolean hasAncestorThatBlocksDescendantFocus() {
6476 ViewParent ancestor = mParent;
6477 while (ancestor instanceof ViewGroup) {
6478 final ViewGroup vgAncestor = (ViewGroup) ancestor;
6479 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6480 return true;
6481 } else {
6482 ancestor = vgAncestor.getParent();
6483 }
6484 }
6485 return false;
6486 }
6487
6488 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07006489 * Gets the mode for determining whether this View is important for accessibility
6490 * which is if it fires accessibility events and if it is reported to
6491 * accessibility services that query the screen.
6492 *
6493 * @return The mode for determining whether a View is important for accessibility.
6494 *
6495 * @attr ref android.R.styleable#View_importantForAccessibility
6496 *
6497 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6498 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6499 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6500 */
6501 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07006502 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6503 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6504 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
Svetoslav Ganov42138042012-03-20 11:51:39 -07006505 })
6506 public int getImportantForAccessibility() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006507 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6508 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006509 }
6510
6511 /**
6512 * Sets how to determine whether this view is important for accessibility
6513 * which is if it fires accessibility events and if it is reported to
6514 * accessibility services that query the screen.
6515 *
6516 * @param mode How to determine whether this view is important for accessibility.
6517 *
6518 * @attr ref android.R.styleable#View_importantForAccessibility
6519 *
6520 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6521 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6522 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6523 */
6524 public void setImportantForAccessibility(int mode) {
6525 if (mode != getImportantForAccessibility()) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006526 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6527 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6528 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006529 notifyAccessibilityStateChanged();
6530 }
6531 }
6532
6533 /**
6534 * Gets whether this view should be exposed for accessibility.
6535 *
6536 * @return Whether the view is exposed for accessibility.
6537 *
6538 * @hide
6539 */
6540 public boolean isImportantForAccessibility() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006541 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6542 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006543 switch (mode) {
6544 case IMPORTANT_FOR_ACCESSIBILITY_YES:
6545 return true;
6546 case IMPORTANT_FOR_ACCESSIBILITY_NO:
6547 return false;
6548 case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
Svetoslav Ganov34caec92012-07-19 18:07:58 -07006549 return isActionableForAccessibility() || hasListenersForAccessibility()
6550 || getAccessibilityNodeProvider() != null;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006551 default:
6552 throw new IllegalArgumentException("Unknow important for accessibility mode: "
6553 + mode);
6554 }
6555 }
6556
6557 /**
6558 * Gets the parent for accessibility purposes. Note that the parent for
6559 * accessibility is not necessary the immediate parent. It is the first
6560 * predecessor that is important for accessibility.
6561 *
6562 * @return The parent for accessibility purposes.
6563 */
6564 public ViewParent getParentForAccessibility() {
6565 if (mParent instanceof View) {
6566 View parentView = (View) mParent;
6567 if (parentView.includeForAccessibility()) {
6568 return mParent;
6569 } else {
6570 return mParent.getParentForAccessibility();
6571 }
6572 }
6573 return null;
6574 }
6575
6576 /**
6577 * Adds the children of a given View for accessibility. Since some Views are
6578 * not important for accessibility the children for accessibility are not
6579 * necessarily direct children of the riew, rather they are the first level of
6580 * descendants important for accessibility.
6581 *
6582 * @param children The list of children for accessibility.
6583 */
6584 public void addChildrenForAccessibility(ArrayList<View> children) {
6585 if (includeForAccessibility()) {
6586 children.add(this);
6587 }
6588 }
6589
6590 /**
6591 * Whether to regard this view for accessibility. A view is regarded for
6592 * accessibility if it is important for accessibility or the querying
6593 * accessibility service has explicitly requested that view not
6594 * important for accessibility are regarded.
6595 *
6596 * @return Whether to regard the view for accessibility.
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006597 *
6598 * @hide
Svetoslav Ganov42138042012-03-20 11:51:39 -07006599 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006600 public boolean includeForAccessibility() {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006601 if (mAttachInfo != null) {
Romain Guyf0af1d52012-07-11 18:31:21 -07006602 return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006603 }
6604 return false;
6605 }
6606
6607 /**
6608 * Returns whether the View is considered actionable from
6609 * accessibility perspective. Such view are important for
6610 * accessiiblity.
6611 *
6612 * @return True if the view is actionable for accessibility.
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006613 *
6614 * @hide
Svetoslav Ganov42138042012-03-20 11:51:39 -07006615 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006616 public boolean isActionableForAccessibility() {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006617 return (isClickable() || isLongClickable() || isFocusable());
6618 }
6619
6620 /**
6621 * Returns whether the View has registered callbacks wich makes it
6622 * important for accessiiblity.
6623 *
6624 * @return True if the view is actionable for accessibility.
6625 */
6626 private boolean hasListenersForAccessibility() {
6627 ListenerInfo info = getListenerInfo();
6628 return mTouchDelegate != null || info.mOnKeyListener != null
6629 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6630 || info.mOnHoverListener != null || info.mOnDragListener != null;
6631 }
6632
6633 /**
6634 * Notifies accessibility services that some view's important for
6635 * accessibility state has changed. Note that such notifications
6636 * are made at most once every
6637 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6638 * to avoid unnecessary load to the system. Also once a view has
6639 * made a notifucation this method is a NOP until the notification has
6640 * been sent to clients.
6641 *
6642 * @hide
6643 *
6644 * TODO: Makse sure this method is called for any view state change
6645 * that is interesting for accessilility purposes.
6646 */
6647 public void notifyAccessibilityStateChanged() {
Svetoslav Ganovc406be92012-05-11 16:12:32 -07006648 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6649 return;
6650 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07006651 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
6652 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006653 if (mParent != null) {
6654 mParent.childAccessibilityStateChanged(this);
6655 }
6656 }
6657 }
6658
6659 /**
6660 * Reset the state indicating the this view has requested clients
6661 * interested in its accessiblity state to be notified.
6662 *
6663 * @hide
6664 */
6665 public void resetAccessibilityStateChanged() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006666 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006667 }
6668
6669 /**
6670 * Performs the specified accessibility action on the view. For
6671 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
alanv8eeefef2012-05-07 16:57:53 -07006672 * <p>
6673 * If an {@link AccessibilityDelegate} has been specified via calling
6674 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6675 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
6676 * is responsible for handling this call.
6677 * </p>
Svetoslav Ganov42138042012-03-20 11:51:39 -07006678 *
6679 * @param action The action to perform.
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006680 * @param arguments Optional action arguments.
Svetoslav Ganov42138042012-03-20 11:51:39 -07006681 * @return Whether the action was performed.
6682 */
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006683 public boolean performAccessibilityAction(int action, Bundle arguments) {
alanv8eeefef2012-05-07 16:57:53 -07006684 if (mAccessibilityDelegate != null) {
6685 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
6686 } else {
6687 return performAccessibilityActionInternal(action, arguments);
6688 }
6689 }
6690
6691 /**
6692 * @see #performAccessibilityAction(int, Bundle)
6693 *
6694 * Note: Called from the default {@link AccessibilityDelegate}.
6695 */
6696 boolean performAccessibilityActionInternal(int action, Bundle arguments) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006697 switch (action) {
6698 case AccessibilityNodeInfo.ACTION_CLICK: {
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006699 if (isClickable()) {
Svetoslav Ganov773f2622012-05-05 19:59:42 -07006700 return performClick();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006701 }
6702 } break;
6703 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6704 if (isLongClickable()) {
Svetoslav Ganov773f2622012-05-05 19:59:42 -07006705 return performLongClick();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006706 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006707 } break;
6708 case AccessibilityNodeInfo.ACTION_FOCUS: {
6709 if (!hasFocus()) {
6710 // Get out of touch mode since accessibility
6711 // wants to move focus around.
6712 getViewRootImpl().ensureTouchMode(false);
6713 return requestFocus();
6714 }
6715 } break;
6716 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
6717 if (hasFocus()) {
6718 clearFocus();
6719 return !isFocused();
6720 }
6721 } break;
6722 case AccessibilityNodeInfo.ACTION_SELECT: {
6723 if (!isSelected()) {
6724 setSelected(true);
6725 return isSelected();
6726 }
6727 } break;
6728 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
6729 if (isSelected()) {
6730 setSelected(false);
6731 return !isSelected();
6732 }
6733 } break;
6734 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07006735 if (!isAccessibilityFocused()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006736 return requestAccessibilityFocus();
6737 }
6738 } break;
6739 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
6740 if (isAccessibilityFocused()) {
6741 clearAccessibilityFocus();
6742 return true;
6743 }
6744 } break;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006745 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
6746 if (arguments != null) {
6747 final int granularity = arguments.getInt(
6748 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6749 return nextAtGranularity(granularity);
6750 }
6751 } break;
6752 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
6753 if (arguments != null) {
6754 final int granularity = arguments.getInt(
6755 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6756 return previousAtGranularity(granularity);
6757 }
6758 } break;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006759 }
6760 return false;
6761 }
6762
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006763 private boolean nextAtGranularity(int granularity) {
6764 CharSequence text = getIterableTextForAccessibility();
Svetoslav Ganov64899e52012-05-15 21:09:30 -07006765 if (text == null || text.length() == 0) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006766 return false;
6767 }
6768 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6769 if (iterator == null) {
6770 return false;
6771 }
6772 final int current = getAccessibilityCursorPosition();
6773 final int[] range = iterator.following(current);
6774 if (range == null) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006775 return false;
6776 }
6777 final int start = range[0];
6778 final int end = range[1];
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006779 setAccessibilityCursorPosition(end);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006780 sendViewTextTraversedAtGranularityEvent(
6781 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
6782 granularity, start, end);
6783 return true;
6784 }
6785
6786 private boolean previousAtGranularity(int granularity) {
6787 CharSequence text = getIterableTextForAccessibility();
Svetoslav Ganov64899e52012-05-15 21:09:30 -07006788 if (text == null || text.length() == 0) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006789 return false;
6790 }
6791 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6792 if (iterator == null) {
6793 return false;
6794 }
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006795 int current = getAccessibilityCursorPosition();
6796 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
6797 current = text.length();
6798 } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6799 // When traversing by character we always put the cursor after the character
6800 // to ease edit and have to compensate before asking the for previous segment.
6801 current--;
6802 }
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006803 final int[] range = iterator.preceding(current);
6804 if (range == null) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006805 return false;
6806 }
6807 final int start = range[0];
6808 final int end = range[1];
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006809 // Always put the cursor after the character to ease edit.
6810 if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6811 setAccessibilityCursorPosition(end);
6812 } else {
6813 setAccessibilityCursorPosition(start);
6814 }
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006815 sendViewTextTraversedAtGranularityEvent(
6816 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
6817 granularity, start, end);
6818 return true;
6819 }
6820
6821 /**
6822 * Gets the text reported for accessibility purposes.
6823 *
6824 * @return The accessibility text.
6825 *
6826 * @hide
6827 */
6828 public CharSequence getIterableTextForAccessibility() {
Svetoslav Ganov05282aa2012-09-06 18:59:29 -07006829 return getContentDescription();
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006830 }
6831
6832 /**
6833 * @hide
6834 */
6835 public int getAccessibilityCursorPosition() {
6836 return mAccessibilityCursorPosition;
6837 }
6838
6839 /**
6840 * @hide
6841 */
6842 public void setAccessibilityCursorPosition(int position) {
6843 mAccessibilityCursorPosition = position;
6844 }
6845
6846 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
6847 int fromIndex, int toIndex) {
6848 if (mParent == null) {
6849 return;
6850 }
6851 AccessibilityEvent event = AccessibilityEvent.obtain(
6852 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
6853 onInitializeAccessibilityEvent(event);
6854 onPopulateAccessibilityEvent(event);
6855 event.setFromIndex(fromIndex);
6856 event.setToIndex(toIndex);
6857 event.setAction(action);
6858 event.setMovementGranularity(granularity);
6859 mParent.requestSendAccessibilityEvent(this, event);
6860 }
6861
6862 /**
6863 * @hide
6864 */
6865 public TextSegmentIterator getIteratorForGranularity(int granularity) {
6866 switch (granularity) {
6867 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
6868 CharSequence text = getIterableTextForAccessibility();
6869 if (text != null && text.length() > 0) {
6870 CharacterTextSegmentIterator iterator =
Svetoslav Ganovbbd31552012-06-11 12:08:18 -07006871 CharacterTextSegmentIterator.getInstance(
6872 mContext.getResources().getConfiguration().locale);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006873 iterator.initialize(text.toString());
6874 return iterator;
6875 }
6876 } break;
6877 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
6878 CharSequence text = getIterableTextForAccessibility();
6879 if (text != null && text.length() > 0) {
6880 WordTextSegmentIterator iterator =
Svetoslav Ganovbbd31552012-06-11 12:08:18 -07006881 WordTextSegmentIterator.getInstance(
6882 mContext.getResources().getConfiguration().locale);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006883 iterator.initialize(text.toString());
6884 return iterator;
6885 }
6886 } break;
6887 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
6888 CharSequence text = getIterableTextForAccessibility();
6889 if (text != null && text.length() > 0) {
6890 ParagraphTextSegmentIterator iterator =
6891 ParagraphTextSegmentIterator.getInstance();
6892 iterator.initialize(text.toString());
6893 return iterator;
6894 }
6895 } break;
6896 }
6897 return null;
6898 }
6899
Svetoslav Ganov42138042012-03-20 11:51:39 -07006900 /**
Romain Guya440b002010-02-24 15:57:54 -08006901 * @hide
6902 */
6903 public void dispatchStartTemporaryDetach() {
Svetoslav Ganov961bf0e2012-05-08 09:40:03 -07006904 clearAccessibilityFocus();
Romain Guy38c2ece2012-05-24 14:20:56 -07006905 clearDisplayList();
6906
Romain Guya440b002010-02-24 15:57:54 -08006907 onStartTemporaryDetach();
6908 }
6909
6910 /**
6911 * This is called when a container is going to temporarily detach a child, with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006912 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
6913 * It will either be followed by {@link #onFinishTemporaryDetach()} or
Romain Guya440b002010-02-24 15:57:54 -08006914 * {@link #onDetachedFromWindow()} when the container is done.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006915 */
6916 public void onStartTemporaryDetach() {
Romain Guya440b002010-02-24 15:57:54 -08006917 removeUnsetPressCallback();
Dianne Hackborn4702a852012-08-17 15:18:29 -07006918 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
Romain Guya440b002010-02-24 15:57:54 -08006919 }
6920
6921 /**
6922 * @hide
6923 */
6924 public void dispatchFinishTemporaryDetach() {
6925 onFinishTemporaryDetach();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006926 }
Romain Guy8506ab42009-06-11 17:35:47 -07006927
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006928 /**
6929 * Called after {@link #onStartTemporaryDetach} when the container is done
6930 * changing the view.
6931 */
6932 public void onFinishTemporaryDetach() {
6933 }
Romain Guy8506ab42009-06-11 17:35:47 -07006934
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006935 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006936 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
6937 * for this view's window. Returns null if the view is not currently attached
6938 * to the window. Normally you will not need to use this directly, but
Romain Guy5c22a8c2011-05-13 11:48:45 -07006939 * just use the standard high-level event callbacks like
6940 * {@link #onKeyDown(int, KeyEvent)}.
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006941 */
6942 public KeyEvent.DispatcherState getKeyDispatcherState() {
6943 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
6944 }
Joe Malin32736f02011-01-19 16:14:20 -08006945
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006946 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006947 * Dispatch a key event before it is processed by any input method
6948 * associated with the view hierarchy. This can be used to intercept
6949 * key events in special situations before the IME consumes them; a
6950 * typical example would be handling the BACK key to update the application's
6951 * UI instead of allowing the IME to see it and close itself.
6952 *
6953 * @param event The key event to be dispatched.
6954 * @return True if the event was handled, false otherwise.
6955 */
6956 public boolean dispatchKeyEventPreIme(KeyEvent event) {
6957 return onKeyPreIme(event.getKeyCode(), event);
6958 }
6959
6960 /**
6961 * Dispatch a key event to the next view on the focus path. This path runs
6962 * from the top of the view tree down to the currently focused view. If this
6963 * view has focus, it will dispatch to itself. Otherwise it will dispatch
6964 * the next node down the focus path. This method also fires any key
6965 * listeners.
6966 *
6967 * @param event The key event to be dispatched.
6968 * @return True if the event was handled, false otherwise.
6969 */
6970 public boolean dispatchKeyEvent(KeyEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006971 if (mInputEventConsistencyVerifier != null) {
6972 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
6973 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006974
Jeff Brown21bc5c92011-02-28 18:27:14 -08006975 // Give any attached key listener a first crack at the event.
Romain Guyf607bdc2010-09-10 19:20:06 -07006976 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07006977 ListenerInfo li = mListenerInfo;
6978 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
6979 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006980 return true;
6981 }
6982
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006983 if (event.dispatch(this, mAttachInfo != null
6984 ? mAttachInfo.mKeyDispatchState : null, this)) {
6985 return true;
6986 }
6987
6988 if (mInputEventConsistencyVerifier != null) {
6989 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
6990 }
6991 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006992 }
6993
6994 /**
6995 * Dispatches a key shortcut event.
6996 *
6997 * @param event The key event to be dispatched.
6998 * @return True if the event was handled by the view, false otherwise.
6999 */
7000 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
7001 return onKeyShortcut(event.getKeyCode(), event);
7002 }
7003
7004 /**
7005 * Pass the touch screen motion event down to the target view, or this
7006 * view if it is the target.
7007 *
7008 * @param event The motion event to be dispatched.
7009 * @return True if the event was handled by the view, false otherwise.
7010 */
7011 public boolean dispatchTouchEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08007012 if (mInputEventConsistencyVerifier != null) {
7013 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
7014 }
7015
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007016 if (onFilterTouchEventForSecurity(event)) {
7017 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007018 ListenerInfo li = mListenerInfo;
7019 if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
7020 && li.mOnTouchListener.onTouch(this, event)) {
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007021 return true;
7022 }
7023
7024 if (onTouchEvent(event)) {
7025 return true;
7026 }
Jeff Brown85a31762010-09-01 17:01:00 -07007027 }
7028
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007029 if (mInputEventConsistencyVerifier != null) {
7030 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007031 }
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007032 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007033 }
7034
7035 /**
Jeff Brown85a31762010-09-01 17:01:00 -07007036 * Filter the touch event to apply security policies.
7037 *
7038 * @param event The motion event to be filtered.
7039 * @return True if the event should be dispatched, false if the event should be dropped.
Joe Malin32736f02011-01-19 16:14:20 -08007040 *
Jeff Brown85a31762010-09-01 17:01:00 -07007041 * @see #getFilterTouchesWhenObscured
7042 */
7043 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
Romain Guyf607bdc2010-09-10 19:20:06 -07007044 //noinspection RedundantIfStatement
Jeff Brown85a31762010-09-01 17:01:00 -07007045 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
7046 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
7047 // Window is obscured, drop this touch.
7048 return false;
7049 }
7050 return true;
7051 }
7052
7053 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007054 * Pass a trackball motion event down to the focused view.
7055 *
7056 * @param event The motion event to be dispatched.
7057 * @return True if the event was handled by the view, false otherwise.
7058 */
7059 public boolean dispatchTrackballEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08007060 if (mInputEventConsistencyVerifier != null) {
7061 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
7062 }
7063
Romain Guy02ccac62011-06-24 13:20:23 -07007064 return onTrackballEvent(event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007065 }
7066
7067 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08007068 * Dispatch a generic motion event.
7069 * <p>
7070 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7071 * are delivered to the view under the pointer. All other generic motion events are
Jeff Browna032cc02011-03-07 16:56:21 -08007072 * delivered to the focused view. Hover events are handled specially and are delivered
Romain Guy5c22a8c2011-05-13 11:48:45 -07007073 * to {@link #onHoverEvent(MotionEvent)}.
Jeff Brown33bbfd22011-02-24 20:55:35 -08007074 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -08007075 *
7076 * @param event The motion event to be dispatched.
7077 * @return True if the event was handled by the view, false otherwise.
7078 */
7079 public boolean dispatchGenericMotionEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08007080 if (mInputEventConsistencyVerifier != null) {
7081 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
7082 }
7083
Jeff Browna032cc02011-03-07 16:56:21 -08007084 final int source = event.getSource();
7085 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
7086 final int action = event.getAction();
7087 if (action == MotionEvent.ACTION_HOVER_ENTER
7088 || action == MotionEvent.ACTION_HOVER_MOVE
7089 || action == MotionEvent.ACTION_HOVER_EXIT) {
7090 if (dispatchHoverEvent(event)) {
7091 return true;
7092 }
7093 } else if (dispatchGenericPointerEvent(event)) {
7094 return true;
7095 }
7096 } else if (dispatchGenericFocusedEvent(event)) {
7097 return true;
7098 }
7099
Jeff Brown10b62902011-06-20 16:40:37 -07007100 if (dispatchGenericMotionEventInternal(event)) {
7101 return true;
7102 }
7103
7104 if (mInputEventConsistencyVerifier != null) {
7105 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7106 }
7107 return false;
7108 }
7109
7110 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
Romain Guy7b5b6ab2011-03-14 18:05:08 -07007111 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007112 ListenerInfo li = mListenerInfo;
7113 if (li != null && li.mOnGenericMotionListener != null
7114 && (mViewFlags & ENABLED_MASK) == ENABLED
7115 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08007116 return true;
7117 }
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007118
7119 if (onGenericMotionEvent(event)) {
7120 return true;
7121 }
7122
7123 if (mInputEventConsistencyVerifier != null) {
7124 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7125 }
7126 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08007127 }
7128
7129 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007130 * Dispatch a hover event.
7131 * <p>
Philip Milne6c8ea062012-04-03 17:38:43 -07007132 * Do not call this method directly.
Romain Guy5c22a8c2011-05-13 11:48:45 -07007133 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007134 * </p>
7135 *
7136 * @param event The motion event to be dispatched.
7137 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007138 */
7139 protected boolean dispatchHoverEvent(MotionEvent event) {
Romain Guy02ccac62011-06-24 13:20:23 -07007140 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007141 ListenerInfo li = mListenerInfo;
7142 if (li != null && li.mOnHoverListener != null
7143 && (mViewFlags & ENABLED_MASK) == ENABLED
7144 && li.mOnHoverListener.onHover(this, event)) {
Jeff Brown10b62902011-06-20 16:40:37 -07007145 return true;
7146 }
7147
Jeff Browna032cc02011-03-07 16:56:21 -08007148 return onHoverEvent(event);
7149 }
7150
7151 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07007152 * Returns true if the view has a child to which it has recently sent
7153 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
7154 * it does not have a hovered child, then it must be the innermost hovered view.
7155 * @hide
7156 */
7157 protected boolean hasHoveredChild() {
7158 return false;
7159 }
7160
7161 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007162 * Dispatch a generic motion event to the view under the first pointer.
7163 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007164 * Do not call this method directly.
7165 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007166 * </p>
7167 *
7168 * @param event The motion event to be dispatched.
7169 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007170 */
7171 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7172 return false;
7173 }
7174
7175 /**
7176 * Dispatch a generic motion event to the currently focused view.
7177 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007178 * Do not call this method directly.
7179 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007180 * </p>
7181 *
7182 * @param event The motion event to be dispatched.
7183 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007184 */
7185 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7186 return false;
7187 }
7188
7189 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08007190 * Dispatch a pointer event.
7191 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007192 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7193 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
7194 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
Jeff Brown33bbfd22011-02-24 20:55:35 -08007195 * and should not be expected to handle other pointing device features.
7196 * </p>
7197 *
7198 * @param event The motion event to be dispatched.
7199 * @return True if the event was handled by the view, false otherwise.
7200 * @hide
7201 */
7202 public final boolean dispatchPointerEvent(MotionEvent event) {
7203 if (event.isTouchEvent()) {
7204 return dispatchTouchEvent(event);
7205 } else {
7206 return dispatchGenericMotionEvent(event);
7207 }
7208 }
7209
7210 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 * Called when the window containing this view gains or loses window focus.
7212 * ViewGroups should override to route to their children.
7213 *
7214 * @param hasFocus True if the window containing this view now has focus,
7215 * false otherwise.
7216 */
7217 public void dispatchWindowFocusChanged(boolean hasFocus) {
7218 onWindowFocusChanged(hasFocus);
7219 }
7220
7221 /**
7222 * Called when the window containing this view gains or loses focus. Note
7223 * that this is separate from view focus: to receive key events, both
7224 * your view and its window must have focus. If a window is displayed
7225 * on top of yours that takes input focus, then your own window will lose
7226 * focus but the view focus will remain unchanged.
7227 *
7228 * @param hasWindowFocus True if the window containing this view now has
7229 * focus, false otherwise.
7230 */
7231 public void onWindowFocusChanged(boolean hasWindowFocus) {
7232 InputMethodManager imm = InputMethodManager.peekInstance();
7233 if (!hasWindowFocus) {
7234 if (isPressed()) {
7235 setPressed(false);
7236 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07007237 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007238 imm.focusOut(this);
7239 }
Maryam Garrett1549dd12009-12-15 16:06:36 -05007240 removeLongPressCallback();
Tony Wu26edf202010-09-13 19:54:00 +08007241 removeTapCallback();
Romain Guya2431d02009-04-30 16:30:00 -07007242 onFocusLost();
Dianne Hackborn4702a852012-08-17 15:18:29 -07007243 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007244 imm.focusIn(this);
7245 }
7246 refreshDrawableState();
7247 }
7248
7249 /**
7250 * Returns true if this view is in a window that currently has window focus.
7251 * Note that this is not the same as the view itself having focus.
7252 *
7253 * @return True if this view is in a window that currently has window focus.
7254 */
7255 public boolean hasWindowFocus() {
7256 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7257 }
7258
7259 /**
Adam Powell326d8082009-12-09 15:10:07 -08007260 * Dispatch a view visibility change down the view hierarchy.
7261 * ViewGroups should override to route to their children.
7262 * @param changedView The view whose visibility changed. Could be 'this' or
7263 * an ancestor view.
Romain Guy43c9cdf2010-01-27 13:53:55 -08007264 * @param visibility The new visibility of changedView: {@link #VISIBLE},
7265 * {@link #INVISIBLE} or {@link #GONE}.
Adam Powell326d8082009-12-09 15:10:07 -08007266 */
7267 protected void dispatchVisibilityChanged(View changedView, int visibility) {
7268 onVisibilityChanged(changedView, visibility);
7269 }
7270
7271 /**
7272 * Called when the visibility of the view or an ancestor of the view is changed.
7273 * @param changedView The view whose visibility changed. Could be 'this' or
7274 * an ancestor view.
Romain Guy43c9cdf2010-01-27 13:53:55 -08007275 * @param visibility The new visibility of changedView: {@link #VISIBLE},
7276 * {@link #INVISIBLE} or {@link #GONE}.
Adam Powell326d8082009-12-09 15:10:07 -08007277 */
7278 protected void onVisibilityChanged(View changedView, int visibility) {
Adam Powell8568c3a2010-04-19 14:26:11 -07007279 if (visibility == VISIBLE) {
7280 if (mAttachInfo != null) {
7281 initialAwakenScrollBars();
7282 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007283 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
Adam Powell8568c3a2010-04-19 14:26:11 -07007284 }
7285 }
Adam Powell326d8082009-12-09 15:10:07 -08007286 }
7287
7288 /**
Romain Guy43c9cdf2010-01-27 13:53:55 -08007289 * Dispatch a hint about whether this view is displayed. For instance, when
7290 * a View moves out of the screen, it might receives a display hint indicating
7291 * the view is not displayed. Applications should not <em>rely</em> on this hint
7292 * as there is no guarantee that they will receive one.
Joe Malin32736f02011-01-19 16:14:20 -08007293 *
Romain Guy43c9cdf2010-01-27 13:53:55 -08007294 * @param hint A hint about whether or not this view is displayed:
7295 * {@link #VISIBLE} or {@link #INVISIBLE}.
7296 */
7297 public void dispatchDisplayHint(int hint) {
7298 onDisplayHint(hint);
7299 }
7300
7301 /**
7302 * Gives this view a hint about whether is displayed or not. For instance, when
7303 * a View moves out of the screen, it might receives a display hint indicating
7304 * the view is not displayed. Applications should not <em>rely</em> on this hint
7305 * as there is no guarantee that they will receive one.
Joe Malin32736f02011-01-19 16:14:20 -08007306 *
Romain Guy43c9cdf2010-01-27 13:53:55 -08007307 * @param hint A hint about whether or not this view is displayed:
7308 * {@link #VISIBLE} or {@link #INVISIBLE}.
7309 */
7310 protected void onDisplayHint(int hint) {
7311 }
7312
7313 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007314 * Dispatch a window visibility change down the view hierarchy.
7315 * ViewGroups should override to route to their children.
7316 *
7317 * @param visibility The new visibility of the window.
7318 *
Philip Milne6c8ea062012-04-03 17:38:43 -07007319 * @see #onWindowVisibilityChanged(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007320 */
7321 public void dispatchWindowVisibilityChanged(int visibility) {
7322 onWindowVisibilityChanged(visibility);
7323 }
7324
7325 /**
7326 * Called when the window containing has change its visibility
7327 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
7328 * that this tells you whether or not your window is being made visible
7329 * to the window manager; this does <em>not</em> tell you whether or not
7330 * your window is obscured by other windows on the screen, even if it
7331 * is itself visible.
7332 *
7333 * @param visibility The new visibility of the window.
7334 */
7335 protected void onWindowVisibilityChanged(int visibility) {
Adam Powell8568c3a2010-04-19 14:26:11 -07007336 if (visibility == VISIBLE) {
7337 initialAwakenScrollBars();
7338 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007339 }
7340
7341 /**
7342 * Returns the current visibility of the window this view is attached to
7343 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7344 *
7345 * @return Returns the current visibility of the view's window.
7346 */
7347 public int getWindowVisibility() {
7348 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7349 }
7350
7351 /**
7352 * Retrieve the overall visible display size in which the window this view is
7353 * attached to has been positioned in. This takes into account screen
7354 * decorations above the window, for both cases where the window itself
7355 * is being position inside of them or the window is being placed under
7356 * then and covered insets are used for the window to position its content
7357 * inside. In effect, this tells you the available area where content can
7358 * be placed and remain visible to users.
7359 *
7360 * <p>This function requires an IPC back to the window manager to retrieve
7361 * the requested information, so should not be used in performance critical
7362 * code like drawing.
7363 *
7364 * @param outRect Filled in with the visible display frame. If the view
7365 * is not attached to a window, this is simply the raw display size.
7366 */
7367 public void getWindowVisibleDisplayFrame(Rect outRect) {
7368 if (mAttachInfo != null) {
7369 try {
7370 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7371 } catch (RemoteException e) {
7372 return;
7373 }
7374 // XXX This is really broken, and probably all needs to be done
7375 // in the window manager, and we need to know more about whether
7376 // we want the area behind or in front of the IME.
7377 final Rect insets = mAttachInfo.mVisibleInsets;
7378 outRect.left += insets.left;
7379 outRect.top += insets.top;
7380 outRect.right -= insets.right;
7381 outRect.bottom -= insets.bottom;
7382 return;
7383 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07007384 // The view is not attached to a display so we don't have a context.
7385 // Make a best guess about the display size.
7386 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07007387 d.getRectSize(outRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007388 }
7389
7390 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007391 * Dispatch a notification about a resource configuration change down
7392 * the view hierarchy.
7393 * ViewGroups should override to route to their children.
7394 *
7395 * @param newConfig The new resource configuration.
7396 *
Philip Milne6c8ea062012-04-03 17:38:43 -07007397 * @see #onConfigurationChanged(android.content.res.Configuration)
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007398 */
7399 public void dispatchConfigurationChanged(Configuration newConfig) {
7400 onConfigurationChanged(newConfig);
7401 }
7402
7403 /**
7404 * Called when the current configuration of the resources being used
7405 * by the application have changed. You can use this to decide when
7406 * to reload resources that can changed based on orientation and other
7407 * configuration characterstics. You only need to use this if you are
7408 * not relying on the normal {@link android.app.Activity} mechanism of
7409 * recreating the activity instance upon a configuration change.
7410 *
7411 * @param newConfig The new resource configuration.
7412 */
7413 protected void onConfigurationChanged(Configuration newConfig) {
7414 }
7415
7416 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007417 * Private function to aggregate all per-view attributes in to the view
7418 * root.
7419 */
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007420 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7421 performCollectViewAttributes(attachInfo, visibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007422 }
7423
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007424 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7425 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
Joe Onorato664644d2011-01-23 17:53:23 -08007426 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007427 attachInfo.mKeepScreenOn = true;
Joe Onorato664644d2011-01-23 17:53:23 -08007428 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007429 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007430 ListenerInfo li = mListenerInfo;
7431 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007432 attachInfo.mHasSystemUiListeners = true;
Joe Onorato664644d2011-01-23 17:53:23 -08007433 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007434 }
7435 }
7436
7437 void needGlobalAttributesUpdate(boolean force) {
Joe Onorato664644d2011-01-23 17:53:23 -08007438 final AttachInfo ai = mAttachInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007439 if (ai != null) {
Joe Onorato664644d2011-01-23 17:53:23 -08007440 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7441 || ai.mHasSystemUiListeners) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007442 ai.mRecomputeGlobalAttributes = true;
7443 }
7444 }
7445 }
7446
7447 /**
7448 * Returns whether the device is currently in touch mode. Touch mode is entered
7449 * once the user begins interacting with the device by touch, and affects various
7450 * things like whether focus is always visible to the user.
7451 *
7452 * @return Whether the device is in touch mode.
7453 */
7454 @ViewDebug.ExportedProperty
7455 public boolean isInTouchMode() {
7456 if (mAttachInfo != null) {
7457 return mAttachInfo.mInTouchMode;
7458 } else {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007459 return ViewRootImpl.isInTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 }
7461 }
7462
7463 /**
7464 * Returns the context the view is running in, through which it can
7465 * access the current theme, resources, etc.
7466 *
7467 * @return The view's Context.
7468 */
7469 @ViewDebug.CapturedViewProperty
7470 public final Context getContext() {
7471 return mContext;
7472 }
7473
7474 /**
7475 * Handle a key event before it is processed by any input method
7476 * associated with the view hierarchy. This can be used to intercept
7477 * key events in special situations before the IME consumes them; a
7478 * typical example would be handling the BACK key to update the application's
7479 * UI instead of allowing the IME to see it and close itself.
7480 *
7481 * @param keyCode The value in event.getKeyCode().
7482 * @param event Description of the key event.
7483 * @return If you handled the event, return true. If you want to allow the
7484 * event to be handled by the next receiver, return false.
7485 */
7486 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7487 return false;
7488 }
7489
7490 /**
Jeff Brown995e7742010-12-22 16:59:36 -08007491 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7492 * KeyEvent.Callback.onKeyDown()}: perform press of the view
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007493 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7494 * is released, if the view is enabled and clickable.
7495 *
Jean Chalard405bc512012-05-29 19:12:34 +09007496 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7497 * although some may elect to do so in some situations. Do not rely on this to
7498 * catch software key presses.
7499 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007500 * @param keyCode A key code that represents the button pressed, from
7501 * {@link android.view.KeyEvent}.
7502 * @param event The KeyEvent object that defines the button action.
7503 */
7504 public boolean onKeyDown(int keyCode, KeyEvent event) {
7505 boolean result = false;
7506
7507 switch (keyCode) {
7508 case KeyEvent.KEYCODE_DPAD_CENTER:
7509 case KeyEvent.KEYCODE_ENTER: {
7510 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7511 return true;
7512 }
7513 // Long clickable items don't necessarily have to be clickable
7514 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7515 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7516 (event.getRepeatCount() == 0)) {
7517 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007518 checkForLongClick(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007519 return true;
7520 }
7521 break;
7522 }
7523 }
7524 return result;
7525 }
7526
7527 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007528 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7529 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7530 * the event).
Jean Chalard405bc512012-05-29 19:12:34 +09007531 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7532 * although some may elect to do so in some situations. Do not rely on this to
7533 * catch software key presses.
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007534 */
7535 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7536 return false;
7537 }
7538
7539 /**
Jeff Brown995e7742010-12-22 16:59:36 -08007540 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7541 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007542 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7543 * {@link KeyEvent#KEYCODE_ENTER} is released.
Jean Chalard405bc512012-05-29 19:12:34 +09007544 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7545 * although some may elect to do so in some situations. Do not rely on this to
7546 * catch software key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007547 *
7548 * @param keyCode A key code that represents the button pressed, from
7549 * {@link android.view.KeyEvent}.
7550 * @param event The KeyEvent object that defines the button action.
7551 */
7552 public boolean onKeyUp(int keyCode, KeyEvent event) {
7553 boolean result = false;
7554
7555 switch (keyCode) {
7556 case KeyEvent.KEYCODE_DPAD_CENTER:
7557 case KeyEvent.KEYCODE_ENTER: {
7558 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7559 return true;
7560 }
7561 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7562 setPressed(false);
7563
7564 if (!mHasPerformedLongPress) {
7565 // This is a tap, so remove the longpress check
Maryam Garrett1549dd12009-12-15 16:06:36 -05007566 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007567
7568 result = performClick();
7569 }
7570 }
7571 break;
7572 }
7573 }
7574 return result;
7575 }
7576
7577 /**
7578 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7579 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7580 * the event).
Jean Chalard405bc512012-05-29 19:12:34 +09007581 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7582 * although some may elect to do so in some situations. Do not rely on this to
7583 * catch software key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007584 *
7585 * @param keyCode A key code that represents the button pressed, from
7586 * {@link android.view.KeyEvent}.
7587 * @param repeatCount The number of times the action was made.
7588 * @param event The KeyEvent object that defines the button action.
7589 */
7590 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7591 return false;
7592 }
7593
7594 /**
Jeff Brown64da12a2011-01-04 19:57:47 -08007595 * Called on the focused view when a key shortcut event is not handled.
7596 * Override this method to implement local key shortcuts for the View.
7597 * Key shortcuts can also be implemented by setting the
7598 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007599 *
7600 * @param keyCode The value in event.getKeyCode().
7601 * @param event Description of the key event.
7602 * @return If you handled the event, return true. If you want to allow the
7603 * event to be handled by the next receiver, return false.
7604 */
7605 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7606 return false;
7607 }
7608
7609 /**
7610 * Check whether the called view is a text editor, in which case it
7611 * would make sense to automatically display a soft input window for
7612 * it. Subclasses should override this if they implement
7613 * {@link #onCreateInputConnection(EditorInfo)} to return true if
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007614 * a call on that method would return a non-null InputConnection, and
7615 * they are really a first-class editor that the user would normally
7616 * start typing on when the go into a window containing your view.
Romain Guy8506ab42009-06-11 17:35:47 -07007617 *
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007618 * <p>The default implementation always returns false. This does
7619 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7620 * will not be called or the user can not otherwise perform edits on your
7621 * view; it is just a hint to the system that this is not the primary
7622 * purpose of this view.
Romain Guy8506ab42009-06-11 17:35:47 -07007623 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007624 * @return Returns true if this view is a text editor, else false.
7625 */
7626 public boolean onCheckIsTextEditor() {
7627 return false;
7628 }
Romain Guy8506ab42009-06-11 17:35:47 -07007629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007630 /**
7631 * Create a new InputConnection for an InputMethod to interact
7632 * with the view. The default implementation returns null, since it doesn't
7633 * support input methods. You can override this to implement such support.
7634 * This is only needed for views that take focus and text input.
Romain Guy8506ab42009-06-11 17:35:47 -07007635 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007636 * <p>When implementing this, you probably also want to implement
7637 * {@link #onCheckIsTextEditor()} to indicate you will return a
7638 * non-null InputConnection.
7639 *
7640 * @param outAttrs Fill in with attribute information about the connection.
7641 */
7642 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
7643 return null;
7644 }
7645
7646 /**
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007647 * Called by the {@link android.view.inputmethod.InputMethodManager}
7648 * when a view who is not the current
7649 * input connection target is trying to make a call on the manager. The
7650 * default implementation returns false; you can override this to return
7651 * true for certain views if you are performing InputConnection proxying
7652 * to them.
7653 * @param view The View that is making the InputMethodManager call.
7654 * @return Return true to allow the call, false to reject.
7655 */
7656 public boolean checkInputConnectionProxy(View view) {
7657 return false;
7658 }
Romain Guy8506ab42009-06-11 17:35:47 -07007659
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007660 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007661 * Show the context menu for this view. It is not safe to hold on to the
7662 * menu after returning from this method.
7663 *
Gilles Debunnef788a9f2010-07-22 10:17:23 -07007664 * You should normally not overload this method. Overload
7665 * {@link #onCreateContextMenu(ContextMenu)} or define an
7666 * {@link OnCreateContextMenuListener} to add items to the context menu.
7667 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007668 * @param menu The context menu to populate
7669 */
7670 public void createContextMenu(ContextMenu menu) {
7671 ContextMenuInfo menuInfo = getContextMenuInfo();
7672
7673 // Sets the current menu info so all items added to menu will have
7674 // my extra info set.
7675 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
7676
7677 onCreateContextMenu(menu);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007678 ListenerInfo li = mListenerInfo;
7679 if (li != null && li.mOnCreateContextMenuListener != null) {
7680 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007681 }
7682
7683 // Clear the extra information so subsequent items that aren't mine don't
7684 // have my extra info.
7685 ((MenuBuilder)menu).setCurrentMenuInfo(null);
7686
7687 if (mParent != null) {
7688 mParent.createContextMenu(menu);
7689 }
7690 }
7691
7692 /**
7693 * Views should implement this if they have extra information to associate
7694 * with the context menu. The return result is supplied as a parameter to
7695 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
7696 * callback.
7697 *
7698 * @return Extra information about the item for which the context menu
7699 * should be shown. This information will vary across different
7700 * subclasses of View.
7701 */
7702 protected ContextMenuInfo getContextMenuInfo() {
7703 return null;
7704 }
7705
7706 /**
7707 * Views should implement this if the view itself is going to add items to
7708 * the context menu.
7709 *
7710 * @param menu the context menu to populate
7711 */
7712 protected void onCreateContextMenu(ContextMenu menu) {
7713 }
7714
7715 /**
7716 * Implement this method to handle trackball motion events. The
7717 * <em>relative</em> movement of the trackball since the last event
7718 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
7719 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
7720 * that a movement of 1 corresponds to the user pressing one DPAD key (so
7721 * they will often be fractional values, representing the more fine-grained
7722 * movement information available from a trackball).
7723 *
7724 * @param event The motion event.
7725 * @return True if the event was handled, false otherwise.
7726 */
7727 public boolean onTrackballEvent(MotionEvent event) {
7728 return false;
7729 }
7730
7731 /**
Jeff Browncb1404e2011-01-15 18:14:15 -08007732 * Implement this method to handle generic motion events.
7733 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -08007734 * Generic motion events describe joystick movements, mouse hovers, track pad
7735 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -08007736 * {@link MotionEvent#getSource() source} of the motion event specifies
7737 * the class of input that was received. Implementations of this method
7738 * must examine the bits in the source before processing the event.
7739 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -08007740 * </p><p>
7741 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7742 * are delivered to the view under the pointer. All other generic motion events are
7743 * delivered to the focused view.
Jeff Browncb1404e2011-01-15 18:14:15 -08007744 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07007745 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
Jeff Browncb1404e2011-01-15 18:14:15 -08007746 * if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08007747 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
7748 * // process the joystick movement...
7749 * return true;
7750 * }
7751 * }
7752 * if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
7753 * switch (event.getAction()) {
7754 * case MotionEvent.ACTION_HOVER_MOVE:
7755 * // process the mouse hover movement...
7756 * return true;
7757 * case MotionEvent.ACTION_SCROLL:
7758 * // process the scroll wheel movement...
7759 * return true;
7760 * }
Jeff Browncb1404e2011-01-15 18:14:15 -08007761 * }
7762 * return super.onGenericMotionEvent(event);
Scott Mainb303d832011-10-12 16:45:18 -07007763 * }</pre>
Jeff Browncb1404e2011-01-15 18:14:15 -08007764 *
7765 * @param event The generic motion event being processed.
Jeff Browna032cc02011-03-07 16:56:21 -08007766 * @return True if the event was handled, false otherwise.
Jeff Browncb1404e2011-01-15 18:14:15 -08007767 */
7768 public boolean onGenericMotionEvent(MotionEvent event) {
7769 return false;
7770 }
7771
7772 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007773 * Implement this method to handle hover events.
7774 * <p>
Jeff Brown10b62902011-06-20 16:40:37 -07007775 * This method is called whenever a pointer is hovering into, over, or out of the
7776 * bounds of a view and the view is not currently being touched.
7777 * Hover events are represented as pointer events with action
7778 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
7779 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
7780 * </p>
7781 * <ul>
7782 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
7783 * when the pointer enters the bounds of the view.</li>
7784 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
7785 * when the pointer has already entered the bounds of the view and has moved.</li>
7786 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
7787 * when the pointer has exited the bounds of the view or when the pointer is
7788 * about to go down due to a button click, tap, or similar user action that
7789 * causes the view to be touched.</li>
7790 * </ul>
7791 * <p>
7792 * The view should implement this method to return true to indicate that it is
7793 * handling the hover event, such as by changing its drawable state.
Jeff Browna032cc02011-03-07 16:56:21 -08007794 * </p><p>
Jeff Brown10b62902011-06-20 16:40:37 -07007795 * The default implementation calls {@link #setHovered} to update the hovered state
7796 * of the view when a hover enter or hover exit event is received, if the view
Jeff Browna1b24182011-07-28 13:38:24 -07007797 * is enabled and is clickable. The default implementation also sends hover
7798 * accessibility events.
Jeff Browna032cc02011-03-07 16:56:21 -08007799 * </p>
7800 *
7801 * @param event The motion event that describes the hover.
Jeff Brown10b62902011-06-20 16:40:37 -07007802 * @return True if the view handled the hover event.
7803 *
7804 * @see #isHovered
7805 * @see #setHovered
7806 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007807 */
7808 public boolean onHoverEvent(MotionEvent event) {
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007809 // The root view may receive hover (or touch) events that are outside the bounds of
7810 // the window. This code ensures that we only send accessibility events for
7811 // hovers that are actually within the bounds of the root view.
Svetoslav Ganov42138042012-03-20 11:51:39 -07007812 final int action = event.getActionMasked();
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007813 if (!mSendingHoverAccessibilityEvents) {
7814 if ((action == MotionEvent.ACTION_HOVER_ENTER
7815 || action == MotionEvent.ACTION_HOVER_MOVE)
7816 && !hasHoveredChild()
7817 && pointInView(event.getX(), event.getY())) {
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07007818 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007819 mSendingHoverAccessibilityEvents = true;
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007820 }
7821 } else {
7822 if (action == MotionEvent.ACTION_HOVER_EXIT
Svetoslav Ganov42138042012-03-20 11:51:39 -07007823 || (action == MotionEvent.ACTION_MOVE
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007824 && !pointInView(event.getX(), event.getY()))) {
7825 mSendingHoverAccessibilityEvents = false;
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07007826 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007827 // If the window does not have input focus we take away accessibility
7828 // focus as soon as the user stop hovering over the view.
Jeff Brown59a422e2012-04-19 15:19:19 -07007829 if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007830 getViewRootImpl().setAccessibilityFocus(null, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007831 }
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007832 }
Jeff Browna1b24182011-07-28 13:38:24 -07007833 }
7834
Jeff Brown87b7f802011-06-21 18:35:45 -07007835 if (isHoverable()) {
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007836 switch (action) {
Jeff Brown10b62902011-06-20 16:40:37 -07007837 case MotionEvent.ACTION_HOVER_ENTER:
7838 setHovered(true);
7839 break;
7840 case MotionEvent.ACTION_HOVER_EXIT:
7841 setHovered(false);
7842 break;
7843 }
Jeff Browna1b24182011-07-28 13:38:24 -07007844
7845 // Dispatch the event to onGenericMotionEvent before returning true.
7846 // This is to provide compatibility with existing applications that
7847 // handled HOVER_MOVE events in onGenericMotionEvent and that would
7848 // break because of the new default handling for hoverable views
7849 // in onHoverEvent.
7850 // Note that onGenericMotionEvent will be called by default when
7851 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
7852 dispatchGenericMotionEventInternal(event);
Jeff Brown10b62902011-06-20 16:40:37 -07007853 return true;
Jeff Browna032cc02011-03-07 16:56:21 -08007854 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07007855
Svetoslav Ganov736c2752011-04-22 18:30:36 -07007856 return false;
Jeff Browna032cc02011-03-07 16:56:21 -08007857 }
7858
7859 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07007860 * Returns true if the view should handle {@link #onHoverEvent}
7861 * by calling {@link #setHovered} to change its hovered state.
7862 *
7863 * @return True if the view is hoverable.
7864 */
7865 private boolean isHoverable() {
7866 final int viewFlags = mViewFlags;
7867 if ((viewFlags & ENABLED_MASK) == DISABLED) {
7868 return false;
7869 }
7870
7871 return (viewFlags & CLICKABLE) == CLICKABLE
7872 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7873 }
7874
7875 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007876 * Returns true if the view is currently hovered.
7877 *
7878 * @return True if the view is currently hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007879 *
7880 * @see #setHovered
7881 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007882 */
Jeff Brown10b62902011-06-20 16:40:37 -07007883 @ViewDebug.ExportedProperty
Jeff Browna032cc02011-03-07 16:56:21 -08007884 public boolean isHovered() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007885 return (mPrivateFlags & PFLAG_HOVERED) != 0;
Jeff Browna032cc02011-03-07 16:56:21 -08007886 }
7887
7888 /**
7889 * Sets whether the view is currently hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007890 * <p>
7891 * Calling this method also changes the drawable state of the view. This
7892 * enables the view to react to hover by using different drawable resources
7893 * to change its appearance.
7894 * </p><p>
7895 * The {@link #onHoverChanged} method is called when the hovered state changes.
7896 * </p>
Jeff Browna032cc02011-03-07 16:56:21 -08007897 *
7898 * @param hovered True if the view is hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007899 *
7900 * @see #isHovered
7901 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007902 */
7903 public void setHovered(boolean hovered) {
7904 if (hovered) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007905 if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
7906 mPrivateFlags |= PFLAG_HOVERED;
Jeff Browna032cc02011-03-07 16:56:21 -08007907 refreshDrawableState();
Jeff Brown10b62902011-06-20 16:40:37 -07007908 onHoverChanged(true);
Jeff Browna032cc02011-03-07 16:56:21 -08007909 }
7910 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007911 if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
7912 mPrivateFlags &= ~PFLAG_HOVERED;
Jeff Browna032cc02011-03-07 16:56:21 -08007913 refreshDrawableState();
Jeff Brown10b62902011-06-20 16:40:37 -07007914 onHoverChanged(false);
Jeff Browna032cc02011-03-07 16:56:21 -08007915 }
7916 }
7917 }
7918
7919 /**
Jeff Brown10b62902011-06-20 16:40:37 -07007920 * Implement this method to handle hover state changes.
7921 * <p>
7922 * This method is called whenever the hover state changes as a result of a
7923 * call to {@link #setHovered}.
7924 * </p>
7925 *
7926 * @param hovered The current hover state, as returned by {@link #isHovered}.
7927 *
7928 * @see #isHovered
7929 * @see #setHovered
7930 */
7931 public void onHoverChanged(boolean hovered) {
Jeff Brown10b62902011-06-20 16:40:37 -07007932 }
7933
7934 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007935 * Implement this method to handle touch screen motion events.
7936 *
7937 * @param event The motion event.
7938 * @return True if the event was handled, false otherwise.
7939 */
7940 public boolean onTouchEvent(MotionEvent event) {
7941 final int viewFlags = mViewFlags;
7942
7943 if ((viewFlags & ENABLED_MASK) == DISABLED) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007944 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
Adam Powell4d6f0662012-02-21 15:11:11 -08007945 setPressed(false);
Svetoslav Ganov77b80c02011-03-15 20:52:58 -07007946 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 // A disabled view that is clickable still consumes the touch
7948 // events, it just doesn't respond to them.
7949 return (((viewFlags & CLICKABLE) == CLICKABLE ||
7950 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
7951 }
7952
7953 if (mTouchDelegate != null) {
7954 if (mTouchDelegate.onTouchEvent(event)) {
7955 return true;
7956 }
7957 }
7958
7959 if (((viewFlags & CLICKABLE) == CLICKABLE ||
7960 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
7961 switch (event.getAction()) {
7962 case MotionEvent.ACTION_UP:
Dianne Hackborn4702a852012-08-17 15:18:29 -07007963 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
7964 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007965 // take focus if we don't have it already and we should in
7966 // touch mode.
7967 boolean focusTaken = false;
7968 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
7969 focusTaken = requestFocus();
7970 }
7971
Dianne Hackbornbe1f6222011-01-20 15:24:28 -08007972 if (prepressed) {
7973 // The button is being released before we actually
7974 // showed it as pressed. Make it show the pressed
7975 // state now (before scheduling the click) to ensure
7976 // the user sees it.
Adam Powell4d6f0662012-02-21 15:11:11 -08007977 setPressed(true);
Dianne Hackbornbe1f6222011-01-20 15:24:28 -08007978 }
Joe Malin32736f02011-01-19 16:14:20 -08007979
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007980 if (!mHasPerformedLongPress) {
7981 // This is a tap, so remove the longpress check
Maryam Garrett1549dd12009-12-15 16:06:36 -05007982 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007983
7984 // Only perform take click actions if we were in the pressed state
7985 if (!focusTaken) {
Adam Powella35d7682010-03-12 14:48:13 -08007986 // Use a Runnable and post this rather than calling
7987 // performClick directly. This lets other visual state
7988 // of the view update before click actions start.
7989 if (mPerformClick == null) {
7990 mPerformClick = new PerformClick();
7991 }
7992 if (!post(mPerformClick)) {
7993 performClick();
7994 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007995 }
7996 }
7997
7998 if (mUnsetPressedState == null) {
7999 mUnsetPressedState = new UnsetPressedState();
8000 }
8001
Adam Powelle14579b2009-12-16 18:39:52 -08008002 if (prepressed) {
Adam Powelle14579b2009-12-16 18:39:52 -08008003 postDelayed(mUnsetPressedState,
8004 ViewConfiguration.getPressedStateDuration());
8005 } else if (!post(mUnsetPressedState)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008006 // If the post failed, unpress right now
8007 mUnsetPressedState.run();
8008 }
Adam Powelle14579b2009-12-16 18:39:52 -08008009 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008010 }
8011 break;
8012
8013 case MotionEvent.ACTION_DOWN:
Adam Powell3b023392010-03-11 16:30:28 -08008014 mHasPerformedLongPress = false;
Patrick Dubroye0a799a2011-05-04 16:19:22 -07008015
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07008016 if (performButtonActionOnTouchDown(event)) {
8017 break;
8018 }
8019
Patrick Dubroye0a799a2011-05-04 16:19:22 -07008020 // Walk up the hierarchy to determine if we're inside a scrolling container.
Adam Powell10298662011-08-14 18:26:30 -07008021 boolean isInScrollingContainer = isInScrollingContainer();
Patrick Dubroye0a799a2011-05-04 16:19:22 -07008022
8023 // For views inside a scrolling container, delay the pressed feedback for
8024 // a short period in case this is a scroll.
8025 if (isInScrollingContainer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008026 mPrivateFlags |= PFLAG_PREPRESSED;
Patrick Dubroye0a799a2011-05-04 16:19:22 -07008027 if (mPendingCheckForTap == null) {
8028 mPendingCheckForTap = new CheckForTap();
8029 }
8030 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
8031 } else {
8032 // Not inside a scrolling container, so show the feedback right away
Adam Powell4d6f0662012-02-21 15:11:11 -08008033 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -07008034 checkForLongClick(0);
8035 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008036 break;
8037
8038 case MotionEvent.ACTION_CANCEL:
Adam Powell4d6f0662012-02-21 15:11:11 -08008039 setPressed(false);
Adam Powelle14579b2009-12-16 18:39:52 -08008040 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008041 break;
8042
8043 case MotionEvent.ACTION_MOVE:
8044 final int x = (int) event.getX();
8045 final int y = (int) event.getY();
8046
8047 // Be lenient about moving outside of buttons
Chet Haasec3aa3612010-06-17 08:50:37 -07008048 if (!pointInView(x, y, mTouchSlop)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008049 // Outside button
Adam Powelle14579b2009-12-16 18:39:52 -08008050 removeTapCallback();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008051 if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
Adam Powelle14579b2009-12-16 18:39:52 -08008052 // Remove any future long press/tap checks
Maryam Garrett1549dd12009-12-15 16:06:36 -05008053 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008054
Adam Powell4d6f0662012-02-21 15:11:11 -08008055 setPressed(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008056 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008057 }
8058 break;
8059 }
8060 return true;
8061 }
8062
8063 return false;
8064 }
8065
8066 /**
Adam Powell10298662011-08-14 18:26:30 -07008067 * @hide
8068 */
8069 public boolean isInScrollingContainer() {
8070 ViewParent p = getParent();
8071 while (p != null && p instanceof ViewGroup) {
8072 if (((ViewGroup) p).shouldDelayChildPressedState()) {
8073 return true;
8074 }
8075 p = p.getParent();
8076 }
8077 return false;
8078 }
8079
8080 /**
Maryam Garrett1549dd12009-12-15 16:06:36 -05008081 * Remove the longpress detection timer.
8082 */
8083 private void removeLongPressCallback() {
8084 if (mPendingCheckForLongPress != null) {
8085 removeCallbacks(mPendingCheckForLongPress);
8086 }
8087 }
Adam Powell3cb8b632011-01-21 15:34:14 -08008088
8089 /**
8090 * Remove the pending click action
8091 */
8092 private void removePerformClickCallback() {
8093 if (mPerformClick != null) {
8094 removeCallbacks(mPerformClick);
8095 }
8096 }
8097
Adam Powelle14579b2009-12-16 18:39:52 -08008098 /**
Romain Guya440b002010-02-24 15:57:54 -08008099 * Remove the prepress detection timer.
8100 */
8101 private void removeUnsetPressCallback() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008102 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
Romain Guya440b002010-02-24 15:57:54 -08008103 setPressed(false);
8104 removeCallbacks(mUnsetPressedState);
8105 }
8106 }
8107
8108 /**
Adam Powelle14579b2009-12-16 18:39:52 -08008109 * Remove the tap detection timer.
8110 */
8111 private void removeTapCallback() {
8112 if (mPendingCheckForTap != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008113 mPrivateFlags &= ~PFLAG_PREPRESSED;
Adam Powelle14579b2009-12-16 18:39:52 -08008114 removeCallbacks(mPendingCheckForTap);
8115 }
8116 }
Maryam Garrett1549dd12009-12-15 16:06:36 -05008117
8118 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008119 * Cancels a pending long press. Your subclass can use this if you
8120 * want the context menu to come up if the user presses and holds
8121 * at the same place, but you don't want it to come up if they press
8122 * and then move around enough to cause scrolling.
8123 */
8124 public void cancelLongPress() {
Maryam Garrett1549dd12009-12-15 16:06:36 -05008125 removeLongPressCallback();
Adam Powell732ebb12010-02-02 15:28:14 -08008126
8127 /*
8128 * The prepressed state handled by the tap callback is a display
8129 * construct, but the tap callback will post a long press callback
8130 * less its own timeout. Remove it here.
8131 */
8132 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008133 }
8134
8135 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07008136 * Remove the pending callback for sending a
8137 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8138 */
8139 private void removeSendViewScrolledAccessibilityEventCallback() {
8140 if (mSendViewScrolledAccessibilityEvent != null) {
8141 removeCallbacks(mSendViewScrolledAccessibilityEvent);
Svetoslav Ganov4a812ae2012-05-29 16:46:10 -07008142 mSendViewScrolledAccessibilityEvent.mIsPending = false;
Svetoslav Ganova0156172011-06-26 17:55:44 -07008143 }
8144 }
8145
8146 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008147 * Sets the TouchDelegate for this View.
8148 */
8149 public void setTouchDelegate(TouchDelegate delegate) {
8150 mTouchDelegate = delegate;
8151 }
8152
8153 /**
8154 * Gets the TouchDelegate for this View.
8155 */
8156 public TouchDelegate getTouchDelegate() {
8157 return mTouchDelegate;
8158 }
8159
8160 /**
8161 * Set flags controlling behavior of this view.
8162 *
8163 * @param flags Constant indicating the value which should be set
8164 * @param mask Constant indicating the bit range that should be changed
8165 */
8166 void setFlags(int flags, int mask) {
8167 int old = mViewFlags;
8168 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8169
8170 int changed = mViewFlags ^ old;
8171 if (changed == 0) {
8172 return;
8173 }
8174 int privateFlags = mPrivateFlags;
8175
8176 /* Check if the FOCUSABLE bit has changed */
8177 if (((changed & FOCUSABLE_MASK) != 0) &&
Dianne Hackborn4702a852012-08-17 15:18:29 -07008178 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008179 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
Dianne Hackborn4702a852012-08-17 15:18:29 -07008180 && ((privateFlags & PFLAG_FOCUSED) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008181 /* Give up focus if we are no longer focusable */
8182 clearFocus();
8183 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
Dianne Hackborn4702a852012-08-17 15:18:29 -07008184 && ((privateFlags & PFLAG_FOCUSED) == 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008185 /*
8186 * Tell the view system that we are now available to take focus
8187 * if no one else already has it.
8188 */
8189 if (mParent != null) mParent.focusableViewAvailable(this);
8190 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07008191 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8192 notifyAccessibilityStateChanged();
8193 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008194 }
8195
8196 if ((flags & VISIBILITY_MASK) == VISIBLE) {
8197 if ((changed & VISIBILITY_MASK) != 0) {
8198 /*
Chet Haase4324ead2011-08-24 21:31:03 -07008199 * If this view is becoming visible, invalidate it in case it changed while
Chet Haaseaceafe62011-08-26 15:44:33 -07008200 * it was not visible. Marking it drawn ensures that the invalidation will
8201 * go through.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008202 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07008203 mPrivateFlags |= PFLAG_DRAWN;
Chet Haase4324ead2011-08-24 21:31:03 -07008204 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008205
8206 needGlobalAttributesUpdate(true);
8207
8208 // a view becoming visible is worth notifying the parent
8209 // about in case nothing has focus. even if this specific view
8210 // isn't focusable, it may contain something that is, so let
8211 // the root view try to give this focus if nothing else does.
8212 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8213 mParent.focusableViewAvailable(this);
8214 }
8215 }
8216 }
8217
8218 /* Check if the GONE bit has changed */
8219 if ((changed & GONE) != 0) {
8220 needGlobalAttributesUpdate(false);
8221 requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008222
Romain Guyecd80ee2009-12-03 17:13:02 -08008223 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8224 if (hasFocus()) clearFocus();
Svetoslav Ganov42138042012-03-20 11:51:39 -07008225 clearAccessibilityFocus();
Romain Guyecd80ee2009-12-03 17:13:02 -08008226 destroyDrawingCache();
Chet Haaseaceafe62011-08-26 15:44:33 -07008227 if (mParent instanceof View) {
8228 // GONE views noop invalidation, so invalidate the parent
8229 ((View) mParent).invalidate(true);
8230 }
8231 // Mark the view drawn to ensure that it gets invalidated properly the next
8232 // time it is visible and gets invalidated
Dianne Hackborn4702a852012-08-17 15:18:29 -07008233 mPrivateFlags |= PFLAG_DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008234 }
8235 if (mAttachInfo != null) {
8236 mAttachInfo.mViewVisibilityChanged = true;
8237 }
8238 }
8239
8240 /* Check if the VISIBLE bit has changed */
8241 if ((changed & INVISIBLE) != 0) {
8242 needGlobalAttributesUpdate(false);
Chet Haasec8a9a702011-06-17 12:13:42 -07008243 /*
8244 * If this view is becoming invisible, set the DRAWN flag so that
8245 * the next invalidate() will not be skipped.
8246 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07008247 mPrivateFlags |= PFLAG_DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008248
8249 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07008250 // root view becoming invisible shouldn't clear focus and accessibility focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008251 if (getRootView() != this) {
8252 clearFocus();
Svetoslav Ganov42138042012-03-20 11:51:39 -07008253 clearAccessibilityFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008254 }
8255 }
8256 if (mAttachInfo != null) {
8257 mAttachInfo.mViewVisibilityChanged = true;
8258 }
8259 }
8260
Adam Powell326d8082009-12-09 15:10:07 -08008261 if ((changed & VISIBILITY_MASK) != 0) {
Chet Haase5e25c2c2010-09-16 11:15:56 -07008262 if (mParent instanceof ViewGroup) {
Romain Guyfe455af2012-02-15 16:40:20 -08008263 ((ViewGroup) mParent).onChildVisibilityChanged(this,
8264 (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
Romain Guy0fd89bf2011-01-26 15:41:30 -08008265 ((View) mParent).invalidate(true);
Chet Haasee4e6e202011-08-29 14:34:30 -07008266 } else if (mParent != null) {
8267 mParent.invalidateChild(this, null);
Chet Haase5e25c2c2010-09-16 11:15:56 -07008268 }
Adam Powell326d8082009-12-09 15:10:07 -08008269 dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8270 }
8271
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008272 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8273 destroyDrawingCache();
8274 }
8275
8276 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8277 destroyDrawingCache();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008278 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
Romain Guy0fd89bf2011-01-26 15:41:30 -08008279 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 }
8281
8282 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8283 destroyDrawingCache();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008284 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008285 }
8286
8287 if ((changed & DRAW_MASK) != 0) {
8288 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
Philip Milne6c8ea062012-04-03 17:38:43 -07008289 if (mBackground != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008290 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8291 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008292 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008293 mPrivateFlags |= PFLAG_SKIP_DRAW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008294 }
8295 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008296 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008297 }
8298 requestLayout();
Romain Guy0fd89bf2011-01-26 15:41:30 -08008299 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008300 }
8301
8302 if ((changed & KEEP_SCREEN_ON) != 0) {
Joe Onorato664644d2011-01-23 17:53:23 -08008303 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008304 mParent.recomputeViewAttributes(this);
8305 }
8306 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07008307
8308 if (AccessibilityManager.getInstance(mContext).isEnabled()
8309 && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8310 || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8311 notifyAccessibilityStateChanged();
8312 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008313 }
8314
8315 /**
8316 * Change the view's z order in the tree, so it's on top of other sibling
8317 * views
8318 */
8319 public void bringToFront() {
8320 if (mParent != null) {
8321 mParent.bringChildToFront(this);
8322 }
8323 }
8324
8325 /**
8326 * This is called in response to an internal scroll in this view (i.e., the
8327 * view scrolled its own contents). This is typically as a result of
8328 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8329 * called.
8330 *
8331 * @param l Current horizontal scroll origin.
8332 * @param t Current vertical scroll origin.
8333 * @param oldl Previous horizontal scroll origin.
8334 * @param oldt Previous vertical scroll origin.
8335 */
8336 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
Svetoslav Ganova0156172011-06-26 17:55:44 -07008337 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8338 postSendViewScrolledAccessibilityEventCallback();
8339 }
8340
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008341 mBackgroundSizeChanged = true;
8342
8343 final AttachInfo ai = mAttachInfo;
8344 if (ai != null) {
8345 ai.mViewScrollChanged = true;
8346 }
8347 }
8348
8349 /**
Chet Haase21cd1382010-09-01 17:42:29 -07008350 * Interface definition for a callback to be invoked when the layout bounds of a view
8351 * changes due to layout processing.
8352 */
8353 public interface OnLayoutChangeListener {
8354 /**
8355 * Called when the focus state of a view has changed.
8356 *
8357 * @param v The view whose state has changed.
8358 * @param left The new value of the view's left property.
8359 * @param top The new value of the view's top property.
8360 * @param right The new value of the view's right property.
8361 * @param bottom The new value of the view's bottom property.
8362 * @param oldLeft The previous value of the view's left property.
8363 * @param oldTop The previous value of the view's top property.
8364 * @param oldRight The previous value of the view's right property.
8365 * @param oldBottom The previous value of the view's bottom property.
8366 */
8367 void onLayoutChange(View v, int left, int top, int right, int bottom,
8368 int oldLeft, int oldTop, int oldRight, int oldBottom);
8369 }
8370
8371 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008372 * This is called during layout when the size of this view has changed. If
8373 * you were just added to the view hierarchy, you're called with the old
8374 * values of 0.
8375 *
8376 * @param w Current width of this view.
8377 * @param h Current height of this view.
8378 * @param oldw Old width of this view.
8379 * @param oldh Old height of this view.
8380 */
8381 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8382 }
8383
8384 /**
8385 * Called by draw to draw the child views. This may be overridden
8386 * by derived classes to gain control just before its children are drawn
8387 * (but after its own view has been drawn).
8388 * @param canvas the canvas on which to draw the view
8389 */
8390 protected void dispatchDraw(Canvas canvas) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07008391
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008392 }
8393
8394 /**
8395 * Gets the parent of this view. Note that the parent is a
8396 * ViewParent and not necessarily a View.
8397 *
8398 * @return Parent of this view.
8399 */
8400 public final ViewParent getParent() {
8401 return mParent;
8402 }
8403
8404 /**
Chet Haasecca2c982011-05-20 14:34:18 -07008405 * Set the horizontal scrolled position of your view. This will cause a call to
8406 * {@link #onScrollChanged(int, int, int, int)} and the view will be
8407 * invalidated.
8408 * @param value the x position to scroll to
8409 */
8410 public void setScrollX(int value) {
8411 scrollTo(value, mScrollY);
8412 }
8413
8414 /**
8415 * Set the vertical scrolled position of your view. This will cause a call to
8416 * {@link #onScrollChanged(int, int, int, int)} and the view will be
8417 * invalidated.
8418 * @param value the y position to scroll to
8419 */
8420 public void setScrollY(int value) {
8421 scrollTo(mScrollX, value);
8422 }
8423
8424 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008425 * Return the scrolled left position of this view. This is the left edge of
8426 * the displayed part of your view. You do not need to draw any pixels
8427 * farther left, since those are outside of the frame of your view on
8428 * screen.
8429 *
8430 * @return The left edge of the displayed part of your view, in pixels.
8431 */
8432 public final int getScrollX() {
8433 return mScrollX;
8434 }
8435
8436 /**
8437 * Return the scrolled top position of this view. This is the top edge of
8438 * the displayed part of your view. You do not need to draw any pixels above
8439 * it, since those are outside of the frame of your view on screen.
8440 *
8441 * @return The top edge of the displayed part of your view, in pixels.
8442 */
8443 public final int getScrollY() {
8444 return mScrollY;
8445 }
8446
8447 /**
8448 * Return the width of the your view.
8449 *
8450 * @return The width of your view, in pixels.
8451 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07008452 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008453 public final int getWidth() {
8454 return mRight - mLeft;
8455 }
8456
8457 /**
8458 * Return the height of your view.
8459 *
8460 * @return The height of your view, in pixels.
8461 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07008462 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 public final int getHeight() {
8464 return mBottom - mTop;
8465 }
8466
8467 /**
8468 * Return the visible drawing bounds of your view. Fills in the output
8469 * rectangle with the values from getScrollX(), getScrollY(),
8470 * getWidth(), and getHeight().
8471 *
8472 * @param outRect The (scrolled) drawing bounds of the view.
8473 */
8474 public void getDrawingRect(Rect outRect) {
8475 outRect.left = mScrollX;
8476 outRect.top = mScrollY;
8477 outRect.right = mScrollX + (mRight - mLeft);
8478 outRect.bottom = mScrollY + (mBottom - mTop);
8479 }
8480
8481 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008482 * Like {@link #getMeasuredWidthAndState()}, but only returns the
8483 * raw width component (that is the result is masked by
8484 * {@link #MEASURED_SIZE_MASK}).
8485 *
8486 * @return The raw measured width of this view.
8487 */
8488 public final int getMeasuredWidth() {
8489 return mMeasuredWidth & MEASURED_SIZE_MASK;
8490 }
8491
8492 /**
8493 * Return the full width measurement information for this view as computed
Romain Guy5c22a8c2011-05-13 11:48:45 -07008494 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
Dianne Hackborn189ee182010-12-02 21:48:53 -08008495 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008496 * This should be used during measurement and layout calculations only. Use
8497 * {@link #getWidth()} to see how wide a view is after layout.
8498 *
Dianne Hackborn189ee182010-12-02 21:48:53 -08008499 * @return The measured width of this view as a bit mask.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008500 */
Dianne Hackborn189ee182010-12-02 21:48:53 -08008501 public final int getMeasuredWidthAndState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008502 return mMeasuredWidth;
8503 }
8504
8505 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008506 * Like {@link #getMeasuredHeightAndState()}, but only returns the
8507 * raw width component (that is the result is masked by
8508 * {@link #MEASURED_SIZE_MASK}).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008509 *
Dianne Hackborn189ee182010-12-02 21:48:53 -08008510 * @return The raw measured height of this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008511 */
8512 public final int getMeasuredHeight() {
Dianne Hackborn189ee182010-12-02 21:48:53 -08008513 return mMeasuredHeight & MEASURED_SIZE_MASK;
8514 }
8515
8516 /**
8517 * Return the full height measurement information for this view as computed
Romain Guy5c22a8c2011-05-13 11:48:45 -07008518 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
Dianne Hackborn189ee182010-12-02 21:48:53 -08008519 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8520 * This should be used during measurement and layout calculations only. Use
8521 * {@link #getHeight()} to see how wide a view is after layout.
8522 *
8523 * @return The measured width of this view as a bit mask.
8524 */
8525 public final int getMeasuredHeightAndState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008526 return mMeasuredHeight;
8527 }
8528
8529 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008530 * Return only the state bits of {@link #getMeasuredWidthAndState()}
8531 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8532 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8533 * and the height component is at the shifted bits
8534 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8535 */
8536 public final int getMeasuredState() {
8537 return (mMeasuredWidth&MEASURED_STATE_MASK)
8538 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8539 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8540 }
8541
8542 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008543 * The transform matrix of this view, which is calculated based on the current
8544 * roation, scale, and pivot properties.
8545 *
8546 * @see #getRotation()
8547 * @see #getScaleX()
8548 * @see #getScaleY()
8549 * @see #getPivotX()
8550 * @see #getPivotY()
8551 * @return The current transform matrix for the view
8552 */
8553 public Matrix getMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008554 if (mTransformationInfo != null) {
8555 updateMatrix();
8556 return mTransformationInfo.mMatrix;
8557 }
8558 return Matrix.IDENTITY_MATRIX;
Romain Guy33e72ae2010-07-17 12:40:29 -07008559 }
8560
8561 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07008562 * Utility function to determine if the value is far enough away from zero to be
8563 * considered non-zero.
8564 * @param value A floating point value to check for zero-ness
8565 * @return whether the passed-in value is far enough away from zero to be considered non-zero
8566 */
8567 private static boolean nonzero(float value) {
8568 return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8569 }
8570
8571 /**
Jeff Brown86671742010-09-30 20:00:15 -07008572 * Returns true if the transform matrix is the identity matrix.
8573 * Recomputes the matrix if necessary.
Joe Malin32736f02011-01-19 16:14:20 -08008574 *
Romain Guy33e72ae2010-07-17 12:40:29 -07008575 * @return True if the transform matrix is the identity matrix, false otherwise.
8576 */
Jeff Brown86671742010-09-30 20:00:15 -07008577 final boolean hasIdentityMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008578 if (mTransformationInfo != null) {
8579 updateMatrix();
8580 return mTransformationInfo.mMatrixIsIdentity;
8581 }
8582 return true;
8583 }
8584
8585 void ensureTransformationInfo() {
8586 if (mTransformationInfo == null) {
8587 mTransformationInfo = new TransformationInfo();
8588 }
Jeff Brown86671742010-09-30 20:00:15 -07008589 }
8590
8591 /**
8592 * Recomputes the transform matrix if necessary.
8593 */
Romain Guy2fe9a8f2010-10-04 20:17:01 -07008594 private void updateMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008595 final TransformationInfo info = mTransformationInfo;
8596 if (info == null) {
8597 return;
8598 }
8599 if (info.mMatrixDirty) {
Chet Haasec3aa3612010-06-17 08:50:37 -07008600 // transform-related properties have changed since the last time someone
8601 // asked for the matrix; recalculate it with the current values
Chet Haasefd2b0022010-08-06 13:08:56 -07008602
8603 // Figure out if we need to update the pivot point
Dianne Hackborn4702a852012-08-17 15:18:29 -07008604 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008605 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8606 info.mPrevWidth = mRight - mLeft;
8607 info.mPrevHeight = mBottom - mTop;
8608 info.mPivotX = info.mPrevWidth / 2f;
8609 info.mPivotY = info.mPrevHeight / 2f;
Chet Haasefd2b0022010-08-06 13:08:56 -07008610 }
8611 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008612 info.mMatrix.reset();
8613 if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8614 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8615 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8616 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
Chet Haase897247b2010-09-09 14:54:47 -07008617 } else {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008618 if (info.mCamera == null) {
8619 info.mCamera = new Camera();
8620 info.matrix3D = new Matrix();
Chet Haasefd2b0022010-08-06 13:08:56 -07008621 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008622 info.mCamera.save();
8623 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8624 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8625 info.mCamera.getMatrix(info.matrix3D);
8626 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8627 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8628 info.mPivotY + info.mTranslationY);
8629 info.mMatrix.postConcat(info.matrix3D);
8630 info.mCamera.restore();
Chet Haasefd2b0022010-08-06 13:08:56 -07008631 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008632 info.mMatrixDirty = false;
8633 info.mMatrixIsIdentity = info.mMatrix.isIdentity();
8634 info.mInverseMatrixDirty = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07008635 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008636 }
8637
8638 /**
Tobias Duboisdefdb1e2010-12-15 11:35:30 +01008639 * When searching for a view to focus this rectangle is used when considering if this view is
8640 * a good candidate for receiving focus.
8641 *
8642 * By default, the rectangle is the {@link #getDrawingRect}) of the view.
8643 *
8644 * @param r The rectangle to fill in, in this view's coordinates.
8645 */
8646 public void getFocusRect(Rect r) {
8647 getDrawingRect(r);
8648 }
8649
8650 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008651 * Utility method to retrieve the inverse of the current mMatrix property.
8652 * We cache the matrix to avoid recalculating it when transform properties
8653 * have not changed.
8654 *
8655 * @return The inverse of the current matrix of this view.
8656 */
Jeff Brown86671742010-09-30 20:00:15 -07008657 final Matrix getInverseMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008658 final TransformationInfo info = mTransformationInfo;
8659 if (info != null) {
8660 updateMatrix();
8661 if (info.mInverseMatrixDirty) {
8662 if (info.mInverseMatrix == null) {
8663 info.mInverseMatrix = new Matrix();
8664 }
8665 info.mMatrix.invert(info.mInverseMatrix);
8666 info.mInverseMatrixDirty = false;
Chet Haasec3aa3612010-06-17 08:50:37 -07008667 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008668 return info.mInverseMatrix;
Chet Haasec3aa3612010-06-17 08:50:37 -07008669 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008670 return Matrix.IDENTITY_MATRIX;
Chet Haasec3aa3612010-06-17 08:50:37 -07008671 }
8672
8673 /**
Chet Haasea1cff502012-02-21 13:43:44 -08008674 * Gets the distance along the Z axis from the camera to this view.
8675 *
8676 * @see #setCameraDistance(float)
8677 *
8678 * @return The distance along the Z axis.
8679 */
8680 public float getCameraDistance() {
8681 ensureTransformationInfo();
8682 final float dpi = mResources.getDisplayMetrics().densityDpi;
8683 final TransformationInfo info = mTransformationInfo;
8684 if (info.mCamera == null) {
8685 info.mCamera = new Camera();
8686 info.matrix3D = new Matrix();
8687 }
8688 return -(info.mCamera.getLocationZ() * dpi);
8689 }
8690
8691 /**
Romain Guya5364ee2011-02-24 14:46:04 -08008692 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
8693 * views are drawn) from the camera to this view. The camera's distance
8694 * affects 3D transformations, for instance rotations around the X and Y
8695 * axis. If the rotationX or rotationY properties are changed and this view is
Philip Milne6c8ea062012-04-03 17:38:43 -07008696 * large (more than half the size of the screen), it is recommended to always
Romain Guya5364ee2011-02-24 14:46:04 -08008697 * use a camera distance that's greater than the height (X axis rotation) or
8698 * the width (Y axis rotation) of this view.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008699 *
Romain Guya5364ee2011-02-24 14:46:04 -08008700 * <p>The distance of the camera from the view plane can have an affect on the
8701 * perspective distortion of the view when it is rotated around the x or y axis.
8702 * For example, a large distance will result in a large viewing angle, and there
8703 * will not be much perspective distortion of the view as it rotates. A short
Philip Milne6c8ea062012-04-03 17:38:43 -07008704 * distance may cause much more perspective distortion upon rotation, and can
Romain Guya5364ee2011-02-24 14:46:04 -08008705 * also result in some drawing artifacts if the rotated view ends up partially
8706 * behind the camera (which is why the recommendation is to use a distance at
8707 * least as far as the size of the view, if the view is to be rotated.)</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008708 *
Romain Guya5364ee2011-02-24 14:46:04 -08008709 * <p>The distance is expressed in "depth pixels." The default distance depends
8710 * on the screen density. For instance, on a medium density display, the
8711 * default distance is 1280. On a high density display, the default distance
8712 * is 1920.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008713 *
Romain Guya5364ee2011-02-24 14:46:04 -08008714 * <p>If you want to specify a distance that leads to visually consistent
8715 * results across various densities, use the following formula:</p>
8716 * <pre>
8717 * float scale = context.getResources().getDisplayMetrics().density;
8718 * view.setCameraDistance(distance * scale);
8719 * </pre>
Philip Milne6c8ea062012-04-03 17:38:43 -07008720 *
Romain Guya5364ee2011-02-24 14:46:04 -08008721 * <p>The density scale factor of a high density display is 1.5,
8722 * and 1920 = 1280 * 1.5.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008723 *
Romain Guya5364ee2011-02-24 14:46:04 -08008724 * @param distance The distance in "depth pixels", if negative the opposite
8725 * value is used
Philip Milne6c8ea062012-04-03 17:38:43 -07008726 *
8727 * @see #setRotationX(float)
8728 * @see #setRotationY(float)
Romain Guya5364ee2011-02-24 14:46:04 -08008729 */
8730 public void setCameraDistance(float distance) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008731 invalidateViewProperty(true, false);
Romain Guya5364ee2011-02-24 14:46:04 -08008732
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008733 ensureTransformationInfo();
Romain Guya5364ee2011-02-24 14:46:04 -08008734 final float dpi = mResources.getDisplayMetrics().densityDpi;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008735 final TransformationInfo info = mTransformationInfo;
8736 if (info.mCamera == null) {
8737 info.mCamera = new Camera();
8738 info.matrix3D = new Matrix();
Romain Guya5364ee2011-02-24 14:46:04 -08008739 }
8740
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008741 info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
8742 info.mMatrixDirty = true;
Romain Guya5364ee2011-02-24 14:46:04 -08008743
Chet Haase9d1992d2012-03-13 11:03:25 -07008744 invalidateViewProperty(false, false);
Chet Haase1271e2c2012-04-20 09:54:27 -07008745 if (mDisplayList != null) {
Chet Haaseb85967b2012-03-26 14:37:51 -07008746 mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
Chet Haasea1cff502012-02-21 13:43:44 -08008747 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008748 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008749 // View was rejected last time it was drawn by its parent; this may have changed
8750 invalidateParentIfNeeded();
8751 }
Romain Guya5364ee2011-02-24 14:46:04 -08008752 }
8753
8754 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008755 * The degrees that the view is rotated around the pivot point.
8756 *
Philip Milne6c8ea062012-04-03 17:38:43 -07008757 * @see #setRotation(float)
Chet Haasec3aa3612010-06-17 08:50:37 -07008758 * @see #getPivotX()
8759 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008760 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008761 * @return The degrees of rotation.
8762 */
Chet Haasea5531132012-02-02 13:41:44 -08008763 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008764 public float getRotation() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008765 return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07008766 }
8767
8768 /**
Chet Haase897247b2010-09-09 14:54:47 -07008769 * Sets the degrees that the view is rotated around the pivot point. Increasing values
8770 * result in clockwise rotation.
Chet Haasec3aa3612010-06-17 08:50:37 -07008771 *
8772 * @param rotation The degrees of rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008773 *
8774 * @see #getRotation()
Chet Haasec3aa3612010-06-17 08:50:37 -07008775 * @see #getPivotX()
8776 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008777 * @see #setRotationX(float)
8778 * @see #setRotationY(float)
Chet Haase73066682010-11-29 15:55:32 -08008779 *
8780 * @attr ref android.R.styleable#View_rotation
Chet Haasec3aa3612010-06-17 08:50:37 -07008781 */
8782 public void setRotation(float rotation) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008783 ensureTransformationInfo();
8784 final TransformationInfo info = mTransformationInfo;
8785 if (info.mRotation != rotation) {
Chet Haasec3aa3612010-06-17 08:50:37 -07008786 // Double-invalidation is necessary to capture view's old and new areas
Chet Haase9d1992d2012-03-13 11:03:25 -07008787 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008788 info.mRotation = rotation;
8789 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008790 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008791 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008792 mDisplayList.setRotation(rotation);
8793 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008794 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008795 // View was rejected last time it was drawn by its parent; this may have changed
8796 invalidateParentIfNeeded();
8797 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008798 }
8799 }
8800
8801 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07008802 * The degrees that the view is rotated around the vertical axis through the pivot point.
8803 *
8804 * @see #getPivotX()
8805 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008806 * @see #setRotationY(float)
8807 *
Chet Haasefd2b0022010-08-06 13:08:56 -07008808 * @return The degrees of Y rotation.
8809 */
Chet Haasea5531132012-02-02 13:41:44 -08008810 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasefd2b0022010-08-06 13:08:56 -07008811 public float getRotationY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008812 return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
Chet Haasefd2b0022010-08-06 13:08:56 -07008813 }
8814
8815 /**
Chet Haase897247b2010-09-09 14:54:47 -07008816 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
8817 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
8818 * down the y axis.
Philip Milne6c8ea062012-04-03 17:38:43 -07008819 *
Romain Guya5364ee2011-02-24 14:46:04 -08008820 * When rotating large views, it is recommended to adjust the camera distance
8821 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
Chet Haasefd2b0022010-08-06 13:08:56 -07008822 *
8823 * @param rotationY The degrees of Y rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008824 *
8825 * @see #getRotationY()
Chet Haasefd2b0022010-08-06 13:08:56 -07008826 * @see #getPivotX()
8827 * @see #getPivotY()
Romain Guya5364ee2011-02-24 14:46:04 -08008828 * @see #setRotation(float)
Philip Milne6c8ea062012-04-03 17:38:43 -07008829 * @see #setRotationX(float)
8830 * @see #setCameraDistance(float)
Chet Haase73066682010-11-29 15:55:32 -08008831 *
8832 * @attr ref android.R.styleable#View_rotationY
Chet Haasefd2b0022010-08-06 13:08:56 -07008833 */
8834 public void setRotationY(float rotationY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008835 ensureTransformationInfo();
8836 final TransformationInfo info = mTransformationInfo;
8837 if (info.mRotationY != rotationY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008838 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008839 info.mRotationY = rotationY;
8840 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008841 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008842 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008843 mDisplayList.setRotationY(rotationY);
8844 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008845 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008846 // View was rejected last time it was drawn by its parent; this may have changed
8847 invalidateParentIfNeeded();
8848 }
Chet Haasefd2b0022010-08-06 13:08:56 -07008849 }
8850 }
8851
8852 /**
8853 * The degrees that the view is rotated around the horizontal axis through the pivot point.
8854 *
8855 * @see #getPivotX()
8856 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008857 * @see #setRotationX(float)
8858 *
Chet Haasefd2b0022010-08-06 13:08:56 -07008859 * @return The degrees of X rotation.
8860 */
Chet Haasea5531132012-02-02 13:41:44 -08008861 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasefd2b0022010-08-06 13:08:56 -07008862 public float getRotationX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008863 return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
Chet Haasefd2b0022010-08-06 13:08:56 -07008864 }
8865
8866 /**
Chet Haase897247b2010-09-09 14:54:47 -07008867 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
8868 * Increasing values result in clockwise rotation from the viewpoint of looking down the
8869 * x axis.
Philip Milne6c8ea062012-04-03 17:38:43 -07008870 *
Romain Guya5364ee2011-02-24 14:46:04 -08008871 * When rotating large views, it is recommended to adjust the camera distance
8872 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
Chet Haasefd2b0022010-08-06 13:08:56 -07008873 *
8874 * @param rotationX The degrees of X rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008875 *
8876 * @see #getRotationX()
Chet Haasefd2b0022010-08-06 13:08:56 -07008877 * @see #getPivotX()
8878 * @see #getPivotY()
Romain Guya5364ee2011-02-24 14:46:04 -08008879 * @see #setRotation(float)
Philip Milne6c8ea062012-04-03 17:38:43 -07008880 * @see #setRotationY(float)
8881 * @see #setCameraDistance(float)
Chet Haase73066682010-11-29 15:55:32 -08008882 *
8883 * @attr ref android.R.styleable#View_rotationX
Chet Haasefd2b0022010-08-06 13:08:56 -07008884 */
8885 public void setRotationX(float rotationX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008886 ensureTransformationInfo();
8887 final TransformationInfo info = mTransformationInfo;
8888 if (info.mRotationX != rotationX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008889 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008890 info.mRotationX = rotationX;
8891 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008892 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008893 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008894 mDisplayList.setRotationX(rotationX);
8895 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008896 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008897 // View was rejected last time it was drawn by its parent; this may have changed
8898 invalidateParentIfNeeded();
8899 }
Chet Haasefd2b0022010-08-06 13:08:56 -07008900 }
8901 }
8902
8903 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008904 * The amount that the view is scaled in x around the pivot point, as a proportion of
8905 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
8906 *
Joe Onorato93162322010-09-16 15:42:01 -04008907 * <p>By default, this is 1.0f.
8908 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008909 * @see #getPivotX()
8910 * @see #getPivotY()
8911 * @return The scaling factor.
8912 */
Chet Haasea5531132012-02-02 13:41:44 -08008913 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008914 public float getScaleX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008915 return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008916 }
8917
8918 /**
8919 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
8920 * the view's unscaled width. A value of 1 means that no scaling is applied.
8921 *
8922 * @param scaleX The scaling factor.
8923 * @see #getPivotX()
8924 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008925 *
8926 * @attr ref android.R.styleable#View_scaleX
Chet Haasec3aa3612010-06-17 08:50:37 -07008927 */
8928 public void setScaleX(float scaleX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008929 ensureTransformationInfo();
8930 final TransformationInfo info = mTransformationInfo;
8931 if (info.mScaleX != scaleX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008932 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008933 info.mScaleX = scaleX;
8934 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008935 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008936 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008937 mDisplayList.setScaleX(scaleX);
8938 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008939 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008940 // View was rejected last time it was drawn by its parent; this may have changed
8941 invalidateParentIfNeeded();
8942 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008943 }
8944 }
8945
8946 /**
8947 * The amount that the view is scaled in y around the pivot point, as a proportion of
8948 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
8949 *
Joe Onorato93162322010-09-16 15:42:01 -04008950 * <p>By default, this is 1.0f.
8951 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008952 * @see #getPivotX()
8953 * @see #getPivotY()
8954 * @return The scaling factor.
8955 */
Chet Haasea5531132012-02-02 13:41:44 -08008956 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008957 public float getScaleY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008958 return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008959 }
8960
8961 /**
8962 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
8963 * the view's unscaled width. A value of 1 means that no scaling is applied.
8964 *
8965 * @param scaleY The scaling factor.
8966 * @see #getPivotX()
8967 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008968 *
8969 * @attr ref android.R.styleable#View_scaleY
Chet Haasec3aa3612010-06-17 08:50:37 -07008970 */
8971 public void setScaleY(float scaleY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008972 ensureTransformationInfo();
8973 final TransformationInfo info = mTransformationInfo;
8974 if (info.mScaleY != scaleY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008975 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008976 info.mScaleY = scaleY;
8977 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008978 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008979 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008980 mDisplayList.setScaleY(scaleY);
8981 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008982 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008983 // View was rejected last time it was drawn by its parent; this may have changed
8984 invalidateParentIfNeeded();
8985 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008986 }
8987 }
8988
8989 /**
8990 * The x location of the point around which the view is {@link #setRotation(float) rotated}
8991 * and {@link #setScaleX(float) scaled}.
8992 *
8993 * @see #getRotation()
8994 * @see #getScaleX()
8995 * @see #getScaleY()
8996 * @see #getPivotY()
8997 * @return The x location of the pivot point.
Philip Milne6c8ea062012-04-03 17:38:43 -07008998 *
8999 * @attr ref android.R.styleable#View_transformPivotX
Chet Haasec3aa3612010-06-17 08:50:37 -07009000 */
Chet Haasea5531132012-02-02 13:41:44 -08009001 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07009002 public float getPivotX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009003 return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07009004 }
9005
9006 /**
9007 * Sets the x location of the point around which the view is
9008 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
Chet Haasefd2b0022010-08-06 13:08:56 -07009009 * By default, the pivot point is centered on the object.
9010 * Setting this property disables this behavior and causes the view to use only the
9011 * explicitly set pivotX and pivotY values.
Chet Haasec3aa3612010-06-17 08:50:37 -07009012 *
9013 * @param pivotX The x location of the pivot point.
9014 * @see #getRotation()
9015 * @see #getScaleX()
9016 * @see #getScaleY()
9017 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08009018 *
9019 * @attr ref android.R.styleable#View_transformPivotX
Chet Haasec3aa3612010-06-17 08:50:37 -07009020 */
9021 public void setPivotX(float pivotX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009022 ensureTransformationInfo();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009023 mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009024 final TransformationInfo info = mTransformationInfo;
9025 if (info.mPivotX != pivotX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009026 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009027 info.mPivotX = pivotX;
9028 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009029 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009030 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009031 mDisplayList.setPivotX(pivotX);
9032 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009033 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009034 // View was rejected last time it was drawn by its parent; this may have changed
9035 invalidateParentIfNeeded();
9036 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009037 }
9038 }
9039
9040 /**
9041 * The y location of the point around which the view is {@link #setRotation(float) rotated}
9042 * and {@link #setScaleY(float) scaled}.
9043 *
9044 * @see #getRotation()
9045 * @see #getScaleX()
9046 * @see #getScaleY()
9047 * @see #getPivotY()
9048 * @return The y location of the pivot point.
Philip Milne6c8ea062012-04-03 17:38:43 -07009049 *
9050 * @attr ref android.R.styleable#View_transformPivotY
Chet Haasec3aa3612010-06-17 08:50:37 -07009051 */
Chet Haasea5531132012-02-02 13:41:44 -08009052 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07009053 public float getPivotY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009054 return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07009055 }
9056
9057 /**
9058 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
Chet Haasefd2b0022010-08-06 13:08:56 -07009059 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9060 * Setting this property disables this behavior and causes the view to use only the
9061 * explicitly set pivotX and pivotY values.
Chet Haasec3aa3612010-06-17 08:50:37 -07009062 *
9063 * @param pivotY The y location of the pivot point.
9064 * @see #getRotation()
9065 * @see #getScaleX()
9066 * @see #getScaleY()
9067 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08009068 *
9069 * @attr ref android.R.styleable#View_transformPivotY
Chet Haasec3aa3612010-06-17 08:50:37 -07009070 */
9071 public void setPivotY(float pivotY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009072 ensureTransformationInfo();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009073 mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009074 final TransformationInfo info = mTransformationInfo;
9075 if (info.mPivotY != pivotY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009076 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009077 info.mPivotY = pivotY;
9078 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009079 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009080 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009081 mDisplayList.setPivotY(pivotY);
9082 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009083 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009084 // View was rejected last time it was drawn by its parent; this may have changed
9085 invalidateParentIfNeeded();
9086 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009087 }
9088 }
9089
9090 /**
9091 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
9092 * completely transparent and 1 means the view is completely opaque.
9093 *
Joe Onorato93162322010-09-16 15:42:01 -04009094 * <p>By default this is 1.0f.
Chet Haasec3aa3612010-06-17 08:50:37 -07009095 * @return The opacity of the view.
9096 */
Chet Haasea5531132012-02-02 13:41:44 -08009097 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07009098 public float getAlpha() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009099 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07009100 }
9101
9102 /**
Chet Haasedb8c9a62012-03-21 18:54:18 -07009103 * Returns whether this View has content which overlaps. This function, intended to be
9104 * overridden by specific View types, is an optimization when alpha is set on a view. If
9105 * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
9106 * and then composited it into place, which can be expensive. If the view has no overlapping
9107 * rendering, the view can draw each primitive with the appropriate alpha value directly.
9108 * An example of overlapping rendering is a TextView with a background image, such as a
9109 * Button. An example of non-overlapping rendering is a TextView with no background, or
9110 * an ImageView with only the foreground image. The default implementation returns true;
9111 * subclasses should override if they have cases which can be optimized.
9112 *
9113 * @return true if the content in this view might overlap, false otherwise.
9114 */
9115 public boolean hasOverlappingRendering() {
9116 return true;
9117 }
9118
9119 /**
Romain Guy171c5922011-01-06 10:04:23 -08009120 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9121 * completely transparent and 1 means the view is completely opaque.</p>
Joe Malin32736f02011-01-19 16:14:20 -08009122 *
Romain Guy171c5922011-01-06 10:04:23 -08009123 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9124 * responsible for applying the opacity itself. Otherwise, calling this method is
9125 * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
Joe Malin32736f02011-01-19 16:14:20 -08009126 * setting a hardware layer.</p>
Chet Haasec3aa3612010-06-17 08:50:37 -07009127 *
Chet Haasea5531132012-02-02 13:41:44 -08009128 * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
9129 * performance implications. It is generally best to use the alpha property sparingly and
9130 * transiently, as in the case of fading animations.</p>
9131 *
Chet Haasec3aa3612010-06-17 08:50:37 -07009132 * @param alpha The opacity of the view.
Chet Haase73066682010-11-29 15:55:32 -08009133 *
Joe Malin32736f02011-01-19 16:14:20 -08009134 * @see #setLayerType(int, android.graphics.Paint)
9135 *
Chet Haase73066682010-11-29 15:55:32 -08009136 * @attr ref android.R.styleable#View_alpha
Chet Haasec3aa3612010-06-17 08:50:37 -07009137 */
9138 public void setAlpha(float alpha) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009139 ensureTransformationInfo();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009140 if (mTransformationInfo.mAlpha != alpha) {
9141 mTransformationInfo.mAlpha = alpha;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009142 if (onSetAlpha((int) (alpha * 255))) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009143 mPrivateFlags |= PFLAG_ALPHA_SET;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009144 // subclass is handling alpha - don't optimize rendering cache invalidation
Chet Haase9d1992d2012-03-13 11:03:25 -07009145 invalidateParentCaches();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009146 invalidate(true);
9147 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009148 mPrivateFlags &= ~PFLAG_ALPHA_SET;
Chet Haase9d1992d2012-03-13 11:03:25 -07009149 invalidateViewProperty(true, false);
Chet Haase1271e2c2012-04-20 09:54:27 -07009150 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009151 mDisplayList.setAlpha(alpha);
9152 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009153 }
Chet Haaseed032702010-10-01 14:05:54 -07009154 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009155 }
9156
9157 /**
Chet Haasea00f3862011-02-22 06:34:40 -08009158 * Faster version of setAlpha() which performs the same steps except there are
9159 * no calls to invalidate(). The caller of this function should perform proper invalidation
9160 * on the parent and this object. The return value indicates whether the subclass handles
9161 * alpha (the return value for onSetAlpha()).
9162 *
9163 * @param alpha The new value for the alpha property
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009164 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9165 * the new value for the alpha property is different from the old value
Chet Haasea00f3862011-02-22 06:34:40 -08009166 */
9167 boolean setAlphaNoInvalidation(float alpha) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009168 ensureTransformationInfo();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009169 if (mTransformationInfo.mAlpha != alpha) {
9170 mTransformationInfo.mAlpha = alpha;
9171 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9172 if (subclassHandlesAlpha) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009173 mPrivateFlags |= PFLAG_ALPHA_SET;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009174 return true;
9175 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009176 mPrivateFlags &= ~PFLAG_ALPHA_SET;
Chet Haase1271e2c2012-04-20 09:54:27 -07009177 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009178 mDisplayList.setAlpha(alpha);
9179 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009180 }
Chet Haasea00f3862011-02-22 06:34:40 -08009181 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009182 return false;
Chet Haasea00f3862011-02-22 06:34:40 -08009183 }
9184
9185 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009186 * Top position of this view relative to its parent.
9187 *
9188 * @return The top of this view, in pixels.
9189 */
9190 @ViewDebug.CapturedViewProperty
9191 public final int getTop() {
9192 return mTop;
9193 }
9194
9195 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009196 * Sets the top position of this view relative to its parent. This method is meant to be called
9197 * by the layout system and should not generally be called otherwise, because the property
9198 * may be changed at any time by the layout.
9199 *
9200 * @param top The top of this view, in pixels.
9201 */
9202 public final void setTop(int top) {
9203 if (top != mTop) {
Jeff Brown86671742010-09-30 20:00:15 -07009204 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009205 final boolean matrixIsIdentity = mTransformationInfo == null
9206 || mTransformationInfo.mMatrixIsIdentity;
9207 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009208 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009209 int minTop;
9210 int yLoc;
9211 if (top < mTop) {
9212 minTop = top;
9213 yLoc = top - mTop;
9214 } else {
9215 minTop = mTop;
9216 yLoc = 0;
9217 }
Chet Haasee9140a72011-02-16 16:23:29 -08009218 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009219 }
9220 } else {
9221 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009222 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009223 }
9224
Chet Haaseed032702010-10-01 14:05:54 -07009225 int width = mRight - mLeft;
9226 int oldHeight = mBottom - mTop;
9227
Chet Haase21cd1382010-09-01 17:42:29 -07009228 mTop = top;
Chet Haase1271e2c2012-04-20 09:54:27 -07009229 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009230 mDisplayList.setTop(mTop);
9231 }
Chet Haase21cd1382010-09-01 17:42:29 -07009232
Chet Haaseed032702010-10-01 14:05:54 -07009233 onSizeChanged(width, mBottom - mTop, width, oldHeight);
9234
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009235 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009236 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009237 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009238 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009239 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009240 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009241 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009242 }
Chet Haase55dbb652010-12-21 20:15:08 -08009243 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009244 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009245 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009246 // View was rejected last time it was drawn by its parent; this may have changed
9247 invalidateParentIfNeeded();
9248 }
Chet Haase21cd1382010-09-01 17:42:29 -07009249 }
9250 }
9251
9252 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009253 * Bottom position of this view relative to its parent.
9254 *
9255 * @return The bottom of this view, in pixels.
9256 */
9257 @ViewDebug.CapturedViewProperty
9258 public final int getBottom() {
9259 return mBottom;
9260 }
9261
9262 /**
Michael Jurkadab559a2011-01-04 20:31:51 -08009263 * True if this view has changed since the last time being drawn.
9264 *
9265 * @return The dirty state of this view.
9266 */
9267 public boolean isDirty() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009268 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
Michael Jurkadab559a2011-01-04 20:31:51 -08009269 }
9270
9271 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009272 * Sets the bottom position of this view relative to its parent. This method is meant to be
9273 * called by the layout system and should not generally be called otherwise, because the
9274 * property may be changed at any time by the layout.
9275 *
9276 * @param bottom The bottom of this view, in pixels.
9277 */
9278 public final void setBottom(int bottom) {
9279 if (bottom != mBottom) {
Jeff Brown86671742010-09-30 20:00:15 -07009280 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009281 final boolean matrixIsIdentity = mTransformationInfo == null
9282 || mTransformationInfo.mMatrixIsIdentity;
9283 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009284 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009285 int maxBottom;
9286 if (bottom < mBottom) {
9287 maxBottom = mBottom;
9288 } else {
9289 maxBottom = bottom;
9290 }
Chet Haasee9140a72011-02-16 16:23:29 -08009291 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009292 }
9293 } else {
9294 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009295 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009296 }
9297
Chet Haaseed032702010-10-01 14:05:54 -07009298 int width = mRight - mLeft;
9299 int oldHeight = mBottom - mTop;
9300
Chet Haase21cd1382010-09-01 17:42:29 -07009301 mBottom = bottom;
Chet Haase1271e2c2012-04-20 09:54:27 -07009302 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009303 mDisplayList.setBottom(mBottom);
9304 }
Chet Haase21cd1382010-09-01 17:42:29 -07009305
Chet Haaseed032702010-10-01 14:05:54 -07009306 onSizeChanged(width, mBottom - mTop, width, oldHeight);
9307
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009308 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009309 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009310 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009311 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009312 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009313 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009314 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009315 }
Chet Haase55dbb652010-12-21 20:15:08 -08009316 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009317 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009318 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009319 // View was rejected last time it was drawn by its parent; this may have changed
9320 invalidateParentIfNeeded();
9321 }
Chet Haase21cd1382010-09-01 17:42:29 -07009322 }
9323 }
9324
9325 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009326 * Left position of this view relative to its parent.
9327 *
9328 * @return The left edge of this view, in pixels.
9329 */
9330 @ViewDebug.CapturedViewProperty
9331 public final int getLeft() {
9332 return mLeft;
9333 }
9334
9335 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009336 * Sets the left position of this view relative to its parent. This method is meant to be called
9337 * by the layout system and should not generally be called otherwise, because the property
9338 * may be changed at any time by the layout.
9339 *
9340 * @param left The bottom of this view, in pixels.
9341 */
9342 public final void setLeft(int left) {
9343 if (left != mLeft) {
Jeff Brown86671742010-09-30 20:00:15 -07009344 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009345 final boolean matrixIsIdentity = mTransformationInfo == null
9346 || mTransformationInfo.mMatrixIsIdentity;
9347 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009348 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009349 int minLeft;
9350 int xLoc;
9351 if (left < mLeft) {
9352 minLeft = left;
9353 xLoc = left - mLeft;
9354 } else {
9355 minLeft = mLeft;
9356 xLoc = 0;
9357 }
Chet Haasee9140a72011-02-16 16:23:29 -08009358 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009359 }
9360 } else {
9361 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009362 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009363 }
9364
Chet Haaseed032702010-10-01 14:05:54 -07009365 int oldWidth = mRight - mLeft;
9366 int height = mBottom - mTop;
9367
Chet Haase21cd1382010-09-01 17:42:29 -07009368 mLeft = left;
Chet Haase1271e2c2012-04-20 09:54:27 -07009369 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009370 mDisplayList.setLeft(left);
9371 }
Chet Haase21cd1382010-09-01 17:42:29 -07009372
Chet Haaseed032702010-10-01 14:05:54 -07009373 onSizeChanged(mRight - mLeft, height, oldWidth, height);
9374
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009375 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009376 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009377 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009378 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009379 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009380 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009381 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009382 }
Chet Haase55dbb652010-12-21 20:15:08 -08009383 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009384 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009385 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009386 // View was rejected last time it was drawn by its parent; this may have changed
9387 invalidateParentIfNeeded();
9388 }
Chet Haase21cd1382010-09-01 17:42:29 -07009389 }
9390 }
9391
9392 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009393 * Right position of this view relative to its parent.
9394 *
9395 * @return The right edge of this view, in pixels.
9396 */
9397 @ViewDebug.CapturedViewProperty
9398 public final int getRight() {
9399 return mRight;
9400 }
9401
9402 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009403 * Sets the right position of this view relative to its parent. This method is meant to be called
9404 * by the layout system and should not generally be called otherwise, because the property
9405 * may be changed at any time by the layout.
9406 *
9407 * @param right The bottom of this view, in pixels.
9408 */
9409 public final void setRight(int right) {
9410 if (right != mRight) {
Jeff Brown86671742010-09-30 20:00:15 -07009411 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009412 final boolean matrixIsIdentity = mTransformationInfo == null
9413 || mTransformationInfo.mMatrixIsIdentity;
9414 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009415 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009416 int maxRight;
9417 if (right < mRight) {
9418 maxRight = mRight;
9419 } else {
9420 maxRight = right;
9421 }
Chet Haasee9140a72011-02-16 16:23:29 -08009422 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009423 }
9424 } else {
9425 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009426 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009427 }
9428
Chet Haaseed032702010-10-01 14:05:54 -07009429 int oldWidth = mRight - mLeft;
9430 int height = mBottom - mTop;
9431
Chet Haase21cd1382010-09-01 17:42:29 -07009432 mRight = right;
Chet Haase1271e2c2012-04-20 09:54:27 -07009433 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009434 mDisplayList.setRight(mRight);
9435 }
Chet Haase21cd1382010-09-01 17:42:29 -07009436
Chet Haaseed032702010-10-01 14:05:54 -07009437 onSizeChanged(mRight - mLeft, height, oldWidth, height);
9438
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009439 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009440 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009441 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009442 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009443 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009444 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009445 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009446 }
Chet Haase55dbb652010-12-21 20:15:08 -08009447 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009448 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009449 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009450 // View was rejected last time it was drawn by its parent; this may have changed
9451 invalidateParentIfNeeded();
9452 }
Chet Haase21cd1382010-09-01 17:42:29 -07009453 }
9454 }
9455
9456 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009457 * The visual x position of this view, in pixels. This is equivalent to the
9458 * {@link #setTranslationX(float) translationX} property plus the current
Joe Malin32736f02011-01-19 16:14:20 -08009459 * {@link #getLeft() left} property.
Chet Haasec3aa3612010-06-17 08:50:37 -07009460 *
Chet Haasedf030d22010-07-30 17:22:38 -07009461 * @return The visual x position of this view, in pixels.
Chet Haasec3aa3612010-06-17 08:50:37 -07009462 */
Chet Haasea5531132012-02-02 13:41:44 -08009463 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009464 public float getX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009465 return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
Chet Haasedf030d22010-07-30 17:22:38 -07009466 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009467
Chet Haasedf030d22010-07-30 17:22:38 -07009468 /**
9469 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9470 * {@link #setTranslationX(float) translationX} property to be the difference between
9471 * the x value passed in and the current {@link #getLeft() left} property.
9472 *
9473 * @param x The visual x position of this view, in pixels.
9474 */
9475 public void setX(float x) {
9476 setTranslationX(x - mLeft);
9477 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009478
Chet Haasedf030d22010-07-30 17:22:38 -07009479 /**
9480 * The visual y position of this view, in pixels. This is equivalent to the
9481 * {@link #setTranslationY(float) translationY} property plus the current
9482 * {@link #getTop() top} property.
9483 *
9484 * @return The visual y position of this view, in pixels.
9485 */
Chet Haasea5531132012-02-02 13:41:44 -08009486 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009487 public float getY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009488 return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
Chet Haasedf030d22010-07-30 17:22:38 -07009489 }
9490
9491 /**
9492 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9493 * {@link #setTranslationY(float) translationY} property to be the difference between
9494 * the y value passed in and the current {@link #getTop() top} property.
9495 *
9496 * @param y The visual y position of this view, in pixels.
9497 */
9498 public void setY(float y) {
9499 setTranslationY(y - mTop);
9500 }
9501
9502
9503 /**
9504 * The horizontal location of this view relative to its {@link #getLeft() left} position.
9505 * This position is post-layout, in addition to wherever the object's
9506 * layout placed it.
9507 *
9508 * @return The horizontal position of this view relative to its left position, in pixels.
9509 */
Chet Haasea5531132012-02-02 13:41:44 -08009510 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009511 public float getTranslationX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009512 return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
Chet Haasedf030d22010-07-30 17:22:38 -07009513 }
9514
9515 /**
9516 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9517 * This effectively positions the object post-layout, in addition to wherever the object's
9518 * layout placed it.
9519 *
9520 * @param translationX The horizontal position of this view relative to its left position,
9521 * in pixels.
Chet Haase73066682010-11-29 15:55:32 -08009522 *
9523 * @attr ref android.R.styleable#View_translationX
Chet Haasedf030d22010-07-30 17:22:38 -07009524 */
9525 public void setTranslationX(float translationX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009526 ensureTransformationInfo();
9527 final TransformationInfo info = mTransformationInfo;
9528 if (info.mTranslationX != translationX) {
Chet Haasedf030d22010-07-30 17:22:38 -07009529 // Double-invalidation is necessary to capture view's old and new areas
Chet Haase9d1992d2012-03-13 11:03:25 -07009530 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009531 info.mTranslationX = translationX;
9532 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009533 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009534 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009535 mDisplayList.setTranslationX(translationX);
9536 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009537 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009538 // View was rejected last time it was drawn by its parent; this may have changed
9539 invalidateParentIfNeeded();
9540 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009541 }
9542 }
9543
9544 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009545 * The horizontal location of this view relative to its {@link #getTop() top} position.
9546 * This position is post-layout, in addition to wherever the object's
9547 * layout placed it.
Chet Haasec3aa3612010-06-17 08:50:37 -07009548 *
Chet Haasedf030d22010-07-30 17:22:38 -07009549 * @return The vertical position of this view relative to its top position,
9550 * in pixels.
Chet Haasec3aa3612010-06-17 08:50:37 -07009551 */
Chet Haasea5531132012-02-02 13:41:44 -08009552 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009553 public float getTranslationY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009554 return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07009555 }
9556
9557 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009558 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9559 * This effectively positions the object post-layout, in addition to wherever the object's
9560 * layout placed it.
Chet Haasec3aa3612010-06-17 08:50:37 -07009561 *
Chet Haasedf030d22010-07-30 17:22:38 -07009562 * @param translationY The vertical position of this view relative to its top position,
9563 * in pixels.
Chet Haase73066682010-11-29 15:55:32 -08009564 *
9565 * @attr ref android.R.styleable#View_translationY
Chet Haasec3aa3612010-06-17 08:50:37 -07009566 */
Chet Haasedf030d22010-07-30 17:22:38 -07009567 public void setTranslationY(float translationY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009568 ensureTransformationInfo();
9569 final TransformationInfo info = mTransformationInfo;
9570 if (info.mTranslationY != translationY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009571 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009572 info.mTranslationY = translationY;
9573 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009574 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009575 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009576 mDisplayList.setTranslationY(translationY);
9577 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009578 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009579 // View was rejected last time it was drawn by its parent; this may have changed
9580 invalidateParentIfNeeded();
9581 }
Chet Haasedf030d22010-07-30 17:22:38 -07009582 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009583 }
9584
9585 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009586 * Hit rectangle in parent's coordinates
9587 *
9588 * @param outRect The hit rectangle of the view.
9589 */
9590 public void getHitRect(Rect outRect) {
Jeff Brown86671742010-09-30 20:00:15 -07009591 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009592 final TransformationInfo info = mTransformationInfo;
9593 if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009594 outRect.set(mLeft, mTop, mRight, mBottom);
9595 } else {
9596 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009597 tmpRect.set(-info.mPivotX, -info.mPivotY,
9598 getWidth() - info.mPivotX, getHeight() - info.mPivotY);
9599 info.mMatrix.mapRect(tmpRect);
Romain Guy33e72ae2010-07-17 12:40:29 -07009600 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9601 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
Chet Haasec3aa3612010-06-17 08:50:37 -07009602 }
9603 }
9604
9605 /**
Jeff Brown20e987b2010-08-23 12:01:02 -07009606 * Determines whether the given point, in local coordinates is inside the view.
9607 */
9608 /*package*/ final boolean pointInView(float localX, float localY) {
9609 return localX >= 0 && localX < (mRight - mLeft)
9610 && localY >= 0 && localY < (mBottom - mTop);
9611 }
9612
9613 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07009614 * Utility method to determine whether the given point, in local coordinates,
9615 * is inside the view, where the area of the view is expanded by the slop factor.
9616 * This method is called while processing touch-move events to determine if the event
9617 * is still within the view.
9618 */
9619 private boolean pointInView(float localX, float localY, float slop) {
Jeff Brown20e987b2010-08-23 12:01:02 -07009620 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
Romain Guy33e72ae2010-07-17 12:40:29 -07009621 localY < ((mBottom - mTop) + slop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009622 }
9623
9624 /**
9625 * When a view has focus and the user navigates away from it, the next view is searched for
9626 * starting from the rectangle filled in by this method.
9627 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07009628 * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
9629 * of the view. However, if your view maintains some idea of internal selection,
9630 * such as a cursor, or a selected row or column, you should override this method and
9631 * fill in a more specific rectangle.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009632 *
9633 * @param r The rectangle to fill in, in this view's coordinates.
9634 */
9635 public void getFocusedRect(Rect r) {
9636 getDrawingRect(r);
9637 }
9638
9639 /**
9640 * If some part of this view is not clipped by any of its parents, then
9641 * return that area in r in global (root) coordinates. To convert r to local
Gilles Debunnecea45132011-11-24 02:19:27 +01009642 * coordinates (without taking possible View rotations into account), offset
9643 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
9644 * If the view is completely clipped or translated out, return false.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009645 *
9646 * @param r If true is returned, r holds the global coordinates of the
9647 * visible portion of this view.
9648 * @param globalOffset If true is returned, globalOffset holds the dx,dy
9649 * between this view and its root. globalOffet may be null.
9650 * @return true if r is non-empty (i.e. part of the view is visible at the
9651 * root level.
9652 */
9653 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
9654 int width = mRight - mLeft;
9655 int height = mBottom - mTop;
9656 if (width > 0 && height > 0) {
9657 r.set(0, 0, width, height);
9658 if (globalOffset != null) {
9659 globalOffset.set(-mScrollX, -mScrollY);
9660 }
9661 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
9662 }
9663 return false;
9664 }
9665
9666 public final boolean getGlobalVisibleRect(Rect r) {
9667 return getGlobalVisibleRect(r, null);
9668 }
9669
9670 public final boolean getLocalVisibleRect(Rect r) {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07009671 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009672 if (getGlobalVisibleRect(r, offset)) {
9673 r.offset(-offset.x, -offset.y); // make r local
9674 return true;
9675 }
9676 return false;
9677 }
9678
9679 /**
9680 * Offset this view's vertical location by the specified number of pixels.
9681 *
9682 * @param offset the number of pixels to offset the view by
9683 */
9684 public void offsetTopAndBottom(int offset) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009685 if (offset != 0) {
Jeff Brown86671742010-09-30 20:00:15 -07009686 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009687 final boolean matrixIsIdentity = mTransformationInfo == null
9688 || mTransformationInfo.mMatrixIsIdentity;
9689 if (matrixIsIdentity) {
Chet Haase1271e2c2012-04-20 09:54:27 -07009690 if (mDisplayList != null) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009691 invalidateViewProperty(false, false);
9692 } else {
9693 final ViewParent p = mParent;
9694 if (p != null && mAttachInfo != null) {
9695 final Rect r = mAttachInfo.mTmpInvalRect;
9696 int minTop;
9697 int maxBottom;
9698 int yLoc;
9699 if (offset < 0) {
9700 minTop = mTop + offset;
9701 maxBottom = mBottom;
9702 yLoc = offset;
9703 } else {
9704 minTop = mTop;
9705 maxBottom = mBottom + offset;
9706 yLoc = 0;
9707 }
9708 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
9709 p.invalidateChild(this, r);
Chet Haase8fbf8d22010-07-30 15:01:32 -07009710 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009711 }
9712 } else {
Chet Haase9d1992d2012-03-13 11:03:25 -07009713 invalidateViewProperty(false, false);
Chet Haasec3aa3612010-06-17 08:50:37 -07009714 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009715
Chet Haasec3aa3612010-06-17 08:50:37 -07009716 mTop += offset;
9717 mBottom += offset;
Chet Haase1271e2c2012-04-20 09:54:27 -07009718 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009719 mDisplayList.offsetTopBottom(offset);
Chet Haase9d1992d2012-03-13 11:03:25 -07009720 invalidateViewProperty(false, false);
9721 } else {
9722 if (!matrixIsIdentity) {
9723 invalidateViewProperty(false, true);
9724 }
9725 invalidateParentIfNeeded();
Chet Haasea1cff502012-02-21 13:43:44 -08009726 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009727 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009728 }
9729
9730 /**
9731 * Offset this view's horizontal location by the specified amount of pixels.
9732 *
9733 * @param offset the numer of pixels to offset the view by
9734 */
9735 public void offsetLeftAndRight(int offset) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009736 if (offset != 0) {
Jeff Brown86671742010-09-30 20:00:15 -07009737 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009738 final boolean matrixIsIdentity = mTransformationInfo == null
9739 || mTransformationInfo.mMatrixIsIdentity;
9740 if (matrixIsIdentity) {
Chet Haase1271e2c2012-04-20 09:54:27 -07009741 if (mDisplayList != null) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009742 invalidateViewProperty(false, false);
9743 } else {
9744 final ViewParent p = mParent;
9745 if (p != null && mAttachInfo != null) {
9746 final Rect r = mAttachInfo.mTmpInvalRect;
9747 int minLeft;
9748 int maxRight;
9749 if (offset < 0) {
9750 minLeft = mLeft + offset;
9751 maxRight = mRight;
9752 } else {
9753 minLeft = mLeft;
9754 maxRight = mRight + offset;
9755 }
9756 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
9757 p.invalidateChild(this, r);
Chet Haase8fbf8d22010-07-30 15:01:32 -07009758 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009759 }
9760 } else {
Chet Haase9d1992d2012-03-13 11:03:25 -07009761 invalidateViewProperty(false, false);
Chet Haasec3aa3612010-06-17 08:50:37 -07009762 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009763
Chet Haasec3aa3612010-06-17 08:50:37 -07009764 mLeft += offset;
9765 mRight += offset;
Chet Haase1271e2c2012-04-20 09:54:27 -07009766 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009767 mDisplayList.offsetLeftRight(offset);
Chet Haase9d1992d2012-03-13 11:03:25 -07009768 invalidateViewProperty(false, false);
9769 } else {
9770 if (!matrixIsIdentity) {
9771 invalidateViewProperty(false, true);
9772 }
9773 invalidateParentIfNeeded();
Chet Haasea1cff502012-02-21 13:43:44 -08009774 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009775 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009776 }
9777
9778 /**
9779 * Get the LayoutParams associated with this view. All views should have
9780 * layout parameters. These supply parameters to the <i>parent</i> of this
9781 * view specifying how it should be arranged. There are many subclasses of
9782 * ViewGroup.LayoutParams, and these correspond to the different subclasses
9783 * of ViewGroup that are responsible for arranging their children.
Romain Guy01c174b2011-02-22 11:51:06 -08009784 *
9785 * This method may return null if this View is not attached to a parent
9786 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
9787 * was not invoked successfully. When a View is attached to a parent
9788 * ViewGroup, this method must not return null.
9789 *
9790 * @return The LayoutParams associated with this view, or null if no
9791 * parameters have been set yet
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009792 */
Konstantin Lopyrev91a7f5f2010-08-10 18:54:54 -07009793 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009794 public ViewGroup.LayoutParams getLayoutParams() {
9795 return mLayoutParams;
9796 }
9797
9798 /**
9799 * Set the layout parameters associated with this view. These supply
9800 * parameters to the <i>parent</i> of this view specifying how it should be
9801 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
9802 * correspond to the different subclasses of ViewGroup that are responsible
9803 * for arranging their children.
9804 *
Romain Guy01c174b2011-02-22 11:51:06 -08009805 * @param params The layout parameters for this view, cannot be null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009806 */
9807 public void setLayoutParams(ViewGroup.LayoutParams params) {
9808 if (params == null) {
Romain Guy01c174b2011-02-22 11:51:06 -08009809 throw new NullPointerException("Layout parameters cannot be null");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009810 }
9811 mLayoutParams = params;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07009812 resolveLayoutParams();
Philip Milned7dd8902012-01-26 16:55:30 -08009813 if (mParent instanceof ViewGroup) {
9814 ((ViewGroup) mParent).onSetLayoutParams(this, params);
9815 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009816 requestLayout();
9817 }
9818
9819 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07009820 * Resolve the layout parameters depending on the resolved layout direction
9821 */
9822 private void resolveLayoutParams() {
9823 if (mLayoutParams != null) {
9824 mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
9825 }
9826 }
9827
9828 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009829 * Set the scrolled position of your view. This will cause a call to
9830 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9831 * invalidated.
9832 * @param x the x position to scroll to
9833 * @param y the y position to scroll to
9834 */
9835 public void scrollTo(int x, int y) {
9836 if (mScrollX != x || mScrollY != y) {
9837 int oldX = mScrollX;
9838 int oldY = mScrollY;
9839 mScrollX = x;
9840 mScrollY = y;
Romain Guy0fd89bf2011-01-26 15:41:30 -08009841 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009842 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
Mike Cleronf116bf82009-09-27 19:14:12 -07009843 if (!awakenScrollBars()) {
Adam Powelldf3ae4f2012-04-10 18:55:22 -07009844 postInvalidateOnAnimation();
Mike Cleronf116bf82009-09-27 19:14:12 -07009845 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009846 }
9847 }
9848
9849 /**
9850 * Move the scrolled position of your view. This will cause a call to
9851 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9852 * invalidated.
9853 * @param x the amount of pixels to scroll by horizontally
9854 * @param y the amount of pixels to scroll by vertically
9855 */
9856 public void scrollBy(int x, int y) {
9857 scrollTo(mScrollX + x, mScrollY + y);
9858 }
9859
9860 /**
Mike Cleronf116bf82009-09-27 19:14:12 -07009861 * <p>Trigger the scrollbars to draw. When invoked this method starts an
9862 * animation to fade the scrollbars out after a default delay. If a subclass
9863 * provides animated scrolling, the start delay should equal the duration
9864 * of the scrolling animation.</p>
9865 *
9866 * <p>The animation starts only if at least one of the scrollbars is
9867 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
9868 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9869 * this method returns true, and false otherwise. If the animation is
9870 * started, this method calls {@link #invalidate()}; in that case the
9871 * caller should not call {@link #invalidate()}.</p>
9872 *
9873 * <p>This method should be invoked every time a subclass directly updates
Mike Cleronfe81d382009-09-28 14:22:16 -07009874 * the scroll parameters.</p>
Mike Cleronf116bf82009-09-27 19:14:12 -07009875 *
9876 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
9877 * and {@link #scrollTo(int, int)}.</p>
9878 *
9879 * @return true if the animation is played, false otherwise
9880 *
9881 * @see #awakenScrollBars(int)
Mike Cleronf116bf82009-09-27 19:14:12 -07009882 * @see #scrollBy(int, int)
9883 * @see #scrollTo(int, int)
9884 * @see #isHorizontalScrollBarEnabled()
9885 * @see #isVerticalScrollBarEnabled()
9886 * @see #setHorizontalScrollBarEnabled(boolean)
9887 * @see #setVerticalScrollBarEnabled(boolean)
9888 */
9889 protected boolean awakenScrollBars() {
9890 return mScrollCache != null &&
Mike Cleron290947b2009-09-29 18:34:32 -07009891 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
Mike Cleronf116bf82009-09-27 19:14:12 -07009892 }
9893
9894 /**
Adam Powell8568c3a2010-04-19 14:26:11 -07009895 * Trigger the scrollbars to draw.
9896 * This method differs from awakenScrollBars() only in its default duration.
9897 * initialAwakenScrollBars() will show the scroll bars for longer than
9898 * usual to give the user more of a chance to notice them.
9899 *
9900 * @return true if the animation is played, false otherwise.
9901 */
9902 private boolean initialAwakenScrollBars() {
9903 return mScrollCache != null &&
9904 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
9905 }
9906
9907 /**
Mike Cleronf116bf82009-09-27 19:14:12 -07009908 * <p>
9909 * Trigger the scrollbars to draw. When invoked this method starts an
9910 * animation to fade the scrollbars out after a fixed delay. If a subclass
9911 * provides animated scrolling, the start delay should equal the duration of
9912 * the scrolling animation.
9913 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009914 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009915 * <p>
9916 * The animation starts only if at least one of the scrollbars is enabled,
9917 * as specified by {@link #isHorizontalScrollBarEnabled()} and
9918 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9919 * this method returns true, and false otherwise. If the animation is
9920 * started, this method calls {@link #invalidate()}; in that case the caller
9921 * should not call {@link #invalidate()}.
9922 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009923 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009924 * <p>
9925 * This method should be invoked everytime a subclass directly updates the
Mike Cleronfe81d382009-09-28 14:22:16 -07009926 * scroll parameters.
Mike Cleronf116bf82009-09-27 19:14:12 -07009927 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009928 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009929 * @param startDelay the delay, in milliseconds, after which the animation
9930 * should start; when the delay is 0, the animation starts
9931 * immediately
9932 * @return true if the animation is played, false otherwise
Joe Malin32736f02011-01-19 16:14:20 -08009933 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009934 * @see #scrollBy(int, int)
9935 * @see #scrollTo(int, int)
9936 * @see #isHorizontalScrollBarEnabled()
9937 * @see #isVerticalScrollBarEnabled()
9938 * @see #setHorizontalScrollBarEnabled(boolean)
9939 * @see #setVerticalScrollBarEnabled(boolean)
9940 */
9941 protected boolean awakenScrollBars(int startDelay) {
Mike Cleron290947b2009-09-29 18:34:32 -07009942 return awakenScrollBars(startDelay, true);
9943 }
Joe Malin32736f02011-01-19 16:14:20 -08009944
Mike Cleron290947b2009-09-29 18:34:32 -07009945 /**
9946 * <p>
9947 * Trigger the scrollbars to draw. When invoked this method starts an
9948 * animation to fade the scrollbars out after a fixed delay. If a subclass
9949 * provides animated scrolling, the start delay should equal the duration of
9950 * the scrolling animation.
9951 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009952 *
Mike Cleron290947b2009-09-29 18:34:32 -07009953 * <p>
9954 * The animation starts only if at least one of the scrollbars is enabled,
9955 * as specified by {@link #isHorizontalScrollBarEnabled()} and
9956 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9957 * this method returns true, and false otherwise. If the animation is
Joe Malin32736f02011-01-19 16:14:20 -08009958 * started, this method calls {@link #invalidate()} if the invalidate parameter
Mike Cleron290947b2009-09-29 18:34:32 -07009959 * is set to true; in that case the caller
9960 * should not call {@link #invalidate()}.
9961 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009962 *
Mike Cleron290947b2009-09-29 18:34:32 -07009963 * <p>
9964 * This method should be invoked everytime a subclass directly updates the
9965 * scroll parameters.
9966 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009967 *
Mike Cleron290947b2009-09-29 18:34:32 -07009968 * @param startDelay the delay, in milliseconds, after which the animation
9969 * should start; when the delay is 0, the animation starts
9970 * immediately
Joe Malin32736f02011-01-19 16:14:20 -08009971 *
Mike Cleron290947b2009-09-29 18:34:32 -07009972 * @param invalidate Wheter this method should call invalidate
Joe Malin32736f02011-01-19 16:14:20 -08009973 *
Mike Cleron290947b2009-09-29 18:34:32 -07009974 * @return true if the animation is played, false otherwise
Joe Malin32736f02011-01-19 16:14:20 -08009975 *
Mike Cleron290947b2009-09-29 18:34:32 -07009976 * @see #scrollBy(int, int)
9977 * @see #scrollTo(int, int)
9978 * @see #isHorizontalScrollBarEnabled()
9979 * @see #isVerticalScrollBarEnabled()
9980 * @see #setHorizontalScrollBarEnabled(boolean)
9981 * @see #setVerticalScrollBarEnabled(boolean)
9982 */
9983 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
Mike Cleronf116bf82009-09-27 19:14:12 -07009984 final ScrollabilityCache scrollCache = mScrollCache;
Joe Malin32736f02011-01-19 16:14:20 -08009985
Mike Cleronf116bf82009-09-27 19:14:12 -07009986 if (scrollCache == null || !scrollCache.fadeScrollBars) {
9987 return false;
9988 }
9989
9990 if (scrollCache.scrollBar == null) {
9991 scrollCache.scrollBar = new ScrollBarDrawable();
9992 }
9993
9994 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
9995
Mike Cleron290947b2009-09-29 18:34:32 -07009996 if (invalidate) {
9997 // Invalidate to show the scrollbars
Adam Powelldf3ae4f2012-04-10 18:55:22 -07009998 postInvalidateOnAnimation();
Mike Cleron290947b2009-09-29 18:34:32 -07009999 }
Mike Cleronf116bf82009-09-27 19:14:12 -070010000
10001 if (scrollCache.state == ScrollabilityCache.OFF) {
10002 // FIXME: this is copied from WindowManagerService.
10003 // We should get this value from the system when it
10004 // is possible to do so.
10005 final int KEY_REPEAT_FIRST_DELAY = 750;
10006 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
10007 }
10008
10009 // Tell mScrollCache when we should start fading. This may
10010 // extend the fade start time if one was already scheduled
Mike Cleron3ecd58c2009-09-28 11:39:02 -070010011 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
Mike Cleronf116bf82009-09-27 19:14:12 -070010012 scrollCache.fadeStartTime = fadeStartTime;
10013 scrollCache.state = ScrollabilityCache.ON;
10014
10015 // Schedule our fader to run, unscheduling any old ones first
10016 if (mAttachInfo != null) {
10017 mAttachInfo.mHandler.removeCallbacks(scrollCache);
10018 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
10019 }
10020
10021 return true;
10022 }
10023
10024 return false;
10025 }
10026
10027 /**
Chet Haaseaceafe62011-08-26 15:44:33 -070010028 * Do not invalidate views which are not visible and which are not running an animation. They
10029 * will not get drawn and they should not set dirty flags as if they will be drawn
10030 */
10031 private boolean skipInvalidate() {
10032 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
10033 (!(mParent instanceof ViewGroup) ||
10034 !((ViewGroup) mParent).isViewTransitioning(this));
10035 }
10036 /**
Joe Fernandez558459f2011-10-13 16:47:36 -070010037 * Mark the area defined by dirty as needing to be drawn. If the view is
Romain Guy5c22a8c2011-05-13 11:48:45 -070010038 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
10039 * in the future. This must be called from a UI thread. To call from a non-UI
10040 * thread, call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010041 *
10042 * WARNING: This method is destructive to dirty.
10043 * @param dirty the rectangle representing the bounds of the dirty region
10044 */
10045 public void invalidate(Rect dirty) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010046 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010047 return;
10048 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070010049 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10050 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10051 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10052 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10053 mPrivateFlags |= PFLAG_INVALIDATED;
10054 mPrivateFlags |= PFLAG_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010055 final ViewParent p = mParent;
10056 final AttachInfo ai = mAttachInfo;
Romain Guy7d7b5492011-01-24 16:33:45 -080010057 //noinspection PointlessBooleanExpression,ConstantConditions
10058 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10059 if (p != null && ai != null && ai.mHardwareAccelerated) {
10060 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010061 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010062 p.invalidateChild(this, null);
10063 return;
10064 }
Romain Guyaf636eb2010-12-09 17:47:21 -080010065 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010066 if (p != null && ai != null) {
10067 final int scrollX = mScrollX;
10068 final int scrollY = mScrollY;
10069 final Rect r = ai.mTmpInvalRect;
10070 r.set(dirty.left - scrollX, dirty.top - scrollY,
10071 dirty.right - scrollX, dirty.bottom - scrollY);
10072 mParent.invalidateChild(this, r);
10073 }
10074 }
10075 }
10076
10077 /**
Joe Fernandez558459f2011-10-13 16:47:36 -070010078 * Mark the area defined by the rect (l,t,r,b) as needing to be drawn.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010079 * The coordinates of the dirty rect are relative to the view.
Romain Guy5c22a8c2011-05-13 11:48:45 -070010080 * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
10081 * will be called at some point in the future. This must be called from
10082 * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010083 * @param l the left position of the dirty region
10084 * @param t the top position of the dirty region
10085 * @param r the right position of the dirty region
10086 * @param b the bottom position of the dirty region
10087 */
10088 public void invalidate(int l, int t, int r, int b) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010089 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010090 return;
10091 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070010092 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10093 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10094 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10095 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10096 mPrivateFlags |= PFLAG_INVALIDATED;
10097 mPrivateFlags |= PFLAG_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010098 final ViewParent p = mParent;
10099 final AttachInfo ai = mAttachInfo;
Romain Guy7d7b5492011-01-24 16:33:45 -080010100 //noinspection PointlessBooleanExpression,ConstantConditions
10101 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10102 if (p != null && ai != null && ai.mHardwareAccelerated) {
10103 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010104 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010105 p.invalidateChild(this, null);
10106 return;
10107 }
Chet Haasef2f7d8f2010-12-03 14:08:14 -080010108 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010109 if (p != null && ai != null && l < r && t < b) {
10110 final int scrollX = mScrollX;
10111 final int scrollY = mScrollY;
10112 final Rect tmpr = ai.mTmpInvalRect;
10113 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
10114 p.invalidateChild(this, tmpr);
10115 }
10116 }
10117 }
10118
10119 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070010120 * Invalidate the whole view. If the view is visible,
10121 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10122 * the future. This must be called from a UI thread. To call from a non-UI thread,
10123 * call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010124 */
10125 public void invalidate() {
Chet Haaseed032702010-10-01 14:05:54 -070010126 invalidate(true);
10127 }
Joe Malin32736f02011-01-19 16:14:20 -080010128
Chet Haaseed032702010-10-01 14:05:54 -070010129 /**
10130 * This is where the invalidate() work actually happens. A full invalidate()
10131 * causes the drawing cache to be invalidated, but this function can be called with
10132 * invalidateCache set to false to skip that invalidation step for cases that do not
10133 * need it (for example, a component that remains at the same dimensions with the same
10134 * content).
10135 *
10136 * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10137 * well. This is usually true for a full invalidate, but may be set to false if the
10138 * View's contents or dimensions have not changed.
10139 */
Romain Guy849d0a32011-02-01 17:20:48 -080010140 void invalidate(boolean invalidateCache) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010141 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010142 return;
10143 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070010144 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10145 (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10146 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
Romain Guy0fd89bf2011-01-26 15:41:30 -080010147 mLastIsOpaque = isOpaque();
Dianne Hackborn4702a852012-08-17 15:18:29 -070010148 mPrivateFlags &= ~PFLAG_DRAWN;
10149 mPrivateFlags |= PFLAG_DIRTY;
Chet Haaseed032702010-10-01 14:05:54 -070010150 if (invalidateCache) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010151 mPrivateFlags |= PFLAG_INVALIDATED;
10152 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
Chet Haaseed032702010-10-01 14:05:54 -070010153 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010154 final AttachInfo ai = mAttachInfo;
Chet Haase70d4ba12010-10-06 09:46:45 -070010155 final ViewParent p = mParent;
Romain Guy7d7b5492011-01-24 16:33:45 -080010156 //noinspection PointlessBooleanExpression,ConstantConditions
10157 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10158 if (p != null && ai != null && ai.mHardwareAccelerated) {
10159 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010160 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010161 p.invalidateChild(this, null);
10162 return;
10163 }
Chet Haasef2f7d8f2010-12-03 14:08:14 -080010164 }
Michael Jurkaebefea42010-11-15 16:04:01 -080010165
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010166 if (p != null && ai != null) {
10167 final Rect r = ai.mTmpInvalRect;
10168 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10169 // Don't call invalidate -- we don't want to internally scroll
10170 // our own bounds
10171 p.invalidateChild(this, r);
10172 }
10173 }
10174 }
10175
10176 /**
Chet Haase9d1992d2012-03-13 11:03:25 -070010177 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10178 * set any flags or handle all of the cases handled by the default invalidation methods.
10179 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10180 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10181 * walk up the hierarchy, transforming the dirty rect as necessary.
10182 *
10183 * The method also handles normal invalidation logic if display list properties are not
10184 * being used in this view. The invalidateParent and forceRedraw flags are used by that
10185 * backup approach, to handle these cases used in the various property-setting methods.
10186 *
10187 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10188 * are not being used in this view
10189 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10190 * list properties are not being used in this view
10191 */
10192 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010193 if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
Chet Haase9d1992d2012-03-13 11:03:25 -070010194 if (invalidateParent) {
10195 invalidateParentCaches();
10196 }
10197 if (forceRedraw) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010198 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Chet Haase9d1992d2012-03-13 11:03:25 -070010199 }
10200 invalidate(false);
10201 } else {
10202 final AttachInfo ai = mAttachInfo;
10203 final ViewParent p = mParent;
10204 if (p != null && ai != null) {
10205 final Rect r = ai.mTmpInvalRect;
10206 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10207 if (mParent instanceof ViewGroup) {
10208 ((ViewGroup) mParent).invalidateChildFast(this, r);
10209 } else {
10210 mParent.invalidateChild(this, r);
10211 }
10212 }
10213 }
10214 }
10215
10216 /**
10217 * Utility method to transform a given Rect by the current matrix of this view.
10218 */
10219 void transformRect(final Rect rect) {
10220 if (!getMatrix().isIdentity()) {
10221 RectF boundingRect = mAttachInfo.mTmpTransformRect;
10222 boundingRect.set(rect);
10223 getMatrix().mapRect(boundingRect);
10224 rect.set((int) (boundingRect.left - 0.5f),
10225 (int) (boundingRect.top - 0.5f),
10226 (int) (boundingRect.right + 0.5f),
10227 (int) (boundingRect.bottom + 0.5f));
10228 }
10229 }
10230
10231 /**
Romain Guy0fd89bf2011-01-26 15:41:30 -080010232 * Used to indicate that the parent of this view should clear its caches. This functionality
Chet Haasedaf98e92011-01-10 14:10:36 -080010233 * is used to force the parent to rebuild its display list (when hardware-accelerated),
10234 * which is necessary when various parent-managed properties of the view change, such as
Romain Guy0fd89bf2011-01-26 15:41:30 -080010235 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10236 * clears the parent caches and does not causes an invalidate event.
Chet Haasedaf98e92011-01-10 14:10:36 -080010237 *
10238 * @hide
10239 */
Romain Guy0fd89bf2011-01-26 15:41:30 -080010240 protected void invalidateParentCaches() {
10241 if (mParent instanceof View) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010242 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
Romain Guy0fd89bf2011-01-26 15:41:30 -080010243 }
10244 }
Joe Malin32736f02011-01-19 16:14:20 -080010245
Romain Guy0fd89bf2011-01-26 15:41:30 -080010246 /**
10247 * Used to indicate that the parent of this view should be invalidated. This functionality
10248 * is used to force the parent to rebuild its display list (when hardware-accelerated),
10249 * which is necessary when various parent-managed properties of the view change, such as
10250 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10251 * an invalidation event to the parent.
10252 *
10253 * @hide
10254 */
10255 protected void invalidateParentIfNeeded() {
Chet Haasedaf98e92011-01-10 14:10:36 -080010256 if (isHardwareAccelerated() && mParent instanceof View) {
Romain Guy0fd89bf2011-01-26 15:41:30 -080010257 ((View) mParent).invalidate(true);
Chet Haasedaf98e92011-01-10 14:10:36 -080010258 }
10259 }
10260
10261 /**
Romain Guy24443ea2009-05-11 11:56:30 -070010262 * Indicates whether this View is opaque. An opaque View guarantees that it will
10263 * draw all the pixels overlapping its bounds using a fully opaque color.
10264 *
10265 * Subclasses of View should override this method whenever possible to indicate
10266 * whether an instance is opaque. Opaque Views are treated in a special way by
10267 * the View hierarchy, possibly allowing it to perform optimizations during
10268 * invalidate/draw passes.
Romain Guy8506ab42009-06-11 17:35:47 -070010269 *
Romain Guy24443ea2009-05-11 11:56:30 -070010270 * @return True if this View is guaranteed to be fully opaque, false otherwise.
Romain Guy24443ea2009-05-11 11:56:30 -070010271 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070010272 @ViewDebug.ExportedProperty(category = "drawing")
Romain Guy24443ea2009-05-11 11:56:30 -070010273 public boolean isOpaque() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010274 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
Romain Guyf8773082012-07-12 18:01:00 -070010275 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
Romain Guy8f1344f52009-05-15 16:03:59 -070010276 }
10277
Adam Powell20232d02010-12-08 21:08:53 -080010278 /**
10279 * @hide
10280 */
10281 protected void computeOpaqueFlags() {
Romain Guy8f1344f52009-05-15 16:03:59 -070010282 // Opaque if:
10283 // - Has a background
10284 // - Background is opaque
10285 // - Doesn't have scrollbars or scrollbars are inside overlay
10286
Philip Milne6c8ea062012-04-03 17:38:43 -070010287 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010288 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
Romain Guy8f1344f52009-05-15 16:03:59 -070010289 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010290 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
Romain Guy8f1344f52009-05-15 16:03:59 -070010291 }
10292
10293 final int flags = mViewFlags;
10294 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10295 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010296 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
Romain Guy8f1344f52009-05-15 16:03:59 -070010297 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010298 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
Romain Guy8f1344f52009-05-15 16:03:59 -070010299 }
10300 }
10301
10302 /**
10303 * @hide
10304 */
10305 protected boolean hasOpaqueScrollbars() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010306 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
Romain Guy24443ea2009-05-11 11:56:30 -070010307 }
10308
10309 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010310 * @return A handler associated with the thread running the View. This
10311 * handler can be used to pump events in the UI events queue.
10312 */
10313 public Handler getHandler() {
10314 if (mAttachInfo != null) {
10315 return mAttachInfo.mHandler;
10316 }
10317 return null;
10318 }
10319
10320 /**
Jeff Browna175a5b2012-02-15 19:18:31 -080010321 * Gets the view root associated with the View.
10322 * @return The view root, or null if none.
10323 * @hide
10324 */
10325 public ViewRootImpl getViewRootImpl() {
10326 if (mAttachInfo != null) {
10327 return mAttachInfo.mViewRootImpl;
10328 }
10329 return null;
10330 }
10331
10332 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010333 * <p>Causes the Runnable to be added to the message queue.
10334 * The runnable will be run on the user interface thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010335 *
Romain Guye63a4f32011-08-11 11:33:31 -070010336 * <p>This method can be invoked from outside of the UI thread
10337 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010338 *
10339 * @param action The Runnable that will be executed.
10340 *
10341 * @return Returns true if the Runnable was successfully placed in to the
10342 * message queue. Returns false on failure, usually because the
10343 * looper processing the message queue is exiting.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010344 *
10345 * @see #postDelayed
10346 * @see #removeCallbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010347 */
10348 public boolean post(Runnable action) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010349 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010350 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010351 return attachInfo.mHandler.post(action);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010352 }
Jeff Browna175a5b2012-02-15 19:18:31 -080010353 // Assume that post will succeed later
10354 ViewRootImpl.getRunQueue().post(action);
10355 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010356 }
10357
10358 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010359 * <p>Causes the Runnable to be added to the message queue, to be run
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010360 * after the specified amount of time elapses.
Romain Guye63a4f32011-08-11 11:33:31 -070010361 * The runnable will be run on the user interface thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010362 *
Romain Guye63a4f32011-08-11 11:33:31 -070010363 * <p>This method can be invoked from outside of the UI thread
10364 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010365 *
10366 * @param action The Runnable that will be executed.
10367 * @param delayMillis The delay (in milliseconds) until the Runnable
10368 * will be executed.
10369 *
10370 * @return true if the Runnable was successfully placed in to the
10371 * message queue. Returns false on failure, usually because the
10372 * looper processing the message queue is exiting. Note that a
10373 * result of true does not mean the Runnable will be processed --
10374 * if the looper is quit before the delivery time of the message
10375 * occurs then the message will be dropped.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010376 *
10377 * @see #post
10378 * @see #removeCallbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010379 */
10380 public boolean postDelayed(Runnable action, long delayMillis) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010381 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010382 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010383 return attachInfo.mHandler.postDelayed(action, delayMillis);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010384 }
Jeff Browna175a5b2012-02-15 19:18:31 -080010385 // Assume that post will succeed later
10386 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10387 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010388 }
10389
10390 /**
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010391 * <p>Causes the Runnable to execute on the next animation time step.
10392 * The runnable will be run on the user interface thread.</p>
10393 *
10394 * <p>This method can be invoked from outside of the UI thread
10395 * only when this View is attached to a window.</p>
10396 *
10397 * @param action The Runnable that will be executed.
10398 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010399 * @see #postOnAnimationDelayed
10400 * @see #removeCallbacks
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010401 */
10402 public void postOnAnimation(Runnable action) {
10403 final AttachInfo attachInfo = mAttachInfo;
10404 if (attachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010405 attachInfo.mViewRootImpl.mChoreographer.postCallback(
10406 Choreographer.CALLBACK_ANIMATION, action, null);
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010407 } else {
10408 // Assume that post will succeed later
10409 ViewRootImpl.getRunQueue().post(action);
10410 }
10411 }
10412
10413 /**
10414 * <p>Causes the Runnable to execute on the next animation time step,
10415 * after the specified amount of time elapses.
10416 * The runnable will be run on the user interface thread.</p>
10417 *
10418 * <p>This method can be invoked from outside of the UI thread
10419 * only when this View is attached to a window.</p>
10420 *
10421 * @param action The Runnable that will be executed.
10422 * @param delayMillis The delay (in milliseconds) until the Runnable
10423 * will be executed.
10424 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010425 * @see #postOnAnimation
10426 * @see #removeCallbacks
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010427 */
10428 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10429 final AttachInfo attachInfo = mAttachInfo;
10430 if (attachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010431 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10432 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010433 } else {
10434 // Assume that post will succeed later
10435 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10436 }
10437 }
10438
10439 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010440 * <p>Removes the specified Runnable from the message queue.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010441 *
Romain Guye63a4f32011-08-11 11:33:31 -070010442 * <p>This method can be invoked from outside of the UI thread
10443 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010444 *
10445 * @param action The Runnable to remove from the message handling queue
10446 *
10447 * @return true if this view could ask the Handler to remove the Runnable,
10448 * false otherwise. When the returned value is true, the Runnable
10449 * may or may not have been actually removed from the message queue
10450 * (for instance, if the Runnable was not in the queue already.)
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010451 *
10452 * @see #post
10453 * @see #postDelayed
10454 * @see #postOnAnimation
10455 * @see #postOnAnimationDelayed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010456 */
10457 public boolean removeCallbacks(Runnable action) {
Jeff Brown43ea54b2012-03-09 14:37:48 -080010458 if (action != null) {
10459 final AttachInfo attachInfo = mAttachInfo;
10460 if (attachInfo != null) {
10461 attachInfo.mHandler.removeCallbacks(action);
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010462 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10463 Choreographer.CALLBACK_ANIMATION, action, null);
Jeff Brown43ea54b2012-03-09 14:37:48 -080010464 } else {
10465 // Assume that post will succeed later
10466 ViewRootImpl.getRunQueue().removeCallbacks(action);
10467 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010469 return true;
10470 }
10471
10472 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010473 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10474 * Use this to invalidate the View from a non-UI thread.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010475 *
Romain Guye63a4f32011-08-11 11:33:31 -070010476 * <p>This method can be invoked from outside of the UI thread
10477 * only when this View is attached to a window.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010478 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 * @see #invalidate()
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010480 * @see #postInvalidateDelayed(long)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010481 */
10482 public void postInvalidate() {
10483 postInvalidateDelayed(0);
10484 }
10485
10486 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010487 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10488 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010489 *
Romain Guye63a4f32011-08-11 11:33:31 -070010490 * <p>This method can be invoked from outside of the UI thread
10491 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 *
10493 * @param left The left coordinate of the rectangle to invalidate.
10494 * @param top The top coordinate of the rectangle to invalidate.
10495 * @param right The right coordinate of the rectangle to invalidate.
10496 * @param bottom The bottom coordinate of the rectangle to invalidate.
10497 *
10498 * @see #invalidate(int, int, int, int)
10499 * @see #invalidate(Rect)
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010500 * @see #postInvalidateDelayed(long, int, int, int, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 */
10502 public void postInvalidate(int left, int top, int right, int bottom) {
10503 postInvalidateDelayed(0, left, top, right, bottom);
10504 }
10505
10506 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010507 * <p>Cause an invalidate to happen on a subsequent cycle through the event
10508 * loop. Waits for the specified amount of time.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010509 *
Romain Guye63a4f32011-08-11 11:33:31 -070010510 * <p>This method can be invoked from outside of the UI thread
10511 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 *
10513 * @param delayMilliseconds the duration in milliseconds to delay the
10514 * invalidation by
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010515 *
10516 * @see #invalidate()
10517 * @see #postInvalidate()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010518 */
10519 public void postInvalidateDelayed(long delayMilliseconds) {
10520 // We try only with the AttachInfo because there's no point in invalidating
10521 // if we are not attached to our window
Jeff Browna175a5b2012-02-15 19:18:31 -080010522 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010523 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010524 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010525 }
10526 }
10527
10528 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010529 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10530 * through the event loop. Waits for the specified amount of time.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010531 *
Romain Guye63a4f32011-08-11 11:33:31 -070010532 * <p>This method can be invoked from outside of the UI thread
10533 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010534 *
10535 * @param delayMilliseconds the duration in milliseconds to delay the
10536 * invalidation by
10537 * @param left The left coordinate of the rectangle to invalidate.
10538 * @param top The top coordinate of the rectangle to invalidate.
10539 * @param right The right coordinate of the rectangle to invalidate.
10540 * @param bottom The bottom coordinate of the rectangle to invalidate.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010541 *
10542 * @see #invalidate(int, int, int, int)
10543 * @see #invalidate(Rect)
10544 * @see #postInvalidate(int, int, int, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010545 */
10546 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10547 int right, int bottom) {
10548
10549 // We try only with the AttachInfo because there's no point in invalidating
10550 // if we are not attached to our window
Jeff Browna175a5b2012-02-15 19:18:31 -080010551 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010552 if (attachInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010553 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10554 info.target = this;
10555 info.left = left;
10556 info.top = top;
10557 info.right = right;
10558 info.bottom = bottom;
10559
Jeff Browna175a5b2012-02-15 19:18:31 -080010560 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010561 }
10562 }
10563
10564 /**
Jeff Brown6cb7b462012-03-05 13:21:17 -080010565 * <p>Cause an invalidate to happen on the next animation time step, typically the
10566 * next display frame.</p>
10567 *
10568 * <p>This method can be invoked from outside of the UI thread
10569 * only when this View is attached to a window.</p>
10570 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010571 * @see #invalidate()
Jeff Brown6cb7b462012-03-05 13:21:17 -080010572 */
10573 public void postInvalidateOnAnimation() {
10574 // We try only with the AttachInfo because there's no point in invalidating
10575 // if we are not attached to our window
10576 final AttachInfo attachInfo = mAttachInfo;
10577 if (attachInfo != null) {
10578 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10579 }
10580 }
10581
10582 /**
10583 * <p>Cause an invalidate of the specified area to happen on the next animation
10584 * time step, typically the next display frame.</p>
10585 *
10586 * <p>This method can be invoked from outside of the UI thread
10587 * only when this View is attached to a window.</p>
10588 *
10589 * @param left The left coordinate of the rectangle to invalidate.
10590 * @param top The top coordinate of the rectangle to invalidate.
10591 * @param right The right coordinate of the rectangle to invalidate.
10592 * @param bottom The bottom coordinate of the rectangle to invalidate.
10593 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010594 * @see #invalidate(int, int, int, int)
10595 * @see #invalidate(Rect)
Jeff Brown6cb7b462012-03-05 13:21:17 -080010596 */
10597 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10598 // We try only with the AttachInfo because there's no point in invalidating
10599 // if we are not attached to our window
10600 final AttachInfo attachInfo = mAttachInfo;
10601 if (attachInfo != null) {
10602 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10603 info.target = this;
10604 info.left = left;
10605 info.top = top;
10606 info.right = right;
10607 info.bottom = bottom;
10608
10609 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10610 }
10611 }
10612
10613 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -070010614 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10615 * This event is sent at most once every
10616 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10617 */
10618 private void postSendViewScrolledAccessibilityEventCallback() {
10619 if (mSendViewScrolledAccessibilityEvent == null) {
10620 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10621 }
10622 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10623 mSendViewScrolledAccessibilityEvent.mIsPending = true;
10624 postDelayed(mSendViewScrolledAccessibilityEvent,
10625 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10626 }
10627 }
10628
10629 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010630 * Called by a parent to request that a child update its values for mScrollX
10631 * and mScrollY if necessary. This will typically be done if the child is
10632 * animating a scroll using a {@link android.widget.Scroller Scroller}
10633 * object.
10634 */
10635 public void computeScroll() {
10636 }
10637
10638 /**
10639 * <p>Indicate whether the horizontal edges are faded when the view is
10640 * scrolled horizontally.</p>
10641 *
10642 * @return true if the horizontal edges should are faded on scroll, false
10643 * otherwise
10644 *
10645 * @see #setHorizontalFadingEdgeEnabled(boolean)
Philip Milne6c8ea062012-04-03 17:38:43 -070010646 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010647 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010648 */
10649 public boolean isHorizontalFadingEdgeEnabled() {
10650 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
10651 }
10652
10653 /**
10654 * <p>Define whether the horizontal edges should be faded when this view
10655 * is scrolled horizontally.</p>
10656 *
10657 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
10658 * be faded when the view is scrolled
10659 * horizontally
10660 *
10661 * @see #isHorizontalFadingEdgeEnabled()
Philip Milne6c8ea062012-04-03 17:38:43 -070010662 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010663 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010664 */
10665 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
10666 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
10667 if (horizontalFadingEdgeEnabled) {
10668 initScrollCache();
10669 }
10670
10671 mViewFlags ^= FADING_EDGE_HORIZONTAL;
10672 }
10673 }
10674
10675 /**
10676 * <p>Indicate whether the vertical edges are faded when the view is
10677 * scrolled horizontally.</p>
10678 *
10679 * @return true if the vertical edges should are faded on scroll, false
10680 * otherwise
10681 *
10682 * @see #setVerticalFadingEdgeEnabled(boolean)
Philip Milne6c8ea062012-04-03 17:38:43 -070010683 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010684 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010685 */
10686 public boolean isVerticalFadingEdgeEnabled() {
10687 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
10688 }
10689
10690 /**
10691 * <p>Define whether the vertical edges should be faded when this view
10692 * is scrolled vertically.</p>
10693 *
10694 * @param verticalFadingEdgeEnabled true if the vertical edges should
10695 * be faded when the view is scrolled
10696 * vertically
10697 *
10698 * @see #isVerticalFadingEdgeEnabled()
Philip Milne6c8ea062012-04-03 17:38:43 -070010699 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010700 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010701 */
10702 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
10703 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
10704 if (verticalFadingEdgeEnabled) {
10705 initScrollCache();
10706 }
10707
10708 mViewFlags ^= FADING_EDGE_VERTICAL;
10709 }
10710 }
10711
10712 /**
10713 * Returns the strength, or intensity, of the top faded edge. The strength is
10714 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10715 * returns 0.0 or 1.0 but no value in between.
10716 *
10717 * Subclasses should override this method to provide a smoother fade transition
10718 * when scrolling occurs.
10719 *
10720 * @return the intensity of the top fade as a float between 0.0f and 1.0f
10721 */
10722 protected float getTopFadingEdgeStrength() {
10723 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
10724 }
10725
10726 /**
10727 * Returns the strength, or intensity, of the bottom faded edge. The strength is
10728 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10729 * returns 0.0 or 1.0 but no value in between.
10730 *
10731 * Subclasses should override this method to provide a smoother fade transition
10732 * when scrolling occurs.
10733 *
10734 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
10735 */
10736 protected float getBottomFadingEdgeStrength() {
10737 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
10738 computeVerticalScrollRange() ? 1.0f : 0.0f;
10739 }
10740
10741 /**
10742 * Returns the strength, or intensity, of the left faded edge. The strength is
10743 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10744 * returns 0.0 or 1.0 but no value in between.
10745 *
10746 * Subclasses should override this method to provide a smoother fade transition
10747 * when scrolling occurs.
10748 *
10749 * @return the intensity of the left fade as a float between 0.0f and 1.0f
10750 */
10751 protected float getLeftFadingEdgeStrength() {
10752 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
10753 }
10754
10755 /**
10756 * Returns the strength, or intensity, of the right faded edge. The strength is
10757 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10758 * returns 0.0 or 1.0 but no value in between.
10759 *
10760 * Subclasses should override this method to provide a smoother fade transition
10761 * when scrolling occurs.
10762 *
10763 * @return the intensity of the right fade as a float between 0.0f and 1.0f
10764 */
10765 protected float getRightFadingEdgeStrength() {
10766 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
10767 computeHorizontalScrollRange() ? 1.0f : 0.0f;
10768 }
10769
10770 /**
10771 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
10772 * scrollbar is not drawn by default.</p>
10773 *
10774 * @return true if the horizontal scrollbar should be painted, false
10775 * otherwise
10776 *
10777 * @see #setHorizontalScrollBarEnabled(boolean)
10778 */
10779 public boolean isHorizontalScrollBarEnabled() {
10780 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
10781 }
10782
10783 /**
10784 * <p>Define whether the horizontal scrollbar should be drawn or not. The
10785 * scrollbar is not drawn by default.</p>
10786 *
10787 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
10788 * be painted
10789 *
10790 * @see #isHorizontalScrollBarEnabled()
10791 */
10792 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
10793 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
10794 mViewFlags ^= SCROLLBARS_HORIZONTAL;
Romain Guy8f1344f52009-05-15 16:03:59 -070010795 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010796 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010797 }
10798 }
10799
10800 /**
10801 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
10802 * scrollbar is not drawn by default.</p>
10803 *
10804 * @return true if the vertical scrollbar should be painted, false
10805 * otherwise
10806 *
10807 * @see #setVerticalScrollBarEnabled(boolean)
10808 */
10809 public boolean isVerticalScrollBarEnabled() {
10810 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
10811 }
10812
10813 /**
10814 * <p>Define whether the vertical scrollbar should be drawn or not. The
10815 * scrollbar is not drawn by default.</p>
10816 *
10817 * @param verticalScrollBarEnabled true if the vertical scrollbar should
10818 * be painted
10819 *
10820 * @see #isVerticalScrollBarEnabled()
10821 */
10822 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
10823 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
10824 mViewFlags ^= SCROLLBARS_VERTICAL;
Romain Guy8f1344f52009-05-15 16:03:59 -070010825 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010826 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010827 }
10828 }
10829
Adam Powell20232d02010-12-08 21:08:53 -080010830 /**
10831 * @hide
10832 */
10833 protected void recomputePadding() {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070010834 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010835 }
Joe Malin32736f02011-01-19 16:14:20 -080010836
Mike Cleronfe81d382009-09-28 14:22:16 -070010837 /**
10838 * Define whether scrollbars will fade when the view is not scrolling.
Joe Malin32736f02011-01-19 16:14:20 -080010839 *
Mike Cleronfe81d382009-09-28 14:22:16 -070010840 * @param fadeScrollbars wheter to enable fading
Joe Malin32736f02011-01-19 16:14:20 -080010841 *
Philip Milne6c8ea062012-04-03 17:38:43 -070010842 * @attr ref android.R.styleable#View_fadeScrollbars
Mike Cleronfe81d382009-09-28 14:22:16 -070010843 */
10844 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
10845 initScrollCache();
10846 final ScrollabilityCache scrollabilityCache = mScrollCache;
10847 scrollabilityCache.fadeScrollBars = fadeScrollbars;
Mike Cleron52f0a642009-09-28 18:21:37 -070010848 if (fadeScrollbars) {
10849 scrollabilityCache.state = ScrollabilityCache.OFF;
10850 } else {
Mike Cleronfe81d382009-09-28 14:22:16 -070010851 scrollabilityCache.state = ScrollabilityCache.ON;
10852 }
10853 }
Joe Malin32736f02011-01-19 16:14:20 -080010854
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010855 /**
Joe Malin32736f02011-01-19 16:14:20 -080010856 *
Mike Cleron52f0a642009-09-28 18:21:37 -070010857 * Returns true if scrollbars will fade when this view is not scrolling
Joe Malin32736f02011-01-19 16:14:20 -080010858 *
Mike Cleron52f0a642009-09-28 18:21:37 -070010859 * @return true if scrollbar fading is enabled
Philip Milne6c8ea062012-04-03 17:38:43 -070010860 *
10861 * @attr ref android.R.styleable#View_fadeScrollbars
Mike Cleron52f0a642009-09-28 18:21:37 -070010862 */
10863 public boolean isScrollbarFadingEnabled() {
Joe Malin32736f02011-01-19 16:14:20 -080010864 return mScrollCache != null && mScrollCache.fadeScrollBars;
Mike Cleron52f0a642009-09-28 18:21:37 -070010865 }
Joe Malin32736f02011-01-19 16:14:20 -080010866
Mike Cleron52f0a642009-09-28 18:21:37 -070010867 /**
Philip Milne6c8ea062012-04-03 17:38:43 -070010868 *
10869 * Returns the delay before scrollbars fade.
10870 *
10871 * @return the delay before scrollbars fade
10872 *
10873 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10874 */
10875 public int getScrollBarDefaultDelayBeforeFade() {
10876 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
10877 mScrollCache.scrollBarDefaultDelayBeforeFade;
10878 }
10879
10880 /**
10881 * Define the delay before scrollbars fade.
10882 *
10883 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
10884 *
10885 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10886 */
10887 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
10888 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
10889 }
10890
10891 /**
10892 *
10893 * Returns the scrollbar fade duration.
10894 *
10895 * @return the scrollbar fade duration
10896 *
10897 * @attr ref android.R.styleable#View_scrollbarFadeDuration
10898 */
10899 public int getScrollBarFadeDuration() {
10900 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
10901 mScrollCache.scrollBarFadeDuration;
10902 }
10903
10904 /**
10905 * Define the scrollbar fade duration.
10906 *
10907 * @param scrollBarFadeDuration - the scrollbar fade duration
10908 *
10909 * @attr ref android.R.styleable#View_scrollbarFadeDuration
10910 */
10911 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
10912 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
10913 }
10914
10915 /**
10916 *
10917 * Returns the scrollbar size.
10918 *
10919 * @return the scrollbar size
10920 *
10921 * @attr ref android.R.styleable#View_scrollbarSize
10922 */
10923 public int getScrollBarSize() {
Romain Guyeb378892012-04-12 11:33:14 -070010924 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
Philip Milne6c8ea062012-04-03 17:38:43 -070010925 mScrollCache.scrollBarSize;
10926 }
10927
10928 /**
10929 * Define the scrollbar size.
10930 *
10931 * @param scrollBarSize - the scrollbar size
10932 *
10933 * @attr ref android.R.styleable#View_scrollbarSize
10934 */
10935 public void setScrollBarSize(int scrollBarSize) {
10936 getScrollCache().scrollBarSize = scrollBarSize;
10937 }
10938
10939 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010940 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
10941 * inset. When inset, they add to the padding of the view. And the scrollbars
10942 * can be drawn inside the padding area or on the edge of the view. For example,
10943 * if a view has a background drawable and you want to draw the scrollbars
10944 * inside the padding specified by the drawable, you can use
10945 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
10946 * appear at the edge of the view, ignoring the padding, then you can use
10947 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
10948 * @param style the style of the scrollbars. Should be one of
10949 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
10950 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
10951 * @see #SCROLLBARS_INSIDE_OVERLAY
10952 * @see #SCROLLBARS_INSIDE_INSET
10953 * @see #SCROLLBARS_OUTSIDE_OVERLAY
10954 * @see #SCROLLBARS_OUTSIDE_INSET
Philip Milne6c8ea062012-04-03 17:38:43 -070010955 *
10956 * @attr ref android.R.styleable#View_scrollbarStyle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010957 */
10958 public void setScrollBarStyle(int style) {
10959 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
10960 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
Romain Guy8f1344f52009-05-15 16:03:59 -070010961 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010962 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010963 }
10964 }
10965
10966 /**
10967 * <p>Returns the current scrollbar style.</p>
10968 * @return the current scrollbar style
10969 * @see #SCROLLBARS_INSIDE_OVERLAY
10970 * @see #SCROLLBARS_INSIDE_INSET
10971 * @see #SCROLLBARS_OUTSIDE_OVERLAY
10972 * @see #SCROLLBARS_OUTSIDE_INSET
Philip Milne6c8ea062012-04-03 17:38:43 -070010973 *
10974 * @attr ref android.R.styleable#View_scrollbarStyle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010975 */
Jeff Sharkey010d7e52011-08-08 21:05:02 -070010976 @ViewDebug.ExportedProperty(mapping = {
10977 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
10978 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
10979 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
10980 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
10981 })
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010982 public int getScrollBarStyle() {
10983 return mViewFlags & SCROLLBARS_STYLE_MASK;
10984 }
10985
10986 /**
10987 * <p>Compute the horizontal range that the horizontal scrollbar
10988 * represents.</p>
10989 *
10990 * <p>The range is expressed in arbitrary units that must be the same as the
10991 * units used by {@link #computeHorizontalScrollExtent()} and
10992 * {@link #computeHorizontalScrollOffset()}.</p>
10993 *
10994 * <p>The default range is the drawing width of this view.</p>
10995 *
10996 * @return the total horizontal range represented by the horizontal
10997 * scrollbar
10998 *
10999 * @see #computeHorizontalScrollExtent()
11000 * @see #computeHorizontalScrollOffset()
11001 * @see android.widget.ScrollBarDrawable
11002 */
11003 protected int computeHorizontalScrollRange() {
11004 return getWidth();
11005 }
11006
11007 /**
11008 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
11009 * within the horizontal range. This value is used to compute the position
11010 * of the thumb within the scrollbar's track.</p>
11011 *
11012 * <p>The range is expressed in arbitrary units that must be the same as the
11013 * units used by {@link #computeHorizontalScrollRange()} and
11014 * {@link #computeHorizontalScrollExtent()}.</p>
11015 *
11016 * <p>The default offset is the scroll offset of this view.</p>
11017 *
11018 * @return the horizontal offset of the scrollbar's thumb
11019 *
11020 * @see #computeHorizontalScrollRange()
11021 * @see #computeHorizontalScrollExtent()
11022 * @see android.widget.ScrollBarDrawable
11023 */
11024 protected int computeHorizontalScrollOffset() {
11025 return mScrollX;
11026 }
11027
11028 /**
11029 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
11030 * within the horizontal range. This value is used to compute the length
11031 * of the thumb within the scrollbar's track.</p>
11032 *
11033 * <p>The range is expressed in arbitrary units that must be the same as the
11034 * units used by {@link #computeHorizontalScrollRange()} and
11035 * {@link #computeHorizontalScrollOffset()}.</p>
11036 *
11037 * <p>The default extent is the drawing width of this view.</p>
11038 *
11039 * @return the horizontal extent of the scrollbar's thumb
11040 *
11041 * @see #computeHorizontalScrollRange()
11042 * @see #computeHorizontalScrollOffset()
11043 * @see android.widget.ScrollBarDrawable
11044 */
11045 protected int computeHorizontalScrollExtent() {
11046 return getWidth();
11047 }
11048
11049 /**
11050 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
11051 *
11052 * <p>The range is expressed in arbitrary units that must be the same as the
11053 * units used by {@link #computeVerticalScrollExtent()} and
11054 * {@link #computeVerticalScrollOffset()}.</p>
11055 *
11056 * @return the total vertical range represented by the vertical scrollbar
11057 *
11058 * <p>The default range is the drawing height of this view.</p>
11059 *
11060 * @see #computeVerticalScrollExtent()
11061 * @see #computeVerticalScrollOffset()
11062 * @see android.widget.ScrollBarDrawable
11063 */
11064 protected int computeVerticalScrollRange() {
11065 return getHeight();
11066 }
11067
11068 /**
11069 * <p>Compute the vertical offset of the vertical scrollbar's thumb
11070 * within the horizontal range. This value is used to compute the position
11071 * of the thumb within the scrollbar's track.</p>
11072 *
11073 * <p>The range is expressed in arbitrary units that must be the same as the
11074 * units used by {@link #computeVerticalScrollRange()} and
11075 * {@link #computeVerticalScrollExtent()}.</p>
11076 *
11077 * <p>The default offset is the scroll offset of this view.</p>
11078 *
11079 * @return the vertical offset of the scrollbar's thumb
11080 *
11081 * @see #computeVerticalScrollRange()
11082 * @see #computeVerticalScrollExtent()
11083 * @see android.widget.ScrollBarDrawable
11084 */
11085 protected int computeVerticalScrollOffset() {
11086 return mScrollY;
11087 }
11088
11089 /**
11090 * <p>Compute the vertical extent of the horizontal scrollbar's thumb
11091 * within the vertical range. This value is used to compute the length
11092 * of the thumb within the scrollbar's track.</p>
11093 *
11094 * <p>The range is expressed in arbitrary units that must be the same as the
Gilles Debunne52964242010-02-24 11:05:19 -080011095 * units used by {@link #computeVerticalScrollRange()} and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011096 * {@link #computeVerticalScrollOffset()}.</p>
11097 *
11098 * <p>The default extent is the drawing height of this view.</p>
11099 *
11100 * @return the vertical extent of the scrollbar's thumb
11101 *
11102 * @see #computeVerticalScrollRange()
11103 * @see #computeVerticalScrollOffset()
11104 * @see android.widget.ScrollBarDrawable
11105 */
11106 protected int computeVerticalScrollExtent() {
11107 return getHeight();
11108 }
11109
11110 /**
Adam Powell69159442011-06-13 17:53:06 -070011111 * Check if this view can be scrolled horizontally in a certain direction.
11112 *
11113 * @param direction Negative to check scrolling left, positive to check scrolling right.
11114 * @return true if this view can be scrolled in the specified direction, false otherwise.
11115 */
11116 public boolean canScrollHorizontally(int direction) {
11117 final int offset = computeHorizontalScrollOffset();
11118 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11119 if (range == 0) return false;
11120 if (direction < 0) {
11121 return offset > 0;
11122 } else {
11123 return offset < range - 1;
11124 }
11125 }
11126
11127 /**
11128 * Check if this view can be scrolled vertically in a certain direction.
11129 *
11130 * @param direction Negative to check scrolling up, positive to check scrolling down.
11131 * @return true if this view can be scrolled in the specified direction, false otherwise.
11132 */
11133 public boolean canScrollVertically(int direction) {
11134 final int offset = computeVerticalScrollOffset();
11135 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11136 if (range == 0) return false;
11137 if (direction < 0) {
11138 return offset > 0;
11139 } else {
11140 return offset < range - 1;
11141 }
11142 }
11143
11144 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011145 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11146 * scrollbars are painted only if they have been awakened first.</p>
11147 *
11148 * @param canvas the canvas on which to draw the scrollbars
Joe Malin32736f02011-01-19 16:14:20 -080011149 *
Mike Cleronf116bf82009-09-27 19:14:12 -070011150 * @see #awakenScrollBars(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011151 */
Romain Guy1d5b3a62009-11-05 18:44:12 -080011152 protected final void onDrawScrollBars(Canvas canvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011153 // scrollbars are drawn only when the animation is running
11154 final ScrollabilityCache cache = mScrollCache;
11155 if (cache != null) {
Joe Malin32736f02011-01-19 16:14:20 -080011156
Mike Cleronf116bf82009-09-27 19:14:12 -070011157 int state = cache.state;
Joe Malin32736f02011-01-19 16:14:20 -080011158
Mike Cleronf116bf82009-09-27 19:14:12 -070011159 if (state == ScrollabilityCache.OFF) {
11160 return;
11161 }
Joe Malin32736f02011-01-19 16:14:20 -080011162
Mike Cleronf116bf82009-09-27 19:14:12 -070011163 boolean invalidate = false;
Joe Malin32736f02011-01-19 16:14:20 -080011164
Mike Cleronf116bf82009-09-27 19:14:12 -070011165 if (state == ScrollabilityCache.FADING) {
11166 // We're fading -- get our fade interpolation
11167 if (cache.interpolatorValues == null) {
11168 cache.interpolatorValues = new float[1];
11169 }
Joe Malin32736f02011-01-19 16:14:20 -080011170
Mike Cleronf116bf82009-09-27 19:14:12 -070011171 float[] values = cache.interpolatorValues;
Joe Malin32736f02011-01-19 16:14:20 -080011172
Mike Cleronf116bf82009-09-27 19:14:12 -070011173 // Stops the animation if we're done
11174 if (cache.scrollBarInterpolator.timeToValues(values) ==
11175 Interpolator.Result.FREEZE_END) {
11176 cache.state = ScrollabilityCache.OFF;
11177 } else {
11178 cache.scrollBar.setAlpha(Math.round(values[0]));
11179 }
Joe Malin32736f02011-01-19 16:14:20 -080011180
11181 // This will make the scroll bars inval themselves after
Mike Cleronf116bf82009-09-27 19:14:12 -070011182 // drawing. We only want this when we're fading so that
11183 // we prevent excessive redraws
11184 invalidate = true;
11185 } else {
11186 // We're just on -- but we may have been fading before so
11187 // reset alpha
11188 cache.scrollBar.setAlpha(255);
11189 }
11190
Joe Malin32736f02011-01-19 16:14:20 -080011191
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011192 final int viewFlags = mViewFlags;
11193
11194 final boolean drawHorizontalScrollBar =
11195 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11196 final boolean drawVerticalScrollBar =
11197 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11198 && !isVerticalScrollBarHidden();
11199
11200 if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11201 final int width = mRight - mLeft;
11202 final int height = mBottom - mTop;
11203
11204 final ScrollBarDrawable scrollBar = cache.scrollBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011205
Mike Reede8853fc2009-09-04 14:01:48 -040011206 final int scrollX = mScrollX;
11207 final int scrollY = mScrollY;
11208 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11209
Mike Cleronf116bf82009-09-27 19:14:12 -070011210 int left, top, right, bottom;
Joe Malin32736f02011-01-19 16:14:20 -080011211
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011212 if (drawHorizontalScrollBar) {
Adam Powell3ba67742011-01-27 14:16:55 -080011213 int size = scrollBar.getSize(false);
11214 if (size <= 0) {
11215 size = cache.scrollBarSize;
11216 }
11217
Mike Cleronf116bf82009-09-27 19:14:12 -070011218 scrollBar.setParameters(computeHorizontalScrollRange(),
Mike Reede8853fc2009-09-04 14:01:48 -040011219 computeHorizontalScrollOffset(),
11220 computeHorizontalScrollExtent(), false);
Mike Reede8853fc2009-09-04 14:01:48 -040011221 final int verticalScrollBarGap = drawVerticalScrollBar ?
Mike Cleronf116bf82009-09-27 19:14:12 -070011222 getVerticalScrollbarWidth() : 0;
Joe Malin32736f02011-01-19 16:14:20 -080011223 top = scrollY + height - size - (mUserPaddingBottom & inside);
Mike Cleronf116bf82009-09-27 19:14:12 -070011224 left = scrollX + (mPaddingLeft & inside);
11225 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11226 bottom = top + size;
11227 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11228 if (invalidate) {
11229 invalidate(left, top, right, bottom);
11230 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011231 }
11232
11233 if (drawVerticalScrollBar) {
Adam Powell3ba67742011-01-27 14:16:55 -080011234 int size = scrollBar.getSize(true);
11235 if (size <= 0) {
11236 size = cache.scrollBarSize;
11237 }
11238
Mike Reede8853fc2009-09-04 14:01:48 -040011239 scrollBar.setParameters(computeVerticalScrollRange(),
11240 computeVerticalScrollOffset(),
11241 computeVerticalScrollExtent(), true);
Fabrice Di Meglioc91b6ca2012-06-22 14:51:15 -070011242 int verticalScrollbarPosition = mVerticalScrollbarPosition;
11243 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11244 verticalScrollbarPosition = isLayoutRtl() ?
11245 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11246 }
11247 switch (verticalScrollbarPosition) {
Adam Powell20232d02010-12-08 21:08:53 -080011248 default:
Adam Powell20232d02010-12-08 21:08:53 -080011249 case SCROLLBAR_POSITION_RIGHT:
11250 left = scrollX + width - size - (mUserPaddingRight & inside);
11251 break;
11252 case SCROLLBAR_POSITION_LEFT:
11253 left = scrollX + (mUserPaddingLeft & inside);
11254 break;
11255 }
Mike Cleronf116bf82009-09-27 19:14:12 -070011256 top = scrollY + (mPaddingTop & inside);
11257 right = left + size;
11258 bottom = scrollY + height - (mUserPaddingBottom & inside);
11259 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11260 if (invalidate) {
11261 invalidate(left, top, right, bottom);
11262 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011263 }
11264 }
11265 }
11266 }
Romain Guy8506ab42009-06-11 17:35:47 -070011267
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011268 /**
Romain Guy8506ab42009-06-11 17:35:47 -070011269 * Override this if the vertical scrollbar needs to be hidden in a subclass, like when
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011270 * FastScroller is visible.
11271 * @return whether to temporarily hide the vertical scrollbar
11272 * @hide
11273 */
11274 protected boolean isVerticalScrollBarHidden() {
11275 return false;
11276 }
11277
11278 /**
11279 * <p>Draw the horizontal scrollbar if
11280 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11281 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011282 * @param canvas the canvas on which to draw the scrollbar
11283 * @param scrollBar the scrollbar's drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011284 *
11285 * @see #isHorizontalScrollBarEnabled()
11286 * @see #computeHorizontalScrollRange()
11287 * @see #computeHorizontalScrollExtent()
11288 * @see #computeHorizontalScrollOffset()
11289 * @see android.widget.ScrollBarDrawable
Mike Cleronf116bf82009-09-27 19:14:12 -070011290 * @hide
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011291 */
Romain Guy8fb95422010-08-17 18:38:51 -070011292 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11293 int l, int t, int r, int b) {
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011294 scrollBar.setBounds(l, t, r, b);
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011295 scrollBar.draw(canvas);
11296 }
Mike Reede8853fc2009-09-04 14:01:48 -040011297
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011298 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011299 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11300 * returns true.</p>
11301 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011302 * @param canvas the canvas on which to draw the scrollbar
11303 * @param scrollBar the scrollbar's drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011304 *
11305 * @see #isVerticalScrollBarEnabled()
11306 * @see #computeVerticalScrollRange()
11307 * @see #computeVerticalScrollExtent()
11308 * @see #computeVerticalScrollOffset()
11309 * @see android.widget.ScrollBarDrawable
Mike Reede8853fc2009-09-04 14:01:48 -040011310 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011311 */
Romain Guy8fb95422010-08-17 18:38:51 -070011312 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11313 int l, int t, int r, int b) {
Mike Reede8853fc2009-09-04 14:01:48 -040011314 scrollBar.setBounds(l, t, r, b);
11315 scrollBar.draw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011316 }
11317
11318 /**
11319 * Implement this to do your drawing.
11320 *
11321 * @param canvas the canvas on which the background will be drawn
11322 */
11323 protected void onDraw(Canvas canvas) {
11324 }
11325
11326 /*
11327 * Caller is responsible for calling requestLayout if necessary.
11328 * (This allows addViewInLayout to not request a new layout.)
11329 */
11330 void assignParent(ViewParent parent) {
11331 if (mParent == null) {
11332 mParent = parent;
11333 } else if (parent == null) {
11334 mParent = null;
11335 } else {
11336 throw new RuntimeException("view " + this + " being added, but"
11337 + " it already has a parent");
11338 }
11339 }
11340
11341 /**
11342 * This is called when the view is attached to a window. At this point it
11343 * has a Surface and will start drawing. Note that this function is
Romain Guy5c22a8c2011-05-13 11:48:45 -070011344 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11345 * however it may be called any time before the first onDraw -- including
11346 * before or after {@link #onMeasure(int, int)}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011347 *
11348 * @see #onDetachedFromWindow()
11349 */
11350 protected void onAttachedToWindow() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011351 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011352 mParent.requestTransparentRegion(this);
11353 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011354
Dianne Hackborn4702a852012-08-17 15:18:29 -070011355 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
Adam Powell8568c3a2010-04-19 14:26:11 -070011356 initialAwakenScrollBars();
Dianne Hackborn4702a852012-08-17 15:18:29 -070011357 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
Adam Powell8568c3a2010-04-19 14:26:11 -070011358 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011359
Chet Haasea9b61ac2010-12-20 07:40:25 -080011360 jumpDrawablesToCurrentState();
Romain Guy2a0f2282012-05-08 14:43:12 -070011361
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011362 resolveRtlProperties();
Romain Guy2a0f2282012-05-08 14:43:12 -070011363
Svetoslav Ganov42138042012-03-20 11:51:39 -070011364 clearAccessibilityFocus();
Amith Yamasani4503c8d2011-06-17 12:36:14 -070011365 if (isFocused()) {
11366 InputMethodManager imm = InputMethodManager.peekInstance();
11367 imm.focusIn(this);
11368 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011369
11370 if (mAttachInfo != null && mDisplayList != null) {
11371 mAttachInfo.mViewRootImpl.dequeueDisplayList(mDisplayList);
11372 }
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011373 }
Cibu Johny86666632010-02-22 13:01:02 -080011374
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011375 void resolveRtlProperties() {
11376 // Order is important here: LayoutDirection MUST be resolved first...
11377 resolveLayoutDirection();
11378 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11379 resolvePadding();
11380 resolveLayoutParams();
11381 resolveTextDirection();
11382 resolveTextAlignment();
Fabrice Di Meglio0af4b8b2012-06-11 18:30:05 -070011383 resolveDrawables();
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011384 }
11385
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011386 /**
Romain Guybb9908b2012-03-08 11:14:07 -080011387 * @see #onScreenStateChanged(int)
11388 */
11389 void dispatchScreenStateChanged(int screenState) {
11390 onScreenStateChanged(screenState);
11391 }
11392
11393 /**
11394 * This method is called whenever the state of the screen this view is
11395 * attached to changes. A state change will usually occurs when the screen
11396 * turns on or off (whether it happens automatically or the user does it
11397 * manually.)
11398 *
11399 * @param screenState The new state of the screen. Can be either
11400 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11401 */
11402 public void onScreenStateChanged(int screenState) {
11403 }
11404
11405 /**
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011406 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11407 */
11408 private boolean hasRtlSupport() {
11409 return mContext.getApplicationInfo().hasRtlSupport();
11410 }
11411
11412 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011413 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11414 * that the parent directionality can and will be resolved before its children.
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011415 * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011416 */
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011417 public void resolveLayoutDirection() {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011418 // Clear any previous layout direction resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070011419 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011420
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011421 if (hasRtlSupport()) {
11422 // Set resolved depending on layout direction
11423 switch (getLayoutDirection()) {
11424 case LAYOUT_DIRECTION_INHERIT:
Fabrice Di Megliob93911f2012-06-26 19:43:15 -070011425 // We cannot resolve yet. LTR is by default and let the resolution happen again
11426 // later to get the correct resolved value
11427 if (!canResolveLayoutDirection()) return;
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011428
Fabrice Di Megliob93911f2012-06-26 19:43:15 -070011429 ViewGroup viewGroup = ((ViewGroup) mParent);
11430
11431 // We cannot resolve yet on the parent too. LTR is by default and let the
11432 // resolution happen again later
11433 if (!viewGroup.canResolveLayoutDirection()) return;
11434
11435 if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011436 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011437 }
11438 break;
11439 case LAYOUT_DIRECTION_RTL:
Dianne Hackborn4702a852012-08-17 15:18:29 -070011440 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011441 break;
11442 case LAYOUT_DIRECTION_LOCALE:
11443 if(isLayoutDirectionRtl(Locale.getDefault())) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011444 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011445 }
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011446 break;
11447 default:
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011448 // Nothing to do, LTR by default
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011449 }
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011450 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011451
11452 // Set to resolved
Dianne Hackborn4702a852012-08-17 15:18:29 -070011453 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011454 onResolvedLayoutDirectionChanged();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011455 }
11456
Fabrice Di Meglioaff599b2011-07-20 19:05:01 -070011457 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011458 * Called when layout direction has been resolved.
11459 *
11460 * The default implementation does nothing.
11461 */
11462 public void onResolvedLayoutDirectionChanged() {
11463 }
11464
11465 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011466 * Return if padding has been resolved
11467 */
11468 boolean isPaddingResolved() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011469 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) != 0;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011470 }
11471
11472 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011473 * Resolve padding depending on layout direction.
Fabrice Di Meglioaff599b2011-07-20 19:05:01 -070011474 */
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011475 public void resolvePadding() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011476 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11477 if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
11478 // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
11479 // left / right padding are used if defined. If they are not defined and start / end
11480 // padding are defined (e.g. in Frameworks resources), then we use start / end and
11481 // resolve them as left / right (layout direction is not taken into account).
11482 if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
11483 mUserPaddingLeft = mUserPaddingStart;
11484 }
11485 if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
11486 mUserPaddingRight = mUserPaddingEnd;
11487 }
11488
11489 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11490
11491 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11492 mUserPaddingBottom);
11493 } else {
11494 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11495 // If start / end padding are defined, they will be resolved (hence overriding) to
11496 // left / right or right / left depending on the resolved layout direction.
11497 // If start / end padding are not defined, use the left / right ones.
11498 int resolvedLayoutDirection = getResolvedLayoutDirection();
11499 switch (resolvedLayoutDirection) {
11500 case LAYOUT_DIRECTION_RTL:
11501 if (mUserPaddingStart != UNDEFINED_PADDING) {
11502 mUserPaddingRight = mUserPaddingStart;
11503 }
11504 if (mUserPaddingEnd != UNDEFINED_PADDING) {
11505 mUserPaddingLeft = mUserPaddingEnd;
11506 }
11507 break;
11508 case LAYOUT_DIRECTION_LTR:
11509 default:
11510 if (mUserPaddingStart != UNDEFINED_PADDING) {
11511 mUserPaddingLeft = mUserPaddingStart;
11512 }
11513 if (mUserPaddingEnd != UNDEFINED_PADDING) {
11514 mUserPaddingRight = mUserPaddingEnd;
11515 }
11516 }
11517
11518 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11519
11520 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11521 mUserPaddingBottom);
11522 onPaddingChanged(resolvedLayoutDirection);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011523 }
11524
Dianne Hackborn4702a852012-08-17 15:18:29 -070011525 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011526 }
11527
11528 /**
11529 * Resolve padding depending on the layout direction. Subclasses that care about
11530 * padding resolution should override this method. The default implementation does
11531 * nothing.
11532 *
11533 * @param layoutDirection the direction of the layout
11534 *
Fabrice Di Meglioe8dc07d2012-03-09 17:10:19 -080011535 * @see {@link #LAYOUT_DIRECTION_LTR}
11536 * @see {@link #LAYOUT_DIRECTION_RTL}
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011537 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011538 public void onPaddingChanged(int layoutDirection) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011539 }
11540
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011541 /**
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011542 * Check if layout direction resolution can be done.
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011543 *
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011544 * @return true if layout direction resolution can be done otherwise return false.
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011545 */
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011546 public boolean canResolveLayoutDirection() {
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011547 switch (getLayoutDirection()) {
11548 case LAYOUT_DIRECTION_INHERIT:
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011549 return (mParent != null) && (mParent instanceof ViewGroup);
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011550 default:
11551 return true;
11552 }
11553 }
11554
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011555 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011556 * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
11557 * when reset is done.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011558 */
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011559 public void resetResolvedLayoutDirection() {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -070011560 // Reset the current resolved bits
Dianne Hackborn4702a852012-08-17 15:18:29 -070011561 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011562 onResolvedLayoutDirectionReset();
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080011563 // Reset also the text direction
11564 resetResolvedTextDirection();
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011565 }
11566
11567 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011568 * Called during reset of resolved layout direction.
11569 *
11570 * Subclasses need to override this method to clear cached information that depends on the
11571 * resolved layout direction, or to inform child views that inherit their layout direction.
11572 *
11573 * The default implementation does nothing.
11574 */
11575 public void onResolvedLayoutDirectionReset() {
11576 }
11577
11578 /**
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011579 * Check if a Locale uses an RTL script.
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011580 *
11581 * @param locale Locale to check
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011582 * @return true if the Locale uses an RTL script.
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011583 */
Fabrice Di Meglio22268862011-06-27 18:13:18 -070011584 protected static boolean isLayoutDirectionRtl(Locale locale) {
Fabrice Di Megliod3d9f3f2012-09-18 12:55:32 -070011585 return (LAYOUT_DIRECTION_RTL == TextUtils.getLayoutDirectionFromLocale(locale));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011586 }
11587
11588 /**
11589 * This is called when the view is detached from a window. At this point it
11590 * no longer has a surface for drawing.
11591 *
11592 * @see #onAttachedToWindow()
11593 */
11594 protected void onDetachedFromWindow() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011595 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
Romain Guy6c319ca2011-01-11 14:29:25 -080011596
Romain Guya440b002010-02-24 15:57:54 -080011597 removeUnsetPressCallback();
Maryam Garrett1549dd12009-12-15 16:06:36 -050011598 removeLongPressCallback();
Adam Powell3cb8b632011-01-21 15:34:14 -080011599 removePerformClickCallback();
Svetoslav Ganova0156172011-06-26 17:55:44 -070011600 removeSendViewScrolledAccessibilityEventCallback();
Romain Guy6c319ca2011-01-11 14:29:25 -080011601
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011602 destroyDrawingCache();
Romain Guy6c319ca2011-01-11 14:29:25 -080011603
Romain Guya998dff2012-03-23 18:58:36 -070011604 destroyLayer(false);
Romain Guy8dd5b1e2011-01-14 17:28:51 -080011605
11606 if (mAttachInfo != null) {
Romain Guy51e4d4d2012-03-15 18:30:47 -070011607 if (mDisplayList != null) {
Romain Guy2a0f2282012-05-08 14:43:12 -070011608 mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
Romain Guy51e4d4d2012-03-15 18:30:47 -070011609 }
Jeff Browna175a5b2012-02-15 19:18:31 -080011610 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
Romain Guy51e4d4d2012-03-15 18:30:47 -070011611 } else {
Romain Guy38c2ece2012-05-24 14:20:56 -070011612 // Should never happen
11613 clearDisplayList();
Romain Guy8dd5b1e2011-01-14 17:28:51 -080011614 }
11615
Patrick Dubroyec84c3a2011-01-13 17:55:37 -080011616 mCurrentAnimation = null;
Fabrice Di Meglio7f86c802011-07-01 15:09:24 -070011617
11618 resetResolvedLayoutDirection();
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070011619 resetResolvedTextAlignment();
Svetoslav Ganov42138042012-03-20 11:51:39 -070011620 resetAccessibilityStateChanged();
Dianne Hackborn4702a852012-08-17 15:18:29 -070011621 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011622 }
11623
11624 /**
11625 * @return The number of times this view has been attached to a window
11626 */
11627 protected int getWindowAttachCount() {
11628 return mWindowAttachCount;
11629 }
11630
11631 /**
11632 * Retrieve a unique token identifying the window this view is attached to.
11633 * @return Return the window's token for use in
11634 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
11635 */
11636 public IBinder getWindowToken() {
11637 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
11638 }
11639
11640 /**
11641 * Retrieve a unique token identifying the top-level "real" window of
11642 * the window that this view is attached to. That is, this is like
11643 * {@link #getWindowToken}, except if the window this view in is a panel
11644 * window (attached to another containing window), then the token of
11645 * the containing window is returned instead.
11646 *
11647 * @return Returns the associated window token, either
11648 * {@link #getWindowToken()} or the containing window's token.
11649 */
11650 public IBinder getApplicationWindowToken() {
11651 AttachInfo ai = mAttachInfo;
11652 if (ai != null) {
11653 IBinder appWindowToken = ai.mPanelParentWindowToken;
11654 if (appWindowToken == null) {
11655 appWindowToken = ai.mWindowToken;
11656 }
11657 return appWindowToken;
11658 }
11659 return null;
11660 }
11661
11662 /**
Jeff Brown98365d72012-08-19 20:30:52 -070011663 * Gets the logical display to which the view's window has been attached.
11664 *
11665 * @return The logical display, or null if the view is not currently attached to a window.
11666 */
11667 public Display getDisplay() {
11668 return mAttachInfo != null ? mAttachInfo.mDisplay : null;
11669 }
11670
11671 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011672 * Retrieve private session object this view hierarchy is using to
11673 * communicate with the window manager.
11674 * @return the session object to communicate with the window manager
11675 */
11676 /*package*/ IWindowSession getWindowSession() {
11677 return mAttachInfo != null ? mAttachInfo.mSession : null;
11678 }
11679
11680 /**
11681 * @param info the {@link android.view.View.AttachInfo} to associated with
11682 * this view
11683 */
11684 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
11685 //System.out.println("Attached! " + this);
11686 mAttachInfo = info;
11687 mWindowAttachCount++;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080011688 // We will need to evaluate the drawable state at least once.
Dianne Hackborn4702a852012-08-17 15:18:29 -070011689 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011690 if (mFloatingTreeObserver != null) {
11691 info.mTreeObserver.merge(mFloatingTreeObserver);
11692 mFloatingTreeObserver = null;
11693 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070011694 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011695 mAttachInfo.mScrollContainers.add(this);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011696 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011697 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070011698 performCollectViewAttributes(mAttachInfo, visibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011699 onAttachedToWindow();
Adam Powell4afd62b2011-02-18 15:02:18 -080011700
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011701 ListenerInfo li = mListenerInfo;
Adam Powell4afd62b2011-02-18 15:02:18 -080011702 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011703 li != null ? li.mOnAttachStateChangeListeners : null;
Adam Powell4afd62b2011-02-18 15:02:18 -080011704 if (listeners != null && listeners.size() > 0) {
11705 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11706 // perform the dispatching. The iterator is a safe guard against listeners that
11707 // could mutate the list by calling the various add/remove methods. This prevents
11708 // the array from being modified while we iterate it.
11709 for (OnAttachStateChangeListener listener : listeners) {
11710 listener.onViewAttachedToWindow(this);
11711 }
11712 }
11713
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011714 int vis = info.mWindowVisibility;
11715 if (vis != GONE) {
11716 onWindowVisibilityChanged(vis);
11717 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070011718 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080011719 // If nobody has evaluated the drawable state yet, then do it now.
11720 refreshDrawableState();
11721 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011722 }
11723
11724 void dispatchDetachedFromWindow() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011725 AttachInfo info = mAttachInfo;
11726 if (info != null) {
11727 int vis = info.mWindowVisibility;
11728 if (vis != GONE) {
11729 onWindowVisibilityChanged(GONE);
11730 }
11731 }
11732
11733 onDetachedFromWindow();
Romain Guy01d5edc2011-01-28 11:28:53 -080011734
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011735 ListenerInfo li = mListenerInfo;
Adam Powell4afd62b2011-02-18 15:02:18 -080011736 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011737 li != null ? li.mOnAttachStateChangeListeners : null;
Adam Powell4afd62b2011-02-18 15:02:18 -080011738 if (listeners != null && listeners.size() > 0) {
11739 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11740 // perform the dispatching. The iterator is a safe guard against listeners that
11741 // could mutate the list by calling the various add/remove methods. This prevents
11742 // the array from being modified while we iterate it.
11743 for (OnAttachStateChangeListener listener : listeners) {
11744 listener.onViewDetachedFromWindow(this);
11745 }
11746 }
11747
Dianne Hackborn4702a852012-08-17 15:18:29 -070011748 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 mAttachInfo.mScrollContainers.remove(this);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011750 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 }
Romain Guy01d5edc2011-01-28 11:28:53 -080011752
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011753 mAttachInfo = null;
11754 }
11755
11756 /**
11757 * Store this view hierarchy's frozen state into the given container.
11758 *
11759 * @param container The SparseArray in which to save the view's state.
11760 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011761 * @see #restoreHierarchyState(android.util.SparseArray)
11762 * @see #dispatchSaveInstanceState(android.util.SparseArray)
11763 * @see #onSaveInstanceState()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011764 */
11765 public void saveHierarchyState(SparseArray<Parcelable> container) {
11766 dispatchSaveInstanceState(container);
11767 }
11768
11769 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070011770 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
11771 * this view and its children. May be overridden to modify how freezing happens to a
11772 * view's children; for example, some views may want to not store state for their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011773 *
11774 * @param container The SparseArray in which to save the view's state.
11775 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011776 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11777 * @see #saveHierarchyState(android.util.SparseArray)
11778 * @see #onSaveInstanceState()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011779 */
11780 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
11781 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011782 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011783 Parcelable state = onSaveInstanceState();
Dianne Hackborn4702a852012-08-17 15:18:29 -070011784 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 throw new IllegalStateException(
11786 "Derived class did not call super.onSaveInstanceState()");
11787 }
11788 if (state != null) {
11789 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
11790 // + ": " + state);
11791 container.put(mID, state);
11792 }
11793 }
11794 }
11795
11796 /**
11797 * Hook allowing a view to generate a representation of its internal state
11798 * that can later be used to create a new instance with that same state.
11799 * This state should only contain information that is not persistent or can
11800 * not be reconstructed later. For example, you will never store your
11801 * current position on screen because that will be computed again when a
11802 * new instance of the view is placed in its view hierarchy.
11803 * <p>
11804 * Some examples of things you may store here: the current cursor position
11805 * in a text view (but usually not the text itself since that is stored in a
11806 * content provider or other persistent storage), the currently selected
11807 * item in a list view.
11808 *
11809 * @return Returns a Parcelable object containing the view's current dynamic
11810 * state, or null if there is nothing interesting to save. The
11811 * default implementation returns null.
Philip Milne6c8ea062012-04-03 17:38:43 -070011812 * @see #onRestoreInstanceState(android.os.Parcelable)
11813 * @see #saveHierarchyState(android.util.SparseArray)
11814 * @see #dispatchSaveInstanceState(android.util.SparseArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011815 * @see #setSaveEnabled(boolean)
11816 */
11817 protected Parcelable onSaveInstanceState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011818 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011819 return BaseSavedState.EMPTY_STATE;
11820 }
11821
11822 /**
11823 * Restore this view hierarchy's frozen state from the given container.
11824 *
11825 * @param container The SparseArray which holds previously frozen states.
11826 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011827 * @see #saveHierarchyState(android.util.SparseArray)
11828 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11829 * @see #onRestoreInstanceState(android.os.Parcelable)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011830 */
11831 public void restoreHierarchyState(SparseArray<Parcelable> container) {
11832 dispatchRestoreInstanceState(container);
11833 }
11834
11835 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070011836 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
11837 * state for this view and its children. May be overridden to modify how restoring
11838 * happens to a view's children; for example, some views may want to not store state
11839 * for their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 *
11841 * @param container The SparseArray which holds previously saved state.
11842 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011843 * @see #dispatchSaveInstanceState(android.util.SparseArray)
11844 * @see #restoreHierarchyState(android.util.SparseArray)
11845 * @see #onRestoreInstanceState(android.os.Parcelable)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011846 */
11847 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
11848 if (mID != NO_ID) {
11849 Parcelable state = container.get(mID);
11850 if (state != null) {
11851 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
11852 // + ": " + state);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011853 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011854 onRestoreInstanceState(state);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011855 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011856 throw new IllegalStateException(
11857 "Derived class did not call super.onRestoreInstanceState()");
11858 }
11859 }
11860 }
11861 }
11862
11863 /**
11864 * Hook allowing a view to re-apply a representation of its internal state that had previously
11865 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
11866 * null state.
11867 *
11868 * @param state The frozen state that had previously been returned by
11869 * {@link #onSaveInstanceState}.
11870 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011871 * @see #onSaveInstanceState()
11872 * @see #restoreHierarchyState(android.util.SparseArray)
11873 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011874 */
11875 protected void onRestoreInstanceState(Parcelable state) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011876 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011877 if (state != BaseSavedState.EMPTY_STATE && state != null) {
Romain Guy237c1ce2009-12-08 11:30:25 -080011878 throw new IllegalArgumentException("Wrong state class, expecting View State but "
11879 + "received " + state.getClass().toString() + " instead. This usually happens "
Joe Malin32736f02011-01-19 16:14:20 -080011880 + "when two views of different type have the same id in the same hierarchy. "
11881 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
Romain Guy237c1ce2009-12-08 11:30:25 -080011882 + "other views do not use the same id.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011883 }
11884 }
11885
11886 /**
11887 * <p>Return the time at which the drawing of the view hierarchy started.</p>
11888 *
11889 * @return the drawing start time in milliseconds
11890 */
11891 public long getDrawingTime() {
11892 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
11893 }
11894
11895 /**
11896 * <p>Enables or disables the duplication of the parent's state into this view. When
11897 * duplication is enabled, this view gets its drawable state from its parent rather
11898 * than from its own internal properties.</p>
11899 *
11900 * <p>Note: in the current implementation, setting this property to true after the
11901 * view was added to a ViewGroup might have no effect at all. This property should
11902 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
11903 *
11904 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
11905 * property is enabled, an exception will be thrown.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011906 *
Gilles Debunnefb817032011-01-13 13:52:49 -080011907 * <p>Note: if the child view uses and updates additionnal states which are unknown to the
11908 * parent, these states should not be affected by this method.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011909 *
11910 * @param enabled True to enable duplication of the parent's drawable state, false
11911 * to disable it.
11912 *
11913 * @see #getDrawableState()
11914 * @see #isDuplicateParentStateEnabled()
11915 */
11916 public void setDuplicateParentStateEnabled(boolean enabled) {
11917 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
11918 }
11919
11920 /**
11921 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
11922 *
11923 * @return True if this view's drawable state is duplicated from the parent,
11924 * false otherwise
11925 *
11926 * @see #getDrawableState()
11927 * @see #setDuplicateParentStateEnabled(boolean)
11928 */
11929 public boolean isDuplicateParentStateEnabled() {
11930 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
11931 }
11932
11933 /**
Romain Guy171c5922011-01-06 10:04:23 -080011934 * <p>Specifies the type of layer backing this view. The layer can be
11935 * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
11936 * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011937 *
Romain Guy171c5922011-01-06 10:04:23 -080011938 * <p>A layer is associated with an optional {@link android.graphics.Paint}
11939 * instance that controls how the layer is composed on screen. The following
11940 * properties of the paint are taken into account when composing the layer:</p>
11941 * <ul>
11942 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
11943 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
11944 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
11945 * </ul>
Joe Malin32736f02011-01-19 16:14:20 -080011946 *
Romain Guy171c5922011-01-06 10:04:23 -080011947 * <p>If this view has an alpha value set to < 1.0 by calling
11948 * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
11949 * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
11950 * equivalent to setting a hardware layer on this view and providing a paint with
Chet Haased15ebf22012-09-05 11:40:29 -070011951 * the desired alpha value.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011952 *
Romain Guy171c5922011-01-06 10:04:23 -080011953 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
11954 * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
11955 * for more information on when and how to use layers.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011956 *
Chet Haased15ebf22012-09-05 11:40:29 -070011957 * @param layerType The type of layer to use with this view, must be one of
Romain Guy171c5922011-01-06 10:04:23 -080011958 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
11959 * {@link #LAYER_TYPE_HARDWARE}
11960 * @param paint The paint used to compose the layer. This argument is optional
11961 * and can be null. It is ignored when the layer type is
11962 * {@link #LAYER_TYPE_NONE}
Joe Malin32736f02011-01-19 16:14:20 -080011963 *
11964 * @see #getLayerType()
Romain Guy171c5922011-01-06 10:04:23 -080011965 * @see #LAYER_TYPE_NONE
11966 * @see #LAYER_TYPE_SOFTWARE
11967 * @see #LAYER_TYPE_HARDWARE
Joe Malin32736f02011-01-19 16:14:20 -080011968 * @see #setAlpha(float)
11969 *
Romain Guy171c5922011-01-06 10:04:23 -080011970 * @attr ref android.R.styleable#View_layerType
11971 */
11972 public void setLayerType(int layerType, Paint paint) {
11973 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
Joe Malin32736f02011-01-19 16:14:20 -080011974 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
Romain Guy171c5922011-01-06 10:04:23 -080011975 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
11976 }
Chet Haasedaf98e92011-01-10 14:10:36 -080011977
Romain Guyd6cd5722011-01-17 14:42:41 -080011978 if (layerType == mLayerType) {
11979 if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
11980 mLayerPaint = paint == null ? new Paint() : paint;
Romain Guy0fd89bf2011-01-26 15:41:30 -080011981 invalidateParentCaches();
11982 invalidate(true);
Romain Guyd6cd5722011-01-17 14:42:41 -080011983 }
11984 return;
11985 }
Romain Guy171c5922011-01-06 10:04:23 -080011986
11987 // Destroy any previous software drawing cache if needed
Romain Guy6c319ca2011-01-11 14:29:25 -080011988 switch (mLayerType) {
Chet Haase6f33e812011-05-17 12:42:19 -070011989 case LAYER_TYPE_HARDWARE:
Romain Guya998dff2012-03-23 18:58:36 -070011990 destroyLayer(false);
Romain Guy31f2c2e2011-11-21 10:55:41 -080011991 // fall through - non-accelerated views may use software layer mechanism instead
Romain Guy6c319ca2011-01-11 14:29:25 -080011992 case LAYER_TYPE_SOFTWARE:
Romain Guy6d7475d2011-07-27 16:28:21 -070011993 destroyDrawingCache();
Romain Guy6c319ca2011-01-11 14:29:25 -080011994 break;
Romain Guy6c319ca2011-01-11 14:29:25 -080011995 default:
11996 break;
Romain Guy171c5922011-01-06 10:04:23 -080011997 }
11998
11999 mLayerType = layerType;
Romain Guy3a3133d2011-02-01 22:59:58 -080012000 final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
12001 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
12002 mLocalDirtyRect = layerDisabled ? null : new Rect();
Romain Guy171c5922011-01-06 10:04:23 -080012003
Romain Guy0fd89bf2011-01-26 15:41:30 -080012004 invalidateParentCaches();
12005 invalidate(true);
Romain Guy171c5922011-01-06 10:04:23 -080012006 }
12007
12008 /**
Chet Haased15ebf22012-09-05 11:40:29 -070012009 * Updates the {@link Paint} object used with the current layer (used only if the current
12010 * layer type is not set to {@link #LAYER_TYPE_NONE}). Changed properties of the Paint
12011 * provided to {@link #setLayerType(int, android.graphics.Paint)} will be used the next time
12012 * the View is redrawn, but {@link #setLayerPaint(android.graphics.Paint)} must be called to
12013 * ensure that the view gets redrawn immediately.
12014 *
12015 * <p>A layer is associated with an optional {@link android.graphics.Paint}
12016 * instance that controls how the layer is composed on screen. The following
12017 * properties of the paint are taken into account when composing the layer:</p>
12018 * <ul>
12019 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
12020 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
12021 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
12022 * </ul>
12023 *
12024 * <p>If this view has an alpha value set to < 1.0 by calling
12025 * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
12026 * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
12027 * equivalent to setting a hardware layer on this view and providing a paint with
12028 * the desired alpha value.</p>
12029 *
12030 * @param paint The paint used to compose the layer. This argument is optional
12031 * and can be null. It is ignored when the layer type is
12032 * {@link #LAYER_TYPE_NONE}
12033 *
12034 * @see #setLayerType(int, android.graphics.Paint)
12035 */
12036 public void setLayerPaint(Paint paint) {
12037 int layerType = getLayerType();
12038 if (layerType != LAYER_TYPE_NONE) {
12039 mLayerPaint = paint == null ? new Paint() : paint;
12040 if (layerType == LAYER_TYPE_HARDWARE) {
12041 HardwareLayer layer = getHardwareLayer();
12042 if (layer != null) {
12043 layer.setLayerPaint(paint);
12044 }
12045 invalidateViewProperty(false, false);
12046 } else {
12047 invalidate();
12048 }
12049 }
12050 }
12051
12052 /**
Romain Guy59c7f802011-09-29 17:21:45 -070012053 * Indicates whether this view has a static layer. A view with layer type
12054 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
12055 * dynamic.
12056 */
12057 boolean hasStaticLayer() {
Romain Guy2bf68f02012-03-02 13:37:47 -080012058 return true;
Romain Guy59c7f802011-09-29 17:21:45 -070012059 }
12060
12061 /**
Romain Guy171c5922011-01-06 10:04:23 -080012062 * Indicates what type of layer is currently associated with this view. By default
12063 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
12064 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
12065 * for more information on the different types of layers.
Joe Malin32736f02011-01-19 16:14:20 -080012066 *
Romain Guy171c5922011-01-06 10:04:23 -080012067 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
12068 * {@link #LAYER_TYPE_HARDWARE}
Joe Malin32736f02011-01-19 16:14:20 -080012069 *
12070 * @see #setLayerType(int, android.graphics.Paint)
Philip Milne6c8ea062012-04-03 17:38:43 -070012071 * @see #buildLayer()
Romain Guy171c5922011-01-06 10:04:23 -080012072 * @see #LAYER_TYPE_NONE
12073 * @see #LAYER_TYPE_SOFTWARE
12074 * @see #LAYER_TYPE_HARDWARE
12075 */
12076 public int getLayerType() {
12077 return mLayerType;
12078 }
Joe Malin32736f02011-01-19 16:14:20 -080012079
Romain Guy6c319ca2011-01-11 14:29:25 -080012080 /**
Romain Guyf1ae1062011-03-02 18:16:04 -080012081 * Forces this view's layer to be created and this view to be rendered
12082 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
12083 * invoking this method will have no effect.
Philip Milne6c8ea062012-04-03 17:38:43 -070012084 *
Romain Guyf1ae1062011-03-02 18:16:04 -080012085 * This method can for instance be used to render a view into its layer before
12086 * starting an animation. If this view is complex, rendering into the layer
12087 * before starting the animation will avoid skipping frames.
Philip Milne6c8ea062012-04-03 17:38:43 -070012088 *
Romain Guyf1ae1062011-03-02 18:16:04 -080012089 * @throws IllegalStateException If this view is not attached to a window
Philip Milne6c8ea062012-04-03 17:38:43 -070012090 *
12091 * @see #setLayerType(int, android.graphics.Paint)
Romain Guyf1ae1062011-03-02 18:16:04 -080012092 */
12093 public void buildLayer() {
12094 if (mLayerType == LAYER_TYPE_NONE) return;
12095
12096 if (mAttachInfo == null) {
12097 throw new IllegalStateException("This view must be attached to a window first");
12098 }
12099
12100 switch (mLayerType) {
12101 case LAYER_TYPE_HARDWARE:
Romain Guyd0609e42011-11-21 17:21:15 -080012102 if (mAttachInfo.mHardwareRenderer != null &&
12103 mAttachInfo.mHardwareRenderer.isEnabled() &&
12104 mAttachInfo.mHardwareRenderer.validate()) {
Michael Jurka7e52caf2012-03-06 15:57:06 -080012105 getHardwareLayer();
Romain Guyd0609e42011-11-21 17:21:15 -080012106 }
Romain Guyf1ae1062011-03-02 18:16:04 -080012107 break;
12108 case LAYER_TYPE_SOFTWARE:
12109 buildDrawingCache(true);
12110 break;
12111 }
12112 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012113
Romain Guyf1ae1062011-03-02 18:16:04 -080012114 /**
Romain Guy6c319ca2011-01-11 14:29:25 -080012115 * <p>Returns a hardware layer that can be used to draw this view again
12116 * without executing its draw method.</p>
12117 *
12118 * @return A HardwareLayer ready to render, or null if an error occurred.
12119 */
Michael Jurka7e52caf2012-03-06 15:57:06 -080012120 HardwareLayer getHardwareLayer() {
Romain Guyea835032011-07-28 19:24:37 -070012121 if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
12122 !mAttachInfo.mHardwareRenderer.isEnabled()) {
Romain Guy6c319ca2011-01-11 14:29:25 -080012123 return null;
12124 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012125
Romain Guy9c4b79a2011-11-10 19:23:58 -080012126 if (!mAttachInfo.mHardwareRenderer.validate()) return null;
Romain Guy6c319ca2011-01-11 14:29:25 -080012127
12128 final int width = mRight - mLeft;
12129 final int height = mBottom - mTop;
Joe Malin32736f02011-01-19 16:14:20 -080012130
Romain Guy6c319ca2011-01-11 14:29:25 -080012131 if (width == 0 || height == 0) {
12132 return null;
12133 }
12134
Dianne Hackborn4702a852012-08-17 15:18:29 -070012135 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
Romain Guy6c319ca2011-01-11 14:29:25 -080012136 if (mHardwareLayer == null) {
12137 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
12138 width, height, isOpaque());
Michael Jurka952e02b2012-03-13 18:34:35 -070012139 mLocalDirtyRect.set(0, 0, width, height);
Romain Guy846a5332012-07-11 17:44:57 -070012140 } else {
12141 if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
12142 mHardwareLayer.resize(width, height);
12143 mLocalDirtyRect.set(0, 0, width, height);
12144 }
12145
12146 // This should not be necessary but applications that change
12147 // the parameters of their background drawable without calling
12148 // this.setBackground(Drawable) can leave the view in a bad state
12149 // (for instance isOpaque() returns true, but the background is
12150 // not opaque.)
12151 computeOpaqueFlags();
12152
12153 final boolean opaque = isOpaque();
12154 if (mHardwareLayer.isOpaque() != opaque) {
12155 mHardwareLayer.setOpaque(opaque);
12156 mLocalDirtyRect.set(0, 0, width, height);
12157 }
Romain Guy6c319ca2011-01-11 14:29:25 -080012158 }
12159
Romain Guy5cd5c3f2011-10-17 17:10:02 -070012160 // The layer is not valid if the underlying GPU resources cannot be allocated
12161 if (!mHardwareLayer.isValid()) {
12162 return null;
12163 }
Chet Haased15ebf22012-09-05 11:40:29 -070012164 mHardwareLayer.setLayerPaint(mLayerPaint);
Romain Guy5cd5c3f2011-10-17 17:10:02 -070012165
Chet Haasea1cff502012-02-21 13:43:44 -080012166 mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
Michael Jurka7e52caf2012-03-06 15:57:06 -080012167 mLocalDirtyRect.setEmpty();
Romain Guy6c319ca2011-01-11 14:29:25 -080012168 }
12169
12170 return mHardwareLayer;
12171 }
Romain Guy171c5922011-01-06 10:04:23 -080012172
Romain Guy589b0bb2011-10-10 13:57:47 -070012173 /**
12174 * Destroys this View's hardware layer if possible.
Philip Milne6c8ea062012-04-03 17:38:43 -070012175 *
Romain Guy589b0bb2011-10-10 13:57:47 -070012176 * @return True if the layer was destroyed, false otherwise.
Philip Milne6c8ea062012-04-03 17:38:43 -070012177 *
12178 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy589b0bb2011-10-10 13:57:47 -070012179 * @see #LAYER_TYPE_HARDWARE
12180 */
Romain Guya998dff2012-03-23 18:58:36 -070012181 boolean destroyLayer(boolean valid) {
Romain Guy6d7475d2011-07-27 16:28:21 -070012182 if (mHardwareLayer != null) {
Romain Guy9c4b79a2011-11-10 19:23:58 -080012183 AttachInfo info = mAttachInfo;
12184 if (info != null && info.mHardwareRenderer != null &&
Romain Guya998dff2012-03-23 18:58:36 -070012185 info.mHardwareRenderer.isEnabled() &&
12186 (valid || info.mHardwareRenderer.validate())) {
Romain Guy9c4b79a2011-11-10 19:23:58 -080012187 mHardwareLayer.destroy();
12188 mHardwareLayer = null;
Romain Guy31f2c2e2011-11-21 10:55:41 -080012189
Romain Guy9c4b79a2011-11-10 19:23:58 -080012190 invalidate(true);
12191 invalidateParentCaches();
12192 }
Romain Guy65b345f2011-07-27 18:51:50 -070012193 return true;
Romain Guy6d7475d2011-07-27 16:28:21 -070012194 }
Romain Guy65b345f2011-07-27 18:51:50 -070012195 return false;
Romain Guy6d7475d2011-07-27 16:28:21 -070012196 }
12197
Romain Guy171c5922011-01-06 10:04:23 -080012198 /**
Romain Guy31f2c2e2011-11-21 10:55:41 -080012199 * Destroys all hardware rendering resources. This method is invoked
12200 * when the system needs to reclaim resources. Upon execution of this
12201 * method, you should free any OpenGL resources created by the view.
Philip Milne6c8ea062012-04-03 17:38:43 -070012202 *
Romain Guy31f2c2e2011-11-21 10:55:41 -080012203 * Note: you <strong>must</strong> call
12204 * <code>super.destroyHardwareResources()</code> when overriding
12205 * this method.
Philip Milne6c8ea062012-04-03 17:38:43 -070012206 *
Romain Guy31f2c2e2011-11-21 10:55:41 -080012207 * @hide
12208 */
12209 protected void destroyHardwareResources() {
Romain Guya998dff2012-03-23 18:58:36 -070012210 destroyLayer(true);
Romain Guy31f2c2e2011-11-21 10:55:41 -080012211 }
12212
12213 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012214 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12215 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12216 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12217 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12218 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12219 * null.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012220 *
Romain Guy171c5922011-01-06 10:04:23 -080012221 * <p>Enabling the drawing cache is similar to
12222 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
Chet Haasedaf98e92011-01-10 14:10:36 -080012223 * acceleration is turned off. When hardware acceleration is turned on, enabling the
12224 * drawing cache has no effect on rendering because the system uses a different mechanism
12225 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12226 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12227 * for information on how to enable software and hardware layers.</p>
12228 *
12229 * <p>This API can be used to manually generate
12230 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12231 * {@link #getDrawingCache()}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012232 *
12233 * @param enabled true to enable the drawing cache, false otherwise
12234 *
12235 * @see #isDrawingCacheEnabled()
12236 * @see #getDrawingCache()
12237 * @see #buildDrawingCache()
Joe Malin32736f02011-01-19 16:14:20 -080012238 * @see #setLayerType(int, android.graphics.Paint)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012239 */
12240 public void setDrawingCacheEnabled(boolean enabled) {
Romain Guy0211a0a2011-02-14 16:34:59 -080012241 mCachingFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012242 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12243 }
12244
12245 /**
12246 * <p>Indicates whether the drawing cache is enabled for this view.</p>
12247 *
12248 * @return true if the drawing cache is enabled
12249 *
12250 * @see #setDrawingCacheEnabled(boolean)
12251 * @see #getDrawingCache()
12252 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070012253 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012254 public boolean isDrawingCacheEnabled() {
12255 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12256 }
12257
12258 /**
Chet Haasedaf98e92011-01-10 14:10:36 -080012259 * Debugging utility which recursively outputs the dirty state of a view and its
12260 * descendants.
Joe Malin32736f02011-01-19 16:14:20 -080012261 *
Chet Haasedaf98e92011-01-10 14:10:36 -080012262 * @hide
12263 */
Romain Guy676b1732011-02-14 14:45:33 -080012264 @SuppressWarnings({"UnusedDeclaration"})
Chet Haasedaf98e92011-01-10 14:10:36 -080012265 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012266 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
12267 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
12268 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
12269 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
Chet Haasedaf98e92011-01-10 14:10:36 -080012270 if (clear) {
12271 mPrivateFlags &= clearMask;
12272 }
12273 if (this instanceof ViewGroup) {
12274 ViewGroup parent = (ViewGroup) this;
12275 final int count = parent.getChildCount();
12276 for (int i = 0; i < count; i++) {
Romain Guy7d7b5492011-01-24 16:33:45 -080012277 final View child = parent.getChildAt(i);
Chet Haasedaf98e92011-01-10 14:10:36 -080012278 child.outputDirtyFlags(indent + " ", clear, clearMask);
12279 }
12280 }
12281 }
12282
12283 /**
12284 * This method is used by ViewGroup to cause its children to restore or recreate their
12285 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12286 * to recreate its own display list, which would happen if it went through the normal
12287 * draw/dispatchDraw mechanisms.
12288 *
12289 * @hide
12290 */
12291 protected void dispatchGetDisplayList() {}
Chet Haasef4ac5472011-01-27 10:30:25 -080012292
12293 /**
12294 * A view that is not attached or hardware accelerated cannot create a display list.
12295 * This method checks these conditions and returns the appropriate result.
12296 *
12297 * @return true if view has the ability to create a display list, false otherwise.
12298 *
12299 * @hide
12300 */
12301 public boolean canHaveDisplayList() {
Romain Guy676b1732011-02-14 14:45:33 -080012302 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
Chet Haasef4ac5472011-01-27 10:30:25 -080012303 }
Joe Malin32736f02011-01-19 16:14:20 -080012304
Chet Haasedaf98e92011-01-10 14:10:36 -080012305 /**
Gilles Debunneb35ab7b2011-12-05 15:54:00 -080012306 * @return The HardwareRenderer associated with that view or null if hardware rendering
12307 * is not supported or this this has not been attached to a window.
12308 *
12309 * @hide
12310 */
12311 public HardwareRenderer getHardwareRenderer() {
12312 if (mAttachInfo != null) {
12313 return mAttachInfo.mHardwareRenderer;
12314 }
12315 return null;
12316 }
12317
12318 /**
Chet Haasea1cff502012-02-21 13:43:44 -080012319 * Returns a DisplayList. If the incoming displayList is null, one will be created.
12320 * Otherwise, the same display list will be returned (after having been rendered into
12321 * along the way, depending on the invalidation state of the view).
12322 *
12323 * @param displayList The previous version of this displayList, could be null.
12324 * @param isLayer Whether the requester of the display list is a layer. If so,
12325 * the view will avoid creating a layer inside the resulting display list.
12326 * @return A new or reused DisplayList object.
12327 */
12328 private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12329 if (!canHaveDisplayList()) {
12330 return null;
12331 }
12332
Dianne Hackborn4702a852012-08-17 15:18:29 -070012333 if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
Chet Haasea1cff502012-02-21 13:43:44 -080012334 displayList == null || !displayList.isValid() ||
12335 (!isLayer && mRecreateDisplayList))) {
12336 // Don't need to recreate the display list, just need to tell our
12337 // children to restore/recreate theirs
12338 if (displayList != null && displayList.isValid() &&
12339 !isLayer && !mRecreateDisplayList) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012340 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12341 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haasea1cff502012-02-21 13:43:44 -080012342 dispatchGetDisplayList();
12343
12344 return displayList;
12345 }
12346
12347 if (!isLayer) {
12348 // If we got here, we're recreating it. Mark it as such to ensure that
12349 // we copy in child display lists into ours in drawChild()
12350 mRecreateDisplayList = true;
12351 }
12352 if (displayList == null) {
12353 final String name = getClass().getSimpleName();
12354 displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12355 // If we're creating a new display list, make sure our parent gets invalidated
12356 // since they will need to recreate their display list to account for this
12357 // new child display list.
12358 invalidateParentCaches();
12359 }
12360
12361 boolean caching = false;
12362 final HardwareCanvas canvas = displayList.start();
Chet Haasea1cff502012-02-21 13:43:44 -080012363 int width = mRight - mLeft;
12364 int height = mBottom - mTop;
12365
12366 try {
12367 canvas.setViewport(width, height);
12368 // The dirty rect should always be null for a display list
12369 canvas.onPreDraw(null);
Michael Jurkaba649742012-06-28 19:12:58 -070012370 int layerType = getLayerType();
Chet Haase1271e2c2012-04-20 09:54:27 -070012371 if (!isLayer && layerType != LAYER_TYPE_NONE) {
Chet Haaseb85967b2012-03-26 14:37:51 -070012372 if (layerType == LAYER_TYPE_HARDWARE) {
12373 final HardwareLayer layer = getHardwareLayer();
12374 if (layer != null && layer.isValid()) {
12375 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12376 } else {
12377 canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12378 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12379 Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12380 }
12381 caching = true;
Chet Haasea1cff502012-02-21 13:43:44 -080012382 } else {
Chet Haaseb85967b2012-03-26 14:37:51 -070012383 buildDrawingCache(true);
12384 Bitmap cache = getDrawingCache(true);
12385 if (cache != null) {
12386 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12387 caching = true;
12388 }
Chet Haasea1cff502012-02-21 13:43:44 -080012389 }
Chet Haasea1cff502012-02-21 13:43:44 -080012390 } else {
12391
12392 computeScroll();
12393
Chet Haasea1cff502012-02-21 13:43:44 -080012394 canvas.translate(-mScrollX, -mScrollY);
12395 if (!isLayer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012396 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12397 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haasea1cff502012-02-21 13:43:44 -080012398 }
12399
12400 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070012401 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Chet Haasea1cff502012-02-21 13:43:44 -080012402 dispatchDraw(canvas);
12403 } else {
12404 draw(canvas);
12405 }
12406 }
12407 } finally {
Chet Haasea1cff502012-02-21 13:43:44 -080012408 canvas.onPostDraw();
12409
12410 displayList.end();
Chet Haase1271e2c2012-04-20 09:54:27 -070012411 displayList.setCaching(caching);
12412 if (isLayer) {
Chet Haasea1cff502012-02-21 13:43:44 -080012413 displayList.setLeftTopRightBottom(0, 0, width, height);
12414 } else {
12415 setDisplayListProperties(displayList);
12416 }
12417 }
12418 } else if (!isLayer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012419 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12420 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haasea1cff502012-02-21 13:43:44 -080012421 }
12422
12423 return displayList;
12424 }
12425
12426 /**
12427 * Get the DisplayList for the HardwareLayer
12428 *
12429 * @param layer The HardwareLayer whose DisplayList we want
12430 * @return A DisplayList fopr the specified HardwareLayer
12431 */
12432 private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12433 DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12434 layer.setDisplayList(displayList);
12435 return displayList;
12436 }
12437
12438
12439 /**
Romain Guyb051e892010-09-28 19:09:36 -070012440 * <p>Returns a display list that can be used to draw this view again
12441 * without executing its draw method.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012442 *
Romain Guyb051e892010-09-28 19:09:36 -070012443 * @return A DisplayList ready to replay, or null if caching is not enabled.
Chet Haasedaf98e92011-01-10 14:10:36 -080012444 *
12445 * @hide
Romain Guyb051e892010-09-28 19:09:36 -070012446 */
Chet Haasedaf98e92011-01-10 14:10:36 -080012447 public DisplayList getDisplayList() {
Chet Haasea1cff502012-02-21 13:43:44 -080012448 mDisplayList = getDisplayList(mDisplayList, false);
Romain Guyb051e892010-09-28 19:09:36 -070012449 return mDisplayList;
12450 }
12451
Romain Guy38c2ece2012-05-24 14:20:56 -070012452 private void clearDisplayList() {
12453 if (mDisplayList != null) {
12454 mDisplayList.invalidate();
12455 mDisplayList.clear();
12456 }
12457 }
12458
Romain Guyb051e892010-09-28 19:09:36 -070012459 /**
Romain Guyfbd8f692009-06-26 14:51:58 -070012460 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012461 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012462 * @return A non-scaled bitmap representing this view or null if cache is disabled.
Joe Malin32736f02011-01-19 16:14:20 -080012463 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012464 * @see #getDrawingCache(boolean)
12465 */
12466 public Bitmap getDrawingCache() {
12467 return getDrawingCache(false);
12468 }
12469
12470 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012471 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12472 * is null when caching is disabled. If caching is enabled and the cache is not ready,
12473 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12474 * draw from the cache when the cache is enabled. To benefit from the cache, you must
12475 * request the drawing cache by calling this method and draw it on screen if the
12476 * returned bitmap is not null.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012477 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012478 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12479 * this method will create a bitmap of the same size as this view. Because this bitmap
12480 * will be drawn scaled by the parent ViewGroup, the result on screen might show
12481 * scaling artifacts. To avoid such artifacts, you should call this method by setting
12482 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12483 * size than the view. This implies that your application must be able to handle this
12484 * size.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012485 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012486 * @param autoScale Indicates whether the generated bitmap should be scaled based on
12487 * the current density of the screen when the application is in compatibility
12488 * mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012489 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012490 * @return A bitmap representing this view or null if cache is disabled.
Joe Malin32736f02011-01-19 16:14:20 -080012491 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012492 * @see #setDrawingCacheEnabled(boolean)
12493 * @see #isDrawingCacheEnabled()
Romain Guyfbd8f692009-06-26 14:51:58 -070012494 * @see #buildDrawingCache(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012495 * @see #destroyDrawingCache()
12496 */
Romain Guyfbd8f692009-06-26 14:51:58 -070012497 public Bitmap getDrawingCache(boolean autoScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012498 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12499 return null;
12500 }
12501 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012502 buildDrawingCache(autoScale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012503 }
Romain Guy02890fd2010-08-06 17:58:44 -070012504 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012505 }
12506
12507 /**
12508 * <p>Frees the resources used by the drawing cache. If you call
12509 * {@link #buildDrawingCache()} manually without calling
12510 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12511 * should cleanup the cache with this method afterwards.</p>
12512 *
12513 * @see #setDrawingCacheEnabled(boolean)
12514 * @see #buildDrawingCache()
12515 * @see #getDrawingCache()
12516 */
12517 public void destroyDrawingCache() {
12518 if (mDrawingCache != null) {
Romain Guy02890fd2010-08-06 17:58:44 -070012519 mDrawingCache.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012520 mDrawingCache = null;
12521 }
Romain Guyfbd8f692009-06-26 14:51:58 -070012522 if (mUnscaledDrawingCache != null) {
Romain Guy02890fd2010-08-06 17:58:44 -070012523 mUnscaledDrawingCache.recycle();
Romain Guyfbd8f692009-06-26 14:51:58 -070012524 mUnscaledDrawingCache = null;
12525 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012526 }
12527
12528 /**
12529 * Setting a solid background color for the drawing cache's bitmaps will improve
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070012530 * performance and memory usage. Note, though that this should only be used if this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 * view will always be drawn on top of a solid color.
12532 *
12533 * @param color The background color to use for the drawing cache's bitmap
12534 *
12535 * @see #setDrawingCacheEnabled(boolean)
12536 * @see #buildDrawingCache()
12537 * @see #getDrawingCache()
12538 */
12539 public void setDrawingCacheBackgroundColor(int color) {
Romain Guy52e2ef82010-01-14 12:11:48 -080012540 if (color != mDrawingCacheBackgroundColor) {
12541 mDrawingCacheBackgroundColor = color;
Dianne Hackborn4702a852012-08-17 15:18:29 -070012542 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
Romain Guy52e2ef82010-01-14 12:11:48 -080012543 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012544 }
12545
12546 /**
12547 * @see #setDrawingCacheBackgroundColor(int)
12548 *
12549 * @return The background color to used for the drawing cache's bitmap
12550 */
12551 public int getDrawingCacheBackgroundColor() {
12552 return mDrawingCacheBackgroundColor;
12553 }
12554
12555 /**
Romain Guyfbd8f692009-06-26 14:51:58 -070012556 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012557 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012558 * @see #buildDrawingCache(boolean)
12559 */
12560 public void buildDrawingCache() {
12561 buildDrawingCache(false);
12562 }
Gilles Debunne2ed2eac2011-02-24 16:29:48 -080012563
Romain Guyfbd8f692009-06-26 14:51:58 -070012564 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012565 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12566 *
12567 * <p>If you call {@link #buildDrawingCache()} manually without calling
12568 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12569 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012570 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012571 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12572 * this method will create a bitmap of the same size as this view. Because this bitmap
12573 * will be drawn scaled by the parent ViewGroup, the result on screen might show
12574 * scaling artifacts. To avoid such artifacts, you should call this method by setting
12575 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12576 * size than the view. This implies that your application must be able to handle this
12577 * size.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012578 *
Romain Guy0d9275e2010-10-26 14:22:30 -070012579 * <p>You should avoid calling this method when hardware acceleration is enabled. If
12580 * you do not need the drawing cache bitmap, calling this method will increase memory
Joe Malin32736f02011-01-19 16:14:20 -080012581 * usage and cause the view to be rendered in software once, thus negatively impacting
Romain Guy0d9275e2010-10-26 14:22:30 -070012582 * performance.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012583 *
12584 * @see #getDrawingCache()
12585 * @see #destroyDrawingCache()
12586 */
Romain Guyfbd8f692009-06-26 14:51:58 -070012587 public void buildDrawingCache(boolean autoScale) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012588 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
Romain Guy02890fd2010-08-06 17:58:44 -070012589 mDrawingCache == null : mUnscaledDrawingCache == null)) {
Romain Guy0211a0a2011-02-14 16:34:59 -080012590 mCachingFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012591
Romain Guy8506ab42009-06-11 17:35:47 -070012592 int width = mRight - mLeft;
12593 int height = mBottom - mTop;
12594
12595 final AttachInfo attachInfo = mAttachInfo;
Romain Guye1123222009-06-29 14:24:56 -070012596 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
Romain Guyfbd8f692009-06-26 14:51:58 -070012597
Romain Guye1123222009-06-29 14:24:56 -070012598 if (autoScale && scalingRequired) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012599 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
12600 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
Romain Guy8506ab42009-06-11 17:35:47 -070012601 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012602
12603 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
Romain Guy35b38ce2009-10-07 13:38:55 -070012604 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
Adam Powell26153a32010-11-08 15:22:27 -080012605 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012606
Chris Craik10e9d1d2012-09-06 14:42:44 -070012607 final int projectedBitmapSize = width * height * (opaque && !use32BitCache ? 2 : 4);
12608 final int drawingCacheSize =
12609 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize();
12610 if (width <= 0 || height <= 0 || projectedBitmapSize > drawingCacheSize) {
Chris Craik3667aa32012-09-06 14:56:39 -070012611 if (width > 0 && height > 0) {
12612 Log.w(VIEW_LOG_TAG, "View too large to fit into drawing cache, needs "
12613 + projectedBitmapSize + " bytes, only "
12614 + drawingCacheSize + " available");
12615 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012616 destroyDrawingCache();
Romain Guy0211a0a2011-02-14 16:34:59 -080012617 mCachingFailed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012618 return;
12619 }
12620
12621 boolean clear = true;
Romain Guy02890fd2010-08-06 17:58:44 -070012622 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012623
12624 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012625 Bitmap.Config quality;
12626 if (!opaque) {
Romain Guy676b1732011-02-14 14:45:33 -080012627 // Never pick ARGB_4444 because it looks awful
12628 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012629 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
12630 case DRAWING_CACHE_QUALITY_AUTO:
12631 quality = Bitmap.Config.ARGB_8888;
12632 break;
12633 case DRAWING_CACHE_QUALITY_LOW:
Romain Guy676b1732011-02-14 14:45:33 -080012634 quality = Bitmap.Config.ARGB_8888;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012635 break;
12636 case DRAWING_CACHE_QUALITY_HIGH:
12637 quality = Bitmap.Config.ARGB_8888;
12638 break;
12639 default:
12640 quality = Bitmap.Config.ARGB_8888;
12641 break;
12642 }
12643 } else {
Romain Guy35b38ce2009-10-07 13:38:55 -070012644 // Optimization for translucent windows
12645 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
Adam Powell26153a32010-11-08 15:22:27 -080012646 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012647 }
12648
12649 // Try to cleanup memory
12650 if (bitmap != null) bitmap.recycle();
12651
12652 try {
Dianne Hackborndde331c2012-08-03 14:01:57 -070012653 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12654 width, height, quality);
Dianne Hackborn11ea3342009-07-22 21:48:55 -070012655 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
Romain Guyfbd8f692009-06-26 14:51:58 -070012656 if (autoScale) {
Romain Guy02890fd2010-08-06 17:58:44 -070012657 mDrawingCache = bitmap;
Romain Guyfbd8f692009-06-26 14:51:58 -070012658 } else {
Romain Guy02890fd2010-08-06 17:58:44 -070012659 mUnscaledDrawingCache = bitmap;
Romain Guyfbd8f692009-06-26 14:51:58 -070012660 }
Adam Powell26153a32010-11-08 15:22:27 -080012661 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012662 } catch (OutOfMemoryError e) {
12663 // If there is not enough memory to create the bitmap cache, just
12664 // ignore the issue as bitmap caches are not required to draw the
12665 // view hierarchy
Romain Guyfbd8f692009-06-26 14:51:58 -070012666 if (autoScale) {
12667 mDrawingCache = null;
12668 } else {
12669 mUnscaledDrawingCache = null;
12670 }
Romain Guy0211a0a2011-02-14 16:34:59 -080012671 mCachingFailed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012672 return;
12673 }
12674
12675 clear = drawingCacheBackgroundColor != 0;
12676 }
12677
12678 Canvas canvas;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012679 if (attachInfo != null) {
12680 canvas = attachInfo.mCanvas;
12681 if (canvas == null) {
12682 canvas = new Canvas();
12683 }
12684 canvas.setBitmap(bitmap);
12685 // Temporarily clobber the cached Canvas in case one of our children
12686 // is also using a drawing cache. Without this, the children would
12687 // steal the canvas by attaching their own bitmap to it and bad, bad
12688 // thing would happen (invisible views, corrupted drawings, etc.)
12689 attachInfo.mCanvas = null;
12690 } else {
12691 // This case should hopefully never or seldom happen
12692 canvas = new Canvas(bitmap);
12693 }
12694
12695 if (clear) {
12696 bitmap.eraseColor(drawingCacheBackgroundColor);
12697 }
12698
12699 computeScroll();
12700 final int restoreCount = canvas.save();
Joe Malin32736f02011-01-19 16:14:20 -080012701
Romain Guye1123222009-06-29 14:24:56 -070012702 if (autoScale && scalingRequired) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012703 final float scale = attachInfo.mApplicationScale;
12704 canvas.scale(scale, scale);
12705 }
Joe Malin32736f02011-01-19 16:14:20 -080012706
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012707 canvas.translate(-mScrollX, -mScrollY);
12708
Dianne Hackborn4702a852012-08-17 15:18:29 -070012709 mPrivateFlags |= PFLAG_DRAWN;
Romain Guy171c5922011-01-06 10:04:23 -080012710 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
12711 mLayerType != LAYER_TYPE_NONE) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012712 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
Romain Guy0d9275e2010-10-26 14:22:30 -070012713 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012714
12715 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070012716 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12717 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012718 dispatchDraw(canvas);
12719 } else {
12720 draw(canvas);
12721 }
12722
12723 canvas.restoreToCount(restoreCount);
Dianne Hackborn6311d0a2011-08-02 16:37:58 -070012724 canvas.setBitmap(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012725
12726 if (attachInfo != null) {
12727 // Restore the cached Canvas for our siblings
12728 attachInfo.mCanvas = canvas;
12729 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012730 }
12731 }
12732
12733 /**
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012734 * Create a snapshot of the view into a bitmap. We should probably make
12735 * some form of this public, but should think about the API.
12736 */
Romain Guy223ff5c2010-03-02 17:07:47 -080012737 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012738 int width = mRight - mLeft;
12739 int height = mBottom - mTop;
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012740
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012741 final AttachInfo attachInfo = mAttachInfo;
Romain Guy8c11e312009-09-14 15:15:30 -070012742 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012743 width = (int) ((width * scale) + 0.5f);
12744 height = (int) ((height * scale) + 0.5f);
Joe Malin32736f02011-01-19 16:14:20 -080012745
Dianne Hackborndde331c2012-08-03 14:01:57 -070012746 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12747 width > 0 ? width : 1, height > 0 ? height : 1, quality);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012748 if (bitmap == null) {
12749 throw new OutOfMemoryError();
12750 }
12751
Romain Guyc529d8d2011-09-06 15:01:39 -070012752 Resources resources = getResources();
12753 if (resources != null) {
12754 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
12755 }
Joe Malin32736f02011-01-19 16:14:20 -080012756
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012757 Canvas canvas;
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012758 if (attachInfo != null) {
12759 canvas = attachInfo.mCanvas;
12760 if (canvas == null) {
12761 canvas = new Canvas();
12762 }
12763 canvas.setBitmap(bitmap);
12764 // Temporarily clobber the cached Canvas in case one of our children
12765 // is also using a drawing cache. Without this, the children would
12766 // steal the canvas by attaching their own bitmap to it and bad, bad
12767 // things would happen (invisible views, corrupted drawings, etc.)
12768 attachInfo.mCanvas = null;
12769 } else {
12770 // This case should hopefully never or seldom happen
12771 canvas = new Canvas(bitmap);
12772 }
12773
Romain Guy5bcdff42009-05-14 21:27:18 -070012774 if ((backgroundColor & 0xff000000) != 0) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012775 bitmap.eraseColor(backgroundColor);
12776 }
12777
12778 computeScroll();
12779 final int restoreCount = canvas.save();
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012780 canvas.scale(scale, scale);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012781 canvas.translate(-mScrollX, -mScrollY);
12782
Romain Guy5bcdff42009-05-14 21:27:18 -070012783 // Temporarily remove the dirty mask
12784 int flags = mPrivateFlags;
Dianne Hackborn4702a852012-08-17 15:18:29 -070012785 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Romain Guy5bcdff42009-05-14 21:27:18 -070012786
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012787 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070012788 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012789 dispatchDraw(canvas);
12790 } else {
12791 draw(canvas);
12792 }
12793
Romain Guy5bcdff42009-05-14 21:27:18 -070012794 mPrivateFlags = flags;
12795
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012796 canvas.restoreToCount(restoreCount);
Dianne Hackborn6311d0a2011-08-02 16:37:58 -070012797 canvas.setBitmap(null);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012798
12799 if (attachInfo != null) {
12800 // Restore the cached Canvas for our siblings
12801 attachInfo.mCanvas = canvas;
12802 }
Romain Guy8506ab42009-06-11 17:35:47 -070012803
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012804 return bitmap;
12805 }
12806
12807 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012808 * Indicates whether this View is currently in edit mode. A View is usually
12809 * in edit mode when displayed within a developer tool. For instance, if
12810 * this View is being drawn by a visual user interface builder, this method
12811 * should return true.
12812 *
12813 * Subclasses should check the return value of this method to provide
12814 * different behaviors if their normal behavior might interfere with the
12815 * host environment. For instance: the class spawns a thread in its
12816 * constructor, the drawing code relies on device-specific features, etc.
12817 *
12818 * This method is usually checked in the drawing code of custom widgets.
12819 *
12820 * @return True if this View is in edit mode, false otherwise.
12821 */
12822 public boolean isInEditMode() {
12823 return false;
12824 }
12825
12826 /**
12827 * If the View draws content inside its padding and enables fading edges,
12828 * it needs to support padding offsets. Padding offsets are added to the
12829 * fading edges to extend the length of the fade so that it covers pixels
12830 * drawn inside the padding.
12831 *
12832 * Subclasses of this class should override this method if they need
12833 * to draw content inside the padding.
12834 *
12835 * @return True if padding offset must be applied, false otherwise.
12836 *
12837 * @see #getLeftPaddingOffset()
12838 * @see #getRightPaddingOffset()
12839 * @see #getTopPaddingOffset()
12840 * @see #getBottomPaddingOffset()
12841 *
12842 * @since CURRENT
12843 */
12844 protected boolean isPaddingOffsetRequired() {
12845 return false;
12846 }
12847
12848 /**
12849 * Amount by which to extend the left fading region. Called only when
12850 * {@link #isPaddingOffsetRequired()} returns true.
12851 *
12852 * @return The left padding offset in pixels.
12853 *
12854 * @see #isPaddingOffsetRequired()
12855 *
12856 * @since CURRENT
12857 */
12858 protected int getLeftPaddingOffset() {
12859 return 0;
12860 }
12861
12862 /**
12863 * Amount by which to extend the right fading region. Called only when
12864 * {@link #isPaddingOffsetRequired()} returns true.
12865 *
12866 * @return The right padding offset in pixels.
12867 *
12868 * @see #isPaddingOffsetRequired()
12869 *
12870 * @since CURRENT
12871 */
12872 protected int getRightPaddingOffset() {
12873 return 0;
12874 }
12875
12876 /**
12877 * Amount by which to extend the top fading region. Called only when
12878 * {@link #isPaddingOffsetRequired()} returns true.
12879 *
12880 * @return The top padding offset in pixels.
12881 *
12882 * @see #isPaddingOffsetRequired()
12883 *
12884 * @since CURRENT
12885 */
12886 protected int getTopPaddingOffset() {
12887 return 0;
12888 }
12889
12890 /**
12891 * Amount by which to extend the bottom fading region. Called only when
12892 * {@link #isPaddingOffsetRequired()} returns true.
12893 *
12894 * @return The bottom padding offset in pixels.
12895 *
12896 * @see #isPaddingOffsetRequired()
12897 *
12898 * @since CURRENT
12899 */
12900 protected int getBottomPaddingOffset() {
12901 return 0;
12902 }
12903
12904 /**
Romain Guyf2fc4602011-07-19 15:20:03 -070012905 * @hide
12906 * @param offsetRequired
12907 */
12908 protected int getFadeTop(boolean offsetRequired) {
12909 int top = mPaddingTop;
12910 if (offsetRequired) top += getTopPaddingOffset();
12911 return top;
12912 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012913
Romain Guyf2fc4602011-07-19 15:20:03 -070012914 /**
12915 * @hide
12916 * @param offsetRequired
12917 */
12918 protected int getFadeHeight(boolean offsetRequired) {
12919 int padding = mPaddingTop;
Philip Milne6c8ea062012-04-03 17:38:43 -070012920 if (offsetRequired) padding += getTopPaddingOffset();
Romain Guyf2fc4602011-07-19 15:20:03 -070012921 return mBottom - mTop - mPaddingBottom - padding;
12922 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012923
Romain Guyf2fc4602011-07-19 15:20:03 -070012924 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090012925 * <p>Indicates whether this view is attached to a hardware accelerated
Romain Guy2bffd262010-09-12 17:40:02 -070012926 * window or not.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012927 *
Romain Guy2bffd262010-09-12 17:40:02 -070012928 * <p>Even if this method returns true, it does not mean that every call
12929 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
12930 * accelerated {@link android.graphics.Canvas}. For instance, if this view
Ken Wakasaf76a50c2012-03-09 19:56:35 +090012931 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
Romain Guy2bffd262010-09-12 17:40:02 -070012932 * window is hardware accelerated,
12933 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
12934 * return false, and this method will return true.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012935 *
Romain Guy2bffd262010-09-12 17:40:02 -070012936 * @return True if the view is attached to a window and the window is
12937 * hardware accelerated; false in any other case.
12938 */
12939 public boolean isHardwareAccelerated() {
12940 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
12941 }
Joe Malin32736f02011-01-19 16:14:20 -080012942
Romain Guy2bffd262010-09-12 17:40:02 -070012943 /**
Chet Haasebcca79a2012-02-14 08:45:14 -080012944 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
12945 * case of an active Animation being run on the view.
12946 */
12947 private boolean drawAnimation(ViewGroup parent, long drawingTime,
12948 Animation a, boolean scalingRequired) {
12949 Transformation invalidationTransform;
12950 final int flags = parent.mGroupFlags;
12951 final boolean initialized = a.isInitialized();
12952 if (!initialized) {
Chet Haase1fb8a9e2012-04-19 09:22:34 -070012953 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
Chet Haasebcca79a2012-02-14 08:45:14 -080012954 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
Romain Guy393a52c2012-05-22 20:21:08 -070012955 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
Chet Haasebcca79a2012-02-14 08:45:14 -080012956 onAnimationStart();
12957 }
12958
12959 boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
12960 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
12961 if (parent.mInvalidationTransformation == null) {
12962 parent.mInvalidationTransformation = new Transformation();
12963 }
12964 invalidationTransform = parent.mInvalidationTransformation;
12965 a.getTransformation(drawingTime, invalidationTransform, 1f);
12966 } else {
12967 invalidationTransform = parent.mChildTransformation;
12968 }
Romain Guy393a52c2012-05-22 20:21:08 -070012969
Chet Haasebcca79a2012-02-14 08:45:14 -080012970 if (more) {
12971 if (!a.willChangeBounds()) {
Romain Guyf0af1d52012-07-11 18:31:21 -070012972 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
12973 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
12974 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
12975 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
Chet Haasebcca79a2012-02-14 08:45:14 -080012976 // The child need to draw an animation, potentially offscreen, so
12977 // make sure we do not cancel invalidate requests
Dianne Hackborn4702a852012-08-17 15:18:29 -070012978 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
Chet Haasebcca79a2012-02-14 08:45:14 -080012979 parent.invalidate(mLeft, mTop, mRight, mBottom);
12980 }
12981 } else {
12982 if (parent.mInvalidateRegion == null) {
12983 parent.mInvalidateRegion = new RectF();
12984 }
12985 final RectF region = parent.mInvalidateRegion;
12986 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
12987 invalidationTransform);
12988
12989 // The child need to draw an animation, potentially offscreen, so
12990 // make sure we do not cancel invalidate requests
Dianne Hackborn4702a852012-08-17 15:18:29 -070012991 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
Chet Haasebcca79a2012-02-14 08:45:14 -080012992
12993 final int left = mLeft + (int) region.left;
12994 final int top = mTop + (int) region.top;
12995 parent.invalidate(left, top, left + (int) (region.width() + .5f),
12996 top + (int) (region.height() + .5f));
12997 }
12998 }
12999 return more;
13000 }
13001
Chet Haasea1cff502012-02-21 13:43:44 -080013002 /**
13003 * This method is called by getDisplayList() when a display list is created or re-rendered.
13004 * It sets or resets the current value of all properties on that display list (resetting is
13005 * necessary when a display list is being re-created, because we need to make sure that
13006 * previously-set transform values
13007 */
13008 void setDisplayListProperties(DisplayList displayList) {
Chet Haase1271e2c2012-04-20 09:54:27 -070013009 if (displayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013010 displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
Chet Haasedb8c9a62012-03-21 18:54:18 -070013011 displayList.setHasOverlappingRendering(hasOverlappingRendering());
Chet Haasea1cff502012-02-21 13:43:44 -080013012 if (mParent instanceof ViewGroup) {
13013 displayList.setClipChildren(
13014 (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
13015 }
Chet Haase9420abd2012-03-29 16:28:32 -070013016 float alpha = 1;
13017 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
13018 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13019 ViewGroup parentVG = (ViewGroup) mParent;
13020 final boolean hasTransform =
13021 parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
13022 if (hasTransform) {
13023 Transformation transform = parentVG.mChildTransformation;
13024 final int transformType = parentVG.mChildTransformation.getTransformationType();
13025 if (transformType != Transformation.TYPE_IDENTITY) {
13026 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
13027 alpha = transform.getAlpha();
13028 }
13029 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
13030 displayList.setStaticMatrix(transform.getMatrix());
13031 }
13032 }
13033 }
Chet Haasea1cff502012-02-21 13:43:44 -080013034 }
13035 if (mTransformationInfo != null) {
Chet Haase9420abd2012-03-29 16:28:32 -070013036 alpha *= mTransformationInfo.mAlpha;
13037 if (alpha < 1) {
13038 final int multipliedAlpha = (int) (255 * alpha);
13039 if (onSetAlpha(multipliedAlpha)) {
13040 alpha = 1;
13041 }
13042 }
13043 displayList.setTransformationInfo(alpha,
Chet Haasea1cff502012-02-21 13:43:44 -080013044 mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
13045 mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
13046 mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
13047 mTransformationInfo.mScaleY);
Chet Haaseb85967b2012-03-26 14:37:51 -070013048 if (mTransformationInfo.mCamera == null) {
13049 mTransformationInfo.mCamera = new Camera();
13050 mTransformationInfo.matrix3D = new Matrix();
13051 }
13052 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
Dianne Hackborn4702a852012-08-17 15:18:29 -070013053 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
Chet Haasea1cff502012-02-21 13:43:44 -080013054 displayList.setPivotX(getPivotX());
13055 displayList.setPivotY(getPivotY());
13056 }
Chet Haase9420abd2012-03-29 16:28:32 -070013057 } else if (alpha < 1) {
13058 displayList.setAlpha(alpha);
Chet Haasea1cff502012-02-21 13:43:44 -080013059 }
13060 }
13061 }
13062
Chet Haasebcca79a2012-02-14 08:45:14 -080013063 /**
Chet Haase64a48c12012-02-13 16:33:29 -080013064 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
13065 * This draw() method is an implementation detail and is not intended to be overridden or
13066 * to be called from anywhere else other than ViewGroup.drawChild().
13067 */
13068 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
Chet Haase1271e2c2012-04-20 09:54:27 -070013069 boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
Chet Haase64a48c12012-02-13 16:33:29 -080013070 boolean more = false;
Chet Haase64a48c12012-02-13 16:33:29 -080013071 final boolean childHasIdentityMatrix = hasIdentityMatrix();
Chet Haase64a48c12012-02-13 16:33:29 -080013072 final int flags = parent.mGroupFlags;
13073
Chet Haasea1cff502012-02-21 13:43:44 -080013074 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
Chet Haase64a48c12012-02-13 16:33:29 -080013075 parent.mChildTransformation.clear();
Chet Haasea1cff502012-02-21 13:43:44 -080013076 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013077 }
13078
13079 Transformation transformToApply = null;
Chet Haase64a48c12012-02-13 16:33:29 -080013080 boolean concatMatrix = false;
13081
13082 boolean scalingRequired = false;
13083 boolean caching;
Michael Jurkaba649742012-06-28 19:12:58 -070013084 int layerType = getLayerType();
Chet Haase64a48c12012-02-13 16:33:29 -080013085
13086 final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
Chet Haasea1cff502012-02-21 13:43:44 -080013087 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
13088 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
Chet Haase64a48c12012-02-13 16:33:29 -080013089 caching = true;
Chet Haase9420abd2012-03-29 16:28:32 -070013090 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
Chet Haase64a48c12012-02-13 16:33:29 -080013091 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
13092 } else {
13093 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
13094 }
13095
Chet Haasebcca79a2012-02-14 08:45:14 -080013096 final Animation a = getAnimation();
Chet Haase64a48c12012-02-13 16:33:29 -080013097 if (a != null) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013098 more = drawAnimation(parent, drawingTime, a, scalingRequired);
Chet Haase64a48c12012-02-13 16:33:29 -080013099 concatMatrix = a.willChangeTransformationMatrix();
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013100 if (concatMatrix) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013101 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013102 }
Chet Haasebcca79a2012-02-14 08:45:14 -080013103 transformToApply = parent.mChildTransformation;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013104 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013105 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013106 mDisplayList != null) {
13107 // No longer animating: clear out old animation matrix
13108 mDisplayList.setAnimationMatrix(null);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013109 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013110 }
13111 if (!useDisplayListProperties &&
13112 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13113 final boolean hasTransform =
13114 parent.getChildStaticTransformation(this, parent.mChildTransformation);
13115 if (hasTransform) {
13116 final int transformType = parent.mChildTransformation.getTransformationType();
13117 transformToApply = transformType != Transformation.TYPE_IDENTITY ?
13118 parent.mChildTransformation : null;
13119 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
13120 }
Chet Haase64a48c12012-02-13 16:33:29 -080013121 }
13122 }
13123
13124 concatMatrix |= !childHasIdentityMatrix;
13125
13126 // Sets the flag as early as possible to allow draw() implementations
13127 // to call invalidate() successfully when doing animations
Dianne Hackborn4702a852012-08-17 15:18:29 -070013128 mPrivateFlags |= PFLAG_DRAWN;
Chet Haase64a48c12012-02-13 16:33:29 -080013129
Romain Guyfbb43212012-08-30 15:19:27 -070013130 if (!concatMatrix &&
13131 (flags & (ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS |
13132 ViewGroup.FLAG_CLIP_CHILDREN)) == ViewGroup.FLAG_CLIP_CHILDREN &&
Chet Haase599913d2012-07-23 16:22:05 -070013133 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
Dianne Hackborn4702a852012-08-17 15:18:29 -070013134 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
13135 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
Chet Haase64a48c12012-02-13 16:33:29 -080013136 return more;
13137 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070013138 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
Chet Haase64a48c12012-02-13 16:33:29 -080013139
13140 if (hardwareAccelerated) {
13141 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
13142 // retain the flag's value temporarily in the mRecreateDisplayList flag
Dianne Hackborn4702a852012-08-17 15:18:29 -070013143 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
13144 mPrivateFlags &= ~PFLAG_INVALIDATED;
Chet Haase64a48c12012-02-13 16:33:29 -080013145 }
13146
Chet Haase64a48c12012-02-13 16:33:29 -080013147 DisplayList displayList = null;
13148 Bitmap cache = null;
13149 boolean hasDisplayList = false;
13150 if (caching) {
13151 if (!hardwareAccelerated) {
13152 if (layerType != LAYER_TYPE_NONE) {
13153 layerType = LAYER_TYPE_SOFTWARE;
13154 buildDrawingCache(true);
13155 }
13156 cache = getDrawingCache(true);
13157 } else {
13158 switch (layerType) {
13159 case LAYER_TYPE_SOFTWARE:
Chet Haaseb85967b2012-03-26 14:37:51 -070013160 if (useDisplayListProperties) {
13161 hasDisplayList = canHaveDisplayList();
13162 } else {
13163 buildDrawingCache(true);
13164 cache = getDrawingCache(true);
13165 }
Chet Haase64a48c12012-02-13 16:33:29 -080013166 break;
Chet Haasea1cff502012-02-21 13:43:44 -080013167 case LAYER_TYPE_HARDWARE:
13168 if (useDisplayListProperties) {
13169 hasDisplayList = canHaveDisplayList();
13170 }
13171 break;
Chet Haase64a48c12012-02-13 16:33:29 -080013172 case LAYER_TYPE_NONE:
13173 // Delay getting the display list until animation-driven alpha values are
13174 // set up and possibly passed on to the view
13175 hasDisplayList = canHaveDisplayList();
13176 break;
13177 }
13178 }
13179 }
Chet Haasea1cff502012-02-21 13:43:44 -080013180 useDisplayListProperties &= hasDisplayList;
Chet Haase9420abd2012-03-29 16:28:32 -070013181 if (useDisplayListProperties) {
13182 displayList = getDisplayList();
13183 if (!displayList.isValid()) {
13184 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13185 // to getDisplayList(), the display list will be marked invalid and we should not
13186 // try to use it again.
13187 displayList = null;
13188 hasDisplayList = false;
13189 useDisplayListProperties = false;
13190 }
13191 }
Chet Haase64a48c12012-02-13 16:33:29 -080013192
Chet Haase526057b2012-07-12 17:50:41 -070013193 int sx = 0;
13194 int sy = 0;
13195 if (!hasDisplayList) {
13196 computeScroll();
13197 sx = mScrollX;
13198 sy = mScrollY;
13199 }
13200
Chet Haase64a48c12012-02-13 16:33:29 -080013201 final boolean hasNoCache = cache == null || hasDisplayList;
13202 final boolean offsetForScroll = cache == null && !hasDisplayList &&
13203 layerType != LAYER_TYPE_HARDWARE;
13204
Chet Haasea1cff502012-02-21 13:43:44 -080013205 int restoreTo = -1;
Chet Haase89b7f2e2012-03-21 11:15:37 -070013206 if (!useDisplayListProperties || transformToApply != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013207 restoreTo = canvas.save();
13208 }
Chet Haase64a48c12012-02-13 16:33:29 -080013209 if (offsetForScroll) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013210 canvas.translate(mLeft - sx, mTop - sy);
Chet Haase64a48c12012-02-13 16:33:29 -080013211 } else {
Chet Haasea1cff502012-02-21 13:43:44 -080013212 if (!useDisplayListProperties) {
13213 canvas.translate(mLeft, mTop);
13214 }
Chet Haase64a48c12012-02-13 16:33:29 -080013215 if (scalingRequired) {
Chet Haasea1cff502012-02-21 13:43:44 -080013216 if (useDisplayListProperties) {
Chet Haase9420abd2012-03-29 16:28:32 -070013217 // TODO: Might not need this if we put everything inside the DL
Chet Haasea1cff502012-02-21 13:43:44 -080013218 restoreTo = canvas.save();
13219 }
Chet Haase64a48c12012-02-13 16:33:29 -080013220 // mAttachInfo cannot be null, otherwise scalingRequired == false
13221 final float scale = 1.0f / mAttachInfo.mApplicationScale;
13222 canvas.scale(scale, scale);
13223 }
13224 }
13225
Chet Haasea1cff502012-02-21 13:43:44 -080013226 float alpha = useDisplayListProperties ? 1 : getAlpha();
Chet Haase21433372012-06-05 07:54:09 -070013227 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
Dianne Hackborn4702a852012-08-17 15:18:29 -070013228 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
Chet Haase64a48c12012-02-13 16:33:29 -080013229 if (transformToApply != null || !childHasIdentityMatrix) {
13230 int transX = 0;
13231 int transY = 0;
13232
13233 if (offsetForScroll) {
13234 transX = -sx;
13235 transY = -sy;
13236 }
13237
13238 if (transformToApply != null) {
13239 if (concatMatrix) {
Chet Haase9420abd2012-03-29 16:28:32 -070013240 if (useDisplayListProperties) {
13241 displayList.setAnimationMatrix(transformToApply.getMatrix());
13242 } else {
13243 // Undo the scroll translation, apply the transformation matrix,
13244 // then redo the scroll translate to get the correct result.
13245 canvas.translate(-transX, -transY);
13246 canvas.concat(transformToApply.getMatrix());
13247 canvas.translate(transX, transY);
13248 }
Chet Haasea1cff502012-02-21 13:43:44 -080013249 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013250 }
13251
13252 float transformAlpha = transformToApply.getAlpha();
Chet Haase9420abd2012-03-29 16:28:32 -070013253 if (transformAlpha < 1) {
Chet Haase21433372012-06-05 07:54:09 -070013254 alpha *= transformAlpha;
Chet Haasea1cff502012-02-21 13:43:44 -080013255 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013256 }
13257 }
13258
Chet Haasea1cff502012-02-21 13:43:44 -080013259 if (!childHasIdentityMatrix && !useDisplayListProperties) {
Chet Haase64a48c12012-02-13 16:33:29 -080013260 canvas.translate(-transX, -transY);
13261 canvas.concat(getMatrix());
13262 canvas.translate(transX, transY);
13263 }
13264 }
13265
Chet Haase21433372012-06-05 07:54:09 -070013266 // Deal with alpha if it is or used to be <1
13267 if (alpha < 1 ||
Dianne Hackborn4702a852012-08-17 15:18:29 -070013268 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
Chet Haase21433372012-06-05 07:54:09 -070013269 if (alpha < 1) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013270 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
Chet Haase21433372012-06-05 07:54:09 -070013271 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013272 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
Chet Haase21433372012-06-05 07:54:09 -070013273 }
Chet Haasea1cff502012-02-21 13:43:44 -080013274 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013275 if (hasNoCache) {
13276 final int multipliedAlpha = (int) (255 * alpha);
13277 if (!onSetAlpha(multipliedAlpha)) {
13278 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
Chet Haasea1cff502012-02-21 13:43:44 -080013279 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
Chet Haase64a48c12012-02-13 16:33:29 -080013280 layerType != LAYER_TYPE_NONE) {
13281 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13282 }
Chet Haase9420abd2012-03-29 16:28:32 -070013283 if (useDisplayListProperties) {
13284 displayList.setAlpha(alpha * getAlpha());
13285 } else if (layerType == LAYER_TYPE_NONE) {
Chet Haase89b7f2e2012-03-21 11:15:37 -070013286 final int scrollX = hasDisplayList ? 0 : sx;
13287 final int scrollY = hasDisplayList ? 0 : sy;
13288 canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13289 scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
Chet Haase64a48c12012-02-13 16:33:29 -080013290 }
13291 } else {
13292 // Alpha is handled by the child directly, clobber the layer's alpha
Dianne Hackborn4702a852012-08-17 15:18:29 -070013293 mPrivateFlags |= PFLAG_ALPHA_SET;
Chet Haase64a48c12012-02-13 16:33:29 -080013294 }
13295 }
13296 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070013297 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
Chet Haase64a48c12012-02-13 16:33:29 -080013298 onSetAlpha(255);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013299 mPrivateFlags &= ~PFLAG_ALPHA_SET;
Chet Haase64a48c12012-02-13 16:33:29 -080013300 }
13301
Chet Haasea1cff502012-02-21 13:43:44 -080013302 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13303 !useDisplayListProperties) {
Chet Haase64a48c12012-02-13 16:33:29 -080013304 if (offsetForScroll) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013305 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
Chet Haase64a48c12012-02-13 16:33:29 -080013306 } else {
13307 if (!scalingRequired || cache == null) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013308 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
Chet Haase64a48c12012-02-13 16:33:29 -080013309 } else {
13310 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13311 }
13312 }
13313 }
13314
Chet Haase9420abd2012-03-29 16:28:32 -070013315 if (!useDisplayListProperties && hasDisplayList) {
Chet Haase64a48c12012-02-13 16:33:29 -080013316 displayList = getDisplayList();
13317 if (!displayList.isValid()) {
13318 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13319 // to getDisplayList(), the display list will be marked invalid and we should not
13320 // try to use it again.
13321 displayList = null;
13322 hasDisplayList = false;
13323 }
13324 }
13325
13326 if (hasNoCache) {
13327 boolean layerRendered = false;
Chet Haasea1cff502012-02-21 13:43:44 -080013328 if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
Michael Jurka7e52caf2012-03-06 15:57:06 -080013329 final HardwareLayer layer = getHardwareLayer();
Chet Haase64a48c12012-02-13 16:33:29 -080013330 if (layer != null && layer.isValid()) {
13331 mLayerPaint.setAlpha((int) (alpha * 255));
13332 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13333 layerRendered = true;
13334 } else {
13335 final int scrollX = hasDisplayList ? 0 : sx;
13336 final int scrollY = hasDisplayList ? 0 : sy;
13337 canvas.saveLayer(scrollX, scrollY,
Chet Haasebcca79a2012-02-14 08:45:14 -080013338 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
Chet Haase64a48c12012-02-13 16:33:29 -080013339 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13340 }
13341 }
13342
13343 if (!layerRendered) {
13344 if (!hasDisplayList) {
13345 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070013346 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13347 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haase64a48c12012-02-13 16:33:29 -080013348 dispatchDraw(canvas);
13349 } else {
13350 draw(canvas);
13351 }
13352 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013353 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haase1271e2c2012-04-20 09:54:27 -070013354 ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
Chet Haase64a48c12012-02-13 16:33:29 -080013355 }
13356 }
13357 } else if (cache != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013358 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haase64a48c12012-02-13 16:33:29 -080013359 Paint cachePaint;
13360
13361 if (layerType == LAYER_TYPE_NONE) {
13362 cachePaint = parent.mCachePaint;
13363 if (cachePaint == null) {
13364 cachePaint = new Paint();
13365 cachePaint.setDither(false);
13366 parent.mCachePaint = cachePaint;
13367 }
Chet Haase9420abd2012-03-29 16:28:32 -070013368 if (alpha < 1) {
Chet Haase64a48c12012-02-13 16:33:29 -080013369 cachePaint.setAlpha((int) (alpha * 255));
Chet Haasea1cff502012-02-21 13:43:44 -080013370 parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13371 } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
Chet Haase64a48c12012-02-13 16:33:29 -080013372 cachePaint.setAlpha(255);
Chet Haasea1cff502012-02-21 13:43:44 -080013373 parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
Chet Haase64a48c12012-02-13 16:33:29 -080013374 }
13375 } else {
13376 cachePaint = mLayerPaint;
13377 cachePaint.setAlpha((int) (alpha * 255));
13378 }
13379 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13380 }
13381
Chet Haasea1cff502012-02-21 13:43:44 -080013382 if (restoreTo >= 0) {
13383 canvas.restoreToCount(restoreTo);
13384 }
Chet Haase64a48c12012-02-13 16:33:29 -080013385
13386 if (a != null && !more) {
13387 if (!hardwareAccelerated && !a.getFillAfter()) {
13388 onSetAlpha(255);
13389 }
13390 parent.finishAnimatingView(this, a);
13391 }
13392
13393 if (more && hardwareAccelerated) {
13394 // invalidation is the trigger to recreate display lists, so if we're using
13395 // display lists to render, force an invalidate to allow the animation to
13396 // continue drawing another frame
13397 parent.invalidate(true);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013398 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
Chet Haase64a48c12012-02-13 16:33:29 -080013399 // alpha animations should cause the child to recreate its display list
13400 invalidate(true);
13401 }
13402 }
13403
13404 mRecreateDisplayList = false;
13405
13406 return more;
13407 }
13408
13409 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013410 * Manually render this view (and all of its children) to the given Canvas.
13411 * The view must have already done a full layout before this function is
Romain Guy5c22a8c2011-05-13 11:48:45 -070013412 * called. When implementing a view, implement
13413 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13414 * If you do need to override this method, call the superclass version.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 *
13416 * @param canvas The Canvas to which the View is rendered.
13417 */
13418 public void draw(Canvas canvas) {
Romain Guy5bcdff42009-05-14 21:27:18 -070013419 final int privateFlags = mPrivateFlags;
Dianne Hackborn4702a852012-08-17 15:18:29 -070013420 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
Romain Guy5bcdff42009-05-14 21:27:18 -070013421 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013422 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
Romain Guy24443ea2009-05-11 11:56:30 -070013423
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013424 /*
13425 * Draw traversal performs several drawing steps which must be executed
13426 * in the appropriate order:
13427 *
13428 * 1. Draw the background
13429 * 2. If necessary, save the canvas' layers to prepare for fading
13430 * 3. Draw view's content
13431 * 4. Draw children
13432 * 5. If necessary, draw the fading edges and restore layers
13433 * 6. Draw decorations (scrollbars for instance)
13434 */
13435
13436 // Step 1, draw the background, if needed
13437 int saveCount;
13438
Romain Guy24443ea2009-05-11 11:56:30 -070013439 if (!dirtyOpaque) {
Philip Milne6c8ea062012-04-03 17:38:43 -070013440 final Drawable background = mBackground;
Romain Guy24443ea2009-05-11 11:56:30 -070013441 if (background != null) {
13442 final int scrollX = mScrollX;
13443 final int scrollY = mScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013444
Romain Guy24443ea2009-05-11 11:56:30 -070013445 if (mBackgroundSizeChanged) {
13446 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
13447 mBackgroundSizeChanged = false;
13448 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013449
Romain Guy24443ea2009-05-11 11:56:30 -070013450 if ((scrollX | scrollY) == 0) {
13451 background.draw(canvas);
13452 } else {
13453 canvas.translate(scrollX, scrollY);
13454 background.draw(canvas);
13455 canvas.translate(-scrollX, -scrollY);
13456 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013457 }
13458 }
13459
13460 // skip step 2 & 5 if possible (common case)
13461 final int viewFlags = mViewFlags;
13462 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13463 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13464 if (!verticalEdges && !horizontalEdges) {
13465 // Step 3, draw the content
Romain Guy24443ea2009-05-11 11:56:30 -070013466 if (!dirtyOpaque) onDraw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013467
13468 // Step 4, draw the children
13469 dispatchDraw(canvas);
13470
13471 // Step 6, draw decorations (scrollbars)
13472 onDrawScrollBars(canvas);
13473
13474 // we're done...
13475 return;
13476 }
13477
13478 /*
13479 * Here we do the full fledged routine...
13480 * (this is an uncommon case where speed matters less,
13481 * this is why we repeat some of the tests that have been
13482 * done above)
13483 */
13484
13485 boolean drawTop = false;
13486 boolean drawBottom = false;
13487 boolean drawLeft = false;
13488 boolean drawRight = false;
13489
13490 float topFadeStrength = 0.0f;
13491 float bottomFadeStrength = 0.0f;
13492 float leftFadeStrength = 0.0f;
13493 float rightFadeStrength = 0.0f;
13494
13495 // Step 2, save the canvas' layers
13496 int paddingLeft = mPaddingLeft;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013497
13498 final boolean offsetRequired = isPaddingOffsetRequired();
13499 if (offsetRequired) {
13500 paddingLeft += getLeftPaddingOffset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013501 }
13502
13503 int left = mScrollX + paddingLeft;
13504 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
Romain Guyf2fc4602011-07-19 15:20:03 -070013505 int top = mScrollY + getFadeTop(offsetRequired);
13506 int bottom = top + getFadeHeight(offsetRequired);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013507
13508 if (offsetRequired) {
13509 right += getRightPaddingOffset();
13510 bottom += getBottomPaddingOffset();
13511 }
13512
13513 final ScrollabilityCache scrollabilityCache = mScrollCache;
Philip Milne6c8ea062012-04-03 17:38:43 -070013514 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013515 int length = (int) fadeHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013516
13517 // clip the fade length if top and bottom fades overlap
13518 // overlapping fades produce odd-looking artifacts
13519 if (verticalEdges && (top + length > bottom - length)) {
13520 length = (bottom - top) / 2;
13521 }
13522
13523 // also clip horizontal fades if necessary
13524 if (horizontalEdges && (left + length > right - length)) {
13525 length = (right - left) / 2;
13526 }
13527
13528 if (verticalEdges) {
13529 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013530 drawTop = topFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013531 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013532 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013533 }
13534
13535 if (horizontalEdges) {
13536 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013537 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013538 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013539 drawRight = rightFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013540 }
13541
13542 saveCount = canvas.getSaveCount();
13543
13544 int solidColor = getSolidColor();
Romain Guyf607bdc2010-09-10 19:20:06 -070013545 if (solidColor == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013546 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13547
13548 if (drawTop) {
13549 canvas.saveLayer(left, top, right, top + length, null, flags);
13550 }
13551
13552 if (drawBottom) {
13553 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
13554 }
13555
13556 if (drawLeft) {
13557 canvas.saveLayer(left, top, left + length, bottom, null, flags);
13558 }
13559
13560 if (drawRight) {
13561 canvas.saveLayer(right - length, top, right, bottom, null, flags);
13562 }
13563 } else {
13564 scrollabilityCache.setFadeColor(solidColor);
13565 }
13566
13567 // Step 3, draw the content
Romain Guy24443ea2009-05-11 11:56:30 -070013568 if (!dirtyOpaque) onDraw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013569
13570 // Step 4, draw the children
13571 dispatchDraw(canvas);
13572
13573 // Step 5, draw the fade effect and restore layers
13574 final Paint p = scrollabilityCache.paint;
13575 final Matrix matrix = scrollabilityCache.matrix;
13576 final Shader fade = scrollabilityCache.shader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013577
13578 if (drawTop) {
13579 matrix.setScale(1, fadeHeight * topFadeStrength);
13580 matrix.postTranslate(left, top);
13581 fade.setLocalMatrix(matrix);
13582 canvas.drawRect(left, top, right, top + length, p);
13583 }
13584
13585 if (drawBottom) {
13586 matrix.setScale(1, fadeHeight * bottomFadeStrength);
13587 matrix.postRotate(180);
13588 matrix.postTranslate(left, bottom);
13589 fade.setLocalMatrix(matrix);
13590 canvas.drawRect(left, bottom - length, right, bottom, p);
13591 }
13592
13593 if (drawLeft) {
13594 matrix.setScale(1, fadeHeight * leftFadeStrength);
13595 matrix.postRotate(-90);
13596 matrix.postTranslate(left, top);
13597 fade.setLocalMatrix(matrix);
13598 canvas.drawRect(left, top, left + length, bottom, p);
13599 }
13600
13601 if (drawRight) {
13602 matrix.setScale(1, fadeHeight * rightFadeStrength);
13603 matrix.postRotate(90);
13604 matrix.postTranslate(right, top);
13605 fade.setLocalMatrix(matrix);
13606 canvas.drawRect(right - length, top, right, bottom, p);
13607 }
13608
13609 canvas.restoreToCount(saveCount);
13610
13611 // Step 6, draw decorations (scrollbars)
13612 onDrawScrollBars(canvas);
13613 }
13614
13615 /**
13616 * Override this if your view is known to always be drawn on top of a solid color background,
13617 * and needs to draw fading edges. Returning a non-zero color enables the view system to
13618 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
13619 * should be set to 0xFF.
13620 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013621 * @see #setVerticalFadingEdgeEnabled(boolean)
13622 * @see #setHorizontalFadingEdgeEnabled(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013623 *
13624 * @return The known solid color background for this view, or 0 if the color may vary
13625 */
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013626 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013627 public int getSolidColor() {
13628 return 0;
13629 }
13630
13631 /**
13632 * Build a human readable string representation of the specified view flags.
13633 *
13634 * @param flags the view flags to convert to a string
13635 * @return a String representing the supplied flags
13636 */
13637 private static String printFlags(int flags) {
13638 String output = "";
13639 int numFlags = 0;
13640 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
13641 output += "TAKES_FOCUS";
13642 numFlags++;
13643 }
13644
13645 switch (flags & VISIBILITY_MASK) {
13646 case INVISIBLE:
13647 if (numFlags > 0) {
13648 output += " ";
13649 }
13650 output += "INVISIBLE";
13651 // USELESS HERE numFlags++;
13652 break;
13653 case GONE:
13654 if (numFlags > 0) {
13655 output += " ";
13656 }
13657 output += "GONE";
13658 // USELESS HERE numFlags++;
13659 break;
13660 default:
13661 break;
13662 }
13663 return output;
13664 }
13665
13666 /**
13667 * Build a human readable string representation of the specified private
13668 * view flags.
13669 *
13670 * @param privateFlags the private view flags to convert to a string
13671 * @return a String representing the supplied flags
13672 */
13673 private static String printPrivateFlags(int privateFlags) {
13674 String output = "";
13675 int numFlags = 0;
13676
Dianne Hackborn4702a852012-08-17 15:18:29 -070013677 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013678 output += "WANTS_FOCUS";
13679 numFlags++;
13680 }
13681
Dianne Hackborn4702a852012-08-17 15:18:29 -070013682 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013683 if (numFlags > 0) {
13684 output += " ";
13685 }
13686 output += "FOCUSED";
13687 numFlags++;
13688 }
13689
Dianne Hackborn4702a852012-08-17 15:18:29 -070013690 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013691 if (numFlags > 0) {
13692 output += " ";
13693 }
13694 output += "SELECTED";
13695 numFlags++;
13696 }
13697
Dianne Hackborn4702a852012-08-17 15:18:29 -070013698 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013699 if (numFlags > 0) {
13700 output += " ";
13701 }
13702 output += "IS_ROOT_NAMESPACE";
13703 numFlags++;
13704 }
13705
Dianne Hackborn4702a852012-08-17 15:18:29 -070013706 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013707 if (numFlags > 0) {
13708 output += " ";
13709 }
13710 output += "HAS_BOUNDS";
13711 numFlags++;
13712 }
13713
Dianne Hackborn4702a852012-08-17 15:18:29 -070013714 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013715 if (numFlags > 0) {
13716 output += " ";
13717 }
13718 output += "DRAWN";
13719 // USELESS HERE numFlags++;
13720 }
13721 return output;
13722 }
13723
13724 /**
13725 * <p>Indicates whether or not this view's layout will be requested during
13726 * the next hierarchy layout pass.</p>
13727 *
13728 * @return true if the layout will be forced during next layout pass
13729 */
13730 public boolean isLayoutRequested() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013731 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013732 }
13733
13734 /**
13735 * Assign a size and position to a view and all of its
13736 * descendants
13737 *
13738 * <p>This is the second phase of the layout mechanism.
13739 * (The first is measuring). In this phase, each parent calls
13740 * layout on all of its children to position them.
13741 * This is typically done using the child measurements
Chet Haase9c087442011-01-12 16:20:16 -080013742 * that were stored in the measure pass().</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013743 *
Chet Haase9c087442011-01-12 16:20:16 -080013744 * <p>Derived classes should not override this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013745 * Derived classes with children should override
13746 * onLayout. In that method, they should
Chet Haase9c087442011-01-12 16:20:16 -080013747 * call layout on each of their children.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013748 *
13749 * @param l Left position, relative to parent
13750 * @param t Top position, relative to parent
13751 * @param r Right position, relative to parent
13752 * @param b Bottom position, relative to parent
13753 */
Romain Guy5429e1d2010-09-07 12:38:00 -070013754 @SuppressWarnings({"unchecked"})
Chet Haase9c087442011-01-12 16:20:16 -080013755 public void layout(int l, int t, int r, int b) {
Chet Haase21cd1382010-09-01 17:42:29 -070013756 int oldL = mLeft;
13757 int oldT = mTop;
13758 int oldB = mBottom;
13759 int oldR = mRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013760 boolean changed = setFrame(l, t, r, b);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013761 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 onLayout(changed, l, t, r, b);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013763 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
Chet Haase21cd1382010-09-01 17:42:29 -070013764
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070013765 ListenerInfo li = mListenerInfo;
13766 if (li != null && li.mOnLayoutChangeListeners != null) {
Chet Haase21cd1382010-09-01 17:42:29 -070013767 ArrayList<OnLayoutChangeListener> listenersCopy =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070013768 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
Chet Haase21cd1382010-09-01 17:42:29 -070013769 int numListeners = listenersCopy.size();
13770 for (int i = 0; i < numListeners; ++i) {
Chet Haase7c608f22010-10-22 17:54:04 -070013771 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
Chet Haase21cd1382010-09-01 17:42:29 -070013772 }
13773 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013774 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070013775 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013776 }
13777
13778 /**
13779 * Called from layout when this view should
13780 * assign a size and position to each of its children.
13781 *
13782 * Derived classes with children should override
13783 * this method and call layout on each of
Chet Haase21cd1382010-09-01 17:42:29 -070013784 * their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013785 * @param changed This is a new size or position for this view
13786 * @param left Left position, relative to parent
13787 * @param top Top position, relative to parent
13788 * @param right Right position, relative to parent
13789 * @param bottom Bottom position, relative to parent
13790 */
13791 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
13792 }
13793
13794 /**
13795 * Assign a size and position to this view.
13796 *
13797 * This is called from layout.
13798 *
13799 * @param left Left position, relative to parent
13800 * @param top Top position, relative to parent
13801 * @param right Right position, relative to parent
13802 * @param bottom Bottom position, relative to parent
13803 * @return true if the new size and position are different than the
13804 * previous ones
13805 * {@hide}
13806 */
13807 protected boolean setFrame(int left, int top, int right, int bottom) {
13808 boolean changed = false;
13809
13810 if (DBG) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -070013811 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013812 + right + "," + bottom + ")");
13813 }
13814
13815 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
13816 changed = true;
13817
13818 // Remember our drawn bit
Dianne Hackborn4702a852012-08-17 15:18:29 -070013819 int drawn = mPrivateFlags & PFLAG_DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013820
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013821 int oldWidth = mRight - mLeft;
13822 int oldHeight = mBottom - mTop;
Chet Haase75755e22011-07-18 17:48:25 -070013823 int newWidth = right - left;
13824 int newHeight = bottom - top;
13825 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
13826
13827 // Invalidate our old position
13828 invalidate(sizeChanged);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013829
13830 mLeft = left;
13831 mTop = top;
13832 mRight = right;
13833 mBottom = bottom;
Chet Haase1271e2c2012-04-20 09:54:27 -070013834 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013835 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13836 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013837
Dianne Hackborn4702a852012-08-17 15:18:29 -070013838 mPrivateFlags |= PFLAG_HAS_BOUNDS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013839
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013840
Chet Haase75755e22011-07-18 17:48:25 -070013841 if (sizeChanged) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013842 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013843 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -070013844 if (mTransformationInfo != null) {
13845 mTransformationInfo.mMatrixDirty = true;
13846 }
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013847 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013848 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
13849 }
13850
13851 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
13852 // If we are visible, force the DRAWN bit to on so that
13853 // this invalidate will go through (at least to our parent).
13854 // This is because someone may have invalidated this view
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013855 // before this call to setFrame came in, thereby clearing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013856 // the DRAWN bit.
Dianne Hackborn4702a852012-08-17 15:18:29 -070013857 mPrivateFlags |= PFLAG_DRAWN;
Chet Haase75755e22011-07-18 17:48:25 -070013858 invalidate(sizeChanged);
Chet Haasef28595e2011-01-31 18:52:12 -080013859 // parent display list may need to be recreated based on a change in the bounds
13860 // of any child
13861 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013862 }
13863
13864 // Reset drawn bit to original value (invalidate turns it off)
13865 mPrivateFlags |= drawn;
13866
13867 mBackgroundSizeChanged = true;
13868 }
13869 return changed;
13870 }
13871
13872 /**
13873 * Finalize inflating a view from XML. This is called as the last phase
13874 * of inflation, after all child views have been added.
13875 *
13876 * <p>Even if the subclass overrides onFinishInflate, they should always be
13877 * sure to call the super method, so that we get called.
13878 */
13879 protected void onFinishInflate() {
13880 }
13881
13882 /**
13883 * Returns the resources associated with this view.
13884 *
13885 * @return Resources object.
13886 */
13887 public Resources getResources() {
13888 return mResources;
13889 }
13890
13891 /**
13892 * Invalidates the specified Drawable.
13893 *
13894 * @param drawable the drawable to invalidate
13895 */
13896 public void invalidateDrawable(Drawable drawable) {
13897 if (verifyDrawable(drawable)) {
13898 final Rect dirty = drawable.getBounds();
13899 final int scrollX = mScrollX;
13900 final int scrollY = mScrollY;
13901
13902 invalidate(dirty.left + scrollX, dirty.top + scrollY,
13903 dirty.right + scrollX, dirty.bottom + scrollY);
13904 }
13905 }
13906
13907 /**
13908 * Schedules an action on a drawable to occur at a specified time.
13909 *
13910 * @param who the recipient of the action
13911 * @param what the action to run on the drawable
13912 * @param when the time at which the action must occur. Uses the
13913 * {@link SystemClock#uptimeMillis} timebase.
13914 */
13915 public void scheduleDrawable(Drawable who, Runnable what, long when) {
Adam Powell37419d72011-11-10 11:32:09 -080013916 if (verifyDrawable(who) && what != null) {
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080013917 final long delay = when - SystemClock.uptimeMillis();
Adam Powell37419d72011-11-10 11:32:09 -080013918 if (mAttachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013919 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13920 Choreographer.CALLBACK_ANIMATION, what, who,
13921 Choreographer.subtractFrameDelay(delay));
Adam Powell37419d72011-11-10 11:32:09 -080013922 } else {
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080013923 ViewRootImpl.getRunQueue().postDelayed(what, delay);
Adam Powell37419d72011-11-10 11:32:09 -080013924 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013925 }
13926 }
13927
13928 /**
13929 * Cancels a scheduled action on a drawable.
13930 *
13931 * @param who the recipient of the action
13932 * @param what the action to cancel
13933 */
13934 public void unscheduleDrawable(Drawable who, Runnable what) {
Adam Powell37419d72011-11-10 11:32:09 -080013935 if (verifyDrawable(who) && what != null) {
13936 if (mAttachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013937 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13938 Choreographer.CALLBACK_ANIMATION, what, who);
Adam Powell37419d72011-11-10 11:32:09 -080013939 } else {
13940 ViewRootImpl.getRunQueue().removeCallbacks(what);
13941 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013942 }
13943 }
13944
13945 /**
13946 * Unschedule any events associated with the given Drawable. This can be
13947 * used when selecting a new Drawable into a view, so that the previous
13948 * one is completely unscheduled.
13949 *
13950 * @param who The Drawable to unschedule.
13951 *
13952 * @see #drawableStateChanged
13953 */
13954 public void unscheduleDrawable(Drawable who) {
Jeff Brown43ea54b2012-03-09 14:37:48 -080013955 if (mAttachInfo != null && who != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013956 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13957 Choreographer.CALLBACK_ANIMATION, null, who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013958 }
13959 }
13960
Fabrice Di Meglioc0053222011-06-13 12:16:51 -070013961 /**
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070013962 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
13963 * that the View directionality can and will be resolved before its Drawables.
13964 *
13965 * Will call {@link View#onResolveDrawables} when resolution is done.
13966 */
13967 public void resolveDrawables() {
13968 if (mBackground != null) {
13969 mBackground.setLayoutDirection(getResolvedLayoutDirection());
13970 }
13971 onResolveDrawables(getResolvedLayoutDirection());
13972 }
13973
13974 /**
13975 * Called when layout direction has been resolved.
13976 *
13977 * The default implementation does nothing.
13978 *
13979 * @param layoutDirection The resolved layout direction.
13980 *
13981 * @see {@link #LAYOUT_DIRECTION_LTR}
13982 * @see {@link #LAYOUT_DIRECTION_RTL}
13983 */
13984 public void onResolveDrawables(int layoutDirection) {
Fabrice Di Meglio6a036402011-05-23 14:43:23 -070013985 }
13986
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013987 /**
13988 * If your view subclass is displaying its own Drawable objects, it should
13989 * override this function and return true for any Drawable it is
13990 * displaying. This allows animations for those drawables to be
13991 * scheduled.
13992 *
13993 * <p>Be sure to call through to the super class when overriding this
13994 * function.
13995 *
13996 * @param who The Drawable to verify. Return true if it is one you are
13997 * displaying, else return the result of calling through to the
13998 * super class.
13999 *
14000 * @return boolean If true than the Drawable is being displayed in the
14001 * view; else false and it is not allowed to animate.
14002 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014003 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
14004 * @see #drawableStateChanged()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014005 */
14006 protected boolean verifyDrawable(Drawable who) {
Philip Milne6c8ea062012-04-03 17:38:43 -070014007 return who == mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014008 }
14009
14010 /**
14011 * This function is called whenever the state of the view changes in such
14012 * a way that it impacts the state of drawables being shown.
14013 *
14014 * <p>Be sure to call through to the superclass when overriding this
14015 * function.
14016 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014017 * @see Drawable#setState(int[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014018 */
14019 protected void drawableStateChanged() {
Philip Milne6c8ea062012-04-03 17:38:43 -070014020 Drawable d = mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014021 if (d != null && d.isStateful()) {
14022 d.setState(getDrawableState());
14023 }
14024 }
14025
14026 /**
14027 * Call this to force a view to update its drawable state. This will cause
14028 * drawableStateChanged to be called on this view. Views that are interested
14029 * in the new state should call getDrawableState.
14030 *
14031 * @see #drawableStateChanged
14032 * @see #getDrawableState
14033 */
14034 public void refreshDrawableState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014035 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014036 drawableStateChanged();
14037
14038 ViewParent parent = mParent;
14039 if (parent != null) {
14040 parent.childDrawableStateChanged(this);
14041 }
14042 }
14043
14044 /**
14045 * Return an array of resource IDs of the drawable states representing the
14046 * current state of the view.
14047 *
14048 * @return The current drawable state
14049 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014050 * @see Drawable#setState(int[])
14051 * @see #drawableStateChanged()
14052 * @see #onCreateDrawableState(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014053 */
14054 public final int[] getDrawableState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014055 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014056 return mDrawableState;
14057 } else {
14058 mDrawableState = onCreateDrawableState(0);
Dianne Hackborn4702a852012-08-17 15:18:29 -070014059 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014060 return mDrawableState;
14061 }
14062 }
14063
14064 /**
14065 * Generate the new {@link android.graphics.drawable.Drawable} state for
14066 * this view. This is called by the view
14067 * system when the cached Drawable state is determined to be invalid. To
14068 * retrieve the current state, you should use {@link #getDrawableState}.
14069 *
14070 * @param extraSpace if non-zero, this is the number of extra entries you
14071 * would like in the returned array in which you can place your own
14072 * states.
14073 *
14074 * @return Returns an array holding the current {@link Drawable} state of
14075 * the view.
14076 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014077 * @see #mergeDrawableStates(int[], int[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014078 */
14079 protected int[] onCreateDrawableState(int extraSpace) {
14080 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
14081 mParent instanceof View) {
14082 return ((View) mParent).onCreateDrawableState(extraSpace);
14083 }
14084
14085 int[] drawableState;
14086
14087 int privateFlags = mPrivateFlags;
14088
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014089 int viewStateIndex = 0;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014090 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014091 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
14092 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014093 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014094 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014095 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
Adam Powell5a7e94e2011-04-25 15:30:43 -070014096 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
14097 HardwareRenderer.isAvailable()) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080014098 // This is set if HW acceleration is requested, even if the current
14099 // process doesn't allow it. This is just to allow app preview
14100 // windows to better match their app.
14101 viewStateIndex |= VIEW_STATE_ACCELERATED;
14102 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070014103 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014104
Christopher Tate3d4bf172011-03-28 16:16:46 -070014105 final int privateFlags2 = mPrivateFlags2;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014106 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
14107 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
Christopher Tate3d4bf172011-03-28 16:16:46 -070014108
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014109 drawableState = VIEW_STATE_SETS[viewStateIndex];
14110
14111 //noinspection ConstantIfStatement
14112 if (false) {
14113 Log.i("View", "drawableStateIndex=" + viewStateIndex);
14114 Log.i("View", toString()
Dianne Hackborn4702a852012-08-17 15:18:29 -070014115 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014116 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
14117 + " fo=" + hasFocus()
Dianne Hackborn4702a852012-08-17 15:18:29 -070014118 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014119 + " wf=" + hasWindowFocus()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014120 + ": " + Arrays.toString(drawableState));
14121 }
14122
14123 if (extraSpace == 0) {
14124 return drawableState;
14125 }
14126
14127 final int[] fullState;
14128 if (drawableState != null) {
14129 fullState = new int[drawableState.length + extraSpace];
14130 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
14131 } else {
14132 fullState = new int[extraSpace];
14133 }
14134
14135 return fullState;
14136 }
14137
14138 /**
14139 * Merge your own state values in <var>additionalState</var> into the base
14140 * state values <var>baseState</var> that were returned by
Romain Guy5c22a8c2011-05-13 11:48:45 -070014141 * {@link #onCreateDrawableState(int)}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014142 *
14143 * @param baseState The base state values returned by
Romain Guy5c22a8c2011-05-13 11:48:45 -070014144 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014145 * own additional state values.
14146 *
14147 * @param additionalState The additional state values you would like
14148 * added to <var>baseState</var>; this array is not modified.
14149 *
14150 * @return As a convenience, the <var>baseState</var> array you originally
14151 * passed into the function is returned.
14152 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014153 * @see #onCreateDrawableState(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014154 */
14155 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
14156 final int N = baseState.length;
14157 int i = N - 1;
14158 while (i >= 0 && baseState[i] == 0) {
14159 i--;
14160 }
14161 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
14162 return baseState;
14163 }
14164
14165 /**
Dianne Hackborn079e2352010-10-18 17:02:43 -070014166 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
14167 * on all Drawable objects associated with this view.
14168 */
14169 public void jumpDrawablesToCurrentState() {
Philip Milne6c8ea062012-04-03 17:38:43 -070014170 if (mBackground != null) {
14171 mBackground.jumpToCurrentState();
Dianne Hackborn079e2352010-10-18 17:02:43 -070014172 }
14173 }
14174
14175 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014176 * Sets the background color for this view.
14177 * @param color the color of the background
14178 */
Bjorn Bringert8354fa62010-02-24 23:54:29 +000014179 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014180 public void setBackgroundColor(int color) {
Philip Milne6c8ea062012-04-03 17:38:43 -070014181 if (mBackground instanceof ColorDrawable) {
Romain Guy5f49c302012-09-06 16:33:31 -070014182 ((ColorDrawable) mBackground.mutate()).setColor(color);
Romain Guy7d3082a2012-07-11 17:52:54 -070014183 computeOpaqueFlags();
Chet Haase70d4ba12010-10-06 09:46:45 -070014184 } else {
Philip Milne6c8ea062012-04-03 17:38:43 -070014185 setBackground(new ColorDrawable(color));
Chet Haase70d4ba12010-10-06 09:46:45 -070014186 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014187 }
14188
14189 /**
14190 * Set the background to a given resource. The resource should refer to
Wink Saville7cd88e12009-08-04 14:45:10 -070014191 * a Drawable object or 0 to remove the background.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014192 * @param resid The identifier of the resource.
Philip Milne6c8ea062012-04-03 17:38:43 -070014193 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 * @attr ref android.R.styleable#View_background
14195 */
Bjorn Bringert8354fa62010-02-24 23:54:29 +000014196 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014197 public void setBackgroundResource(int resid) {
14198 if (resid != 0 && resid == mBackgroundResource) {
14199 return;
14200 }
14201
14202 Drawable d= null;
14203 if (resid != 0) {
14204 d = mResources.getDrawable(resid);
14205 }
Philip Milne6c8ea062012-04-03 17:38:43 -070014206 setBackground(d);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014207
14208 mBackgroundResource = resid;
14209 }
14210
14211 /**
14212 * Set the background to a given Drawable, or remove the background. If the
14213 * background has padding, this View's padding is set to the background's
14214 * padding. However, when a background is removed, this View's padding isn't
14215 * touched. If setting the padding is desired, please use
14216 * {@link #setPadding(int, int, int, int)}.
14217 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014218 * @param background The Drawable to use as the background, or null to remove the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014219 * background
14220 */
Philip Milne6c8ea062012-04-03 17:38:43 -070014221 public void setBackground(Drawable background) {
Romain Guyeb378892012-04-12 11:33:14 -070014222 //noinspection deprecation
Philip Milne6c8ea062012-04-03 17:38:43 -070014223 setBackgroundDrawable(background);
14224 }
14225
14226 /**
14227 * @deprecated use {@link #setBackground(Drawable)} instead
14228 */
14229 @Deprecated
14230 public void setBackgroundDrawable(Drawable background) {
Romain Guy846a5332012-07-11 17:44:57 -070014231 computeOpaqueFlags();
14232
Philip Milne6c8ea062012-04-03 17:38:43 -070014233 if (background == mBackground) {
Adam Powell4d36ec12011-07-17 16:44:16 -070014234 return;
14235 }
14236
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014237 boolean requestLayout = false;
14238
14239 mBackgroundResource = 0;
14240
14241 /*
14242 * Regardless of whether we're setting a new background or not, we want
14243 * to clear the previous drawable.
14244 */
Philip Milne6c8ea062012-04-03 17:38:43 -070014245 if (mBackground != null) {
14246 mBackground.setCallback(null);
14247 unscheduleDrawable(mBackground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014248 }
14249
Philip Milne6c8ea062012-04-03 17:38:43 -070014250 if (background != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014251 Rect padding = sThreadLocal.get();
14252 if (padding == null) {
14253 padding = new Rect();
14254 sThreadLocal.set(padding);
14255 }
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070014256 background.setLayoutDirection(getResolvedLayoutDirection());
Philip Milne6c8ea062012-04-03 17:38:43 -070014257 if (background.getPadding(padding)) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014258 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070014259 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070014260 switch (background.getLayoutDirection()) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014261 case LAYOUT_DIRECTION_RTL:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014262 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014263 break;
14264 case LAYOUT_DIRECTION_LTR:
14265 default:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014266 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014268 }
14269
14270 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
14271 // if it has a different minimum size, we should layout again
Philip Milne6c8ea062012-04-03 17:38:43 -070014272 if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14273 mBackground.getMinimumWidth() != background.getMinimumWidth()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014274 requestLayout = true;
14275 }
14276
Philip Milne6c8ea062012-04-03 17:38:43 -070014277 background.setCallback(this);
14278 if (background.isStateful()) {
14279 background.setState(getDrawableState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014280 }
Philip Milne6c8ea062012-04-03 17:38:43 -070014281 background.setVisible(getVisibility() == VISIBLE, false);
14282 mBackground = background;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014283
Dianne Hackborn4702a852012-08-17 15:18:29 -070014284 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
14285 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14286 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014287 requestLayout = true;
14288 }
14289 } else {
14290 /* Remove the background */
Philip Milne6c8ea062012-04-03 17:38:43 -070014291 mBackground = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014292
Dianne Hackborn4702a852012-08-17 15:18:29 -070014293 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014294 /*
14295 * This view ONLY drew the background before and we're removing
14296 * the background, so now it won't draw anything
14297 * (hence we SKIP_DRAW)
14298 */
Dianne Hackborn4702a852012-08-17 15:18:29 -070014299 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
14300 mPrivateFlags |= PFLAG_SKIP_DRAW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014301 }
14302
14303 /*
14304 * When the background is set, we try to apply its padding to this
14305 * View. When the background is removed, we don't touch this View's
14306 * padding. This is noted in the Javadocs. Hence, we don't need to
14307 * requestLayout(), the invalidate() below is sufficient.
14308 */
14309
14310 // The old background's minimum size could have affected this
14311 // View's layout, so let's requestLayout
14312 requestLayout = true;
14313 }
14314
Romain Guy8f1344f52009-05-15 16:03:59 -070014315 computeOpaqueFlags();
14316
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014317 if (requestLayout) {
14318 requestLayout();
14319 }
14320
14321 mBackgroundSizeChanged = true;
Romain Guy0fd89bf2011-01-26 15:41:30 -080014322 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014323 }
14324
14325 /**
14326 * Gets the background drawable
Philip Milne6c8ea062012-04-03 17:38:43 -070014327 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014328 * @return The drawable used as the background for this view, if any.
Philip Milne6c8ea062012-04-03 17:38:43 -070014329 *
14330 * @see #setBackground(Drawable)
14331 *
14332 * @attr ref android.R.styleable#View_background
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014333 */
14334 public Drawable getBackground() {
Philip Milne6c8ea062012-04-03 17:38:43 -070014335 return mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014336 }
14337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014338 /**
14339 * Sets the padding. The view may add on the space required to display
14340 * the scrollbars, depending on the style and visibility of the scrollbars.
14341 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14342 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14343 * from the values set in this call.
14344 *
14345 * @attr ref android.R.styleable#View_padding
14346 * @attr ref android.R.styleable#View_paddingBottom
14347 * @attr ref android.R.styleable#View_paddingLeft
14348 * @attr ref android.R.styleable#View_paddingRight
14349 * @attr ref android.R.styleable#View_paddingTop
14350 * @param left the left padding in pixels
14351 * @param top the top padding in pixels
14352 * @param right the right padding in pixels
14353 * @param bottom the bottom padding in pixels
14354 */
14355 public void setPadding(int left, int top, int right, int bottom) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014356 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070014357 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014358
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014359 mUserPaddingStart = UNDEFINED_PADDING;
14360 mUserPaddingEnd = UNDEFINED_PADDING;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014361
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014362 internalSetPadding(left, top, right, bottom);
14363 }
14364
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014365 /**
14366 * @hide
14367 */
14368 protected void internalSetPadding(int left, int top, int right, int bottom) {
Adam Powell20232d02010-12-08 21:08:53 -080014369 mUserPaddingLeft = left;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014370 mUserPaddingRight = right;
14371 mUserPaddingBottom = bottom;
14372
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014373 final int viewFlags = mViewFlags;
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014374 boolean changed = false;
Romain Guy8506ab42009-06-11 17:35:47 -070014375
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014376 // Common case is there are no scroll bars.
14377 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014378 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
Adam Powell20232d02010-12-08 21:08:53 -080014379 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014380 ? 0 : getVerticalScrollbarWidth();
Adam Powell20232d02010-12-08 21:08:53 -080014381 switch (mVerticalScrollbarPosition) {
14382 case SCROLLBAR_POSITION_DEFAULT:
Fabrice Di Meglioc91b6ca2012-06-22 14:51:15 -070014383 if (isLayoutRtl()) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014384 left += offset;
14385 } else {
14386 right += offset;
14387 }
14388 break;
Adam Powell20232d02010-12-08 21:08:53 -080014389 case SCROLLBAR_POSITION_RIGHT:
14390 right += offset;
14391 break;
14392 case SCROLLBAR_POSITION_LEFT:
14393 left += offset;
14394 break;
14395 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014396 }
Adam Powell20232d02010-12-08 21:08:53 -080014397 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014398 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14399 ? 0 : getHorizontalScrollbarHeight();
14400 }
14401 }
Romain Guy8506ab42009-06-11 17:35:47 -070014402
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014403 if (mPaddingLeft != left) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014404 changed = true;
14405 mPaddingLeft = left;
14406 }
14407 if (mPaddingTop != top) {
14408 changed = true;
14409 mPaddingTop = top;
14410 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014411 if (mPaddingRight != right) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014412 changed = true;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014413 mPaddingRight = right;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014414 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014415 if (mPaddingBottom != bottom) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014416 changed = true;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014417 mPaddingBottom = bottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014418 }
14419
14420 if (changed) {
14421 requestLayout();
14422 }
14423 }
14424
14425 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014426 * Sets the relative padding. The view may add on the space required to display
14427 * the scrollbars, depending on the style and visibility of the scrollbars.
14428 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14429 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14430 * from the values set in this call.
14431 *
14432 * @attr ref android.R.styleable#View_padding
14433 * @attr ref android.R.styleable#View_paddingBottom
14434 * @attr ref android.R.styleable#View_paddingStart
14435 * @attr ref android.R.styleable#View_paddingEnd
14436 * @attr ref android.R.styleable#View_paddingTop
14437 * @param start the start padding in pixels
14438 * @param top the top padding in pixels
14439 * @param end the end padding in pixels
14440 * @param bottom the bottom padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014441 */
14442 public void setPaddingRelative(int start, int top, int end, int bottom) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014443 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070014444 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014445
Fabrice Di Megliof9e36502011-06-21 18:41:48 -070014446 mUserPaddingStart = start;
14447 mUserPaddingEnd = end;
14448
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014449 switch(getResolvedLayoutDirection()) {
14450 case LAYOUT_DIRECTION_RTL:
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014451 internalSetPadding(end, top, start, bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014452 break;
14453 case LAYOUT_DIRECTION_LTR:
14454 default:
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014455 internalSetPadding(start, top, end, bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014456 }
14457 }
14458
14459 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014460 * Returns the top padding of this view.
14461 *
14462 * @return the top padding in pixels
14463 */
14464 public int getPaddingTop() {
14465 return mPaddingTop;
14466 }
14467
14468 /**
14469 * Returns the bottom padding of this view. If there are inset and enabled
14470 * scrollbars, this value may include the space required to display the
14471 * scrollbars as well.
14472 *
14473 * @return the bottom padding in pixels
14474 */
14475 public int getPaddingBottom() {
14476 return mPaddingBottom;
14477 }
14478
14479 /**
14480 * Returns the left padding of this view. If there are inset and enabled
14481 * scrollbars, this value may include the space required to display the
14482 * scrollbars as well.
14483 *
14484 * @return the left padding in pixels
14485 */
14486 public int getPaddingLeft() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014487 if (!isPaddingResolved()) {
14488 resolvePadding();
14489 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014490 return mPaddingLeft;
14491 }
14492
14493 /**
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -070014494 * Returns the start padding of this view depending on its resolved layout direction.
14495 * If there are inset and enabled scrollbars, this value may include the space
14496 * required to display the scrollbars as well.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014497 *
14498 * @return the start padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014499 */
14500 public int getPaddingStart() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014501 if (!isPaddingResolved()) {
14502 resolvePadding();
14503 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014504 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14505 mPaddingRight : mPaddingLeft;
14506 }
14507
14508 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014509 * Returns the right padding of this view. If there are inset and enabled
14510 * scrollbars, this value may include the space required to display the
14511 * scrollbars as well.
14512 *
14513 * @return the right padding in pixels
14514 */
14515 public int getPaddingRight() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014516 if (!isPaddingResolved()) {
14517 resolvePadding();
14518 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014519 return mPaddingRight;
14520 }
14521
14522 /**
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -070014523 * Returns the end padding of this view depending on its resolved layout direction.
14524 * If there are inset and enabled scrollbars, this value may include the space
14525 * required to display the scrollbars as well.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014526 *
14527 * @return the end padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014528 */
14529 public int getPaddingEnd() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014530 if (!isPaddingResolved()) {
14531 resolvePadding();
14532 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014533 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14534 mPaddingLeft : mPaddingRight;
14535 }
14536
14537 /**
14538 * Return if the padding as been set thru relative values
14539 * {@link #setPaddingRelative(int, int, int, int)} or thru
14540 * @attr ref android.R.styleable#View_paddingStart or
14541 * @attr ref android.R.styleable#View_paddingEnd
14542 *
14543 * @return true if the padding is relative or false if it is not.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014544 */
14545 public boolean isPaddingRelative() {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014546 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014547 }
14548
14549 /**
Philip Milne1557fd72012-04-04 23:41:34 -070014550 * @hide
14551 */
Philip Milne7a23b492012-04-24 22:12:36 -070014552 public Insets getOpticalInsets() {
Philip Milne1557fd72012-04-04 23:41:34 -070014553 if (mLayoutInsets == null) {
Philip Milnebbd51f12012-04-18 15:09:05 -070014554 mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
Philip Milne1557fd72012-04-04 23:41:34 -070014555 }
14556 return mLayoutInsets;
14557 }
14558
14559 /**
14560 * @hide
14561 */
14562 public void setLayoutInsets(Insets layoutInsets) {
14563 mLayoutInsets = layoutInsets;
14564 }
14565
14566 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014567 * Changes the selection state of this view. A view can be selected or not.
14568 * Note that selection is not the same as focus. Views are typically
14569 * selected in the context of an AdapterView like ListView or GridView;
14570 * the selected view is the view that is highlighted.
14571 *
14572 * @param selected true if the view must be selected, false otherwise
14573 */
14574 public void setSelected(boolean selected) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014575 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
14576 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
Romain Guya2431d02009-04-30 16:30:00 -070014577 if (!selected) resetPressedState();
Romain Guy0fd89bf2011-01-26 15:41:30 -080014578 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014579 refreshDrawableState();
14580 dispatchSetSelected(selected);
Svetoslav Ganov42138042012-03-20 11:51:39 -070014581 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14582 notifyAccessibilityStateChanged();
14583 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014584 }
14585 }
14586
14587 /**
14588 * Dispatch setSelected to all of this View's children.
14589 *
14590 * @see #setSelected(boolean)
14591 *
14592 * @param selected The new selected state
14593 */
14594 protected void dispatchSetSelected(boolean selected) {
14595 }
14596
14597 /**
14598 * Indicates the selection state of this view.
14599 *
14600 * @return true if the view is selected, false otherwise
14601 */
14602 @ViewDebug.ExportedProperty
14603 public boolean isSelected() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014604 return (mPrivateFlags & PFLAG_SELECTED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014605 }
14606
14607 /**
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014608 * Changes the activated state of this view. A view can be activated or not.
14609 * Note that activation is not the same as selection. Selection is
14610 * a transient property, representing the view (hierarchy) the user is
14611 * currently interacting with. Activation is a longer-term state that the
14612 * user can move views in and out of. For example, in a list view with
14613 * single or multiple selection enabled, the views in the current selection
14614 * set are activated. (Um, yeah, we are deeply sorry about the terminology
14615 * here.) The activated state is propagated down to children of the view it
14616 * is set on.
14617 *
14618 * @param activated true if the view must be activated, false otherwise
14619 */
14620 public void setActivated(boolean activated) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014621 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
14622 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
Romain Guy0fd89bf2011-01-26 15:41:30 -080014623 invalidate(true);
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014624 refreshDrawableState();
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070014625 dispatchSetActivated(activated);
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014626 }
14627 }
14628
14629 /**
14630 * Dispatch setActivated to all of this View's children.
14631 *
14632 * @see #setActivated(boolean)
14633 *
14634 * @param activated The new activated state
14635 */
14636 protected void dispatchSetActivated(boolean activated) {
14637 }
14638
14639 /**
14640 * Indicates the activation state of this view.
14641 *
14642 * @return true if the view is activated, false otherwise
14643 */
14644 @ViewDebug.ExportedProperty
14645 public boolean isActivated() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014646 return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014647 }
14648
14649 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014650 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
14651 * observer can be used to get notifications when global events, like
14652 * layout, happen.
14653 *
14654 * The returned ViewTreeObserver observer is not guaranteed to remain
14655 * valid for the lifetime of this View. If the caller of this method keeps
14656 * a long-lived reference to ViewTreeObserver, it should always check for
14657 * the return value of {@link ViewTreeObserver#isAlive()}.
14658 *
14659 * @return The ViewTreeObserver for this view's hierarchy.
14660 */
14661 public ViewTreeObserver getViewTreeObserver() {
14662 if (mAttachInfo != null) {
14663 return mAttachInfo.mTreeObserver;
14664 }
14665 if (mFloatingTreeObserver == null) {
14666 mFloatingTreeObserver = new ViewTreeObserver();
14667 }
14668 return mFloatingTreeObserver;
14669 }
14670
14671 /**
14672 * <p>Finds the topmost view in the current view hierarchy.</p>
14673 *
14674 * @return the topmost view containing this view
14675 */
14676 public View getRootView() {
14677 if (mAttachInfo != null) {
14678 final View v = mAttachInfo.mRootView;
14679 if (v != null) {
14680 return v;
14681 }
14682 }
Romain Guy8506ab42009-06-11 17:35:47 -070014683
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014684 View parent = this;
14685
14686 while (parent.mParent != null && parent.mParent instanceof View) {
14687 parent = (View) parent.mParent;
14688 }
14689
14690 return parent;
14691 }
14692
14693 /**
14694 * <p>Computes the coordinates of this view on the screen. The argument
14695 * must be an array of two integers. After the method returns, the array
14696 * contains the x and y location in that order.</p>
14697 *
14698 * @param location an array of two integers in which to hold the coordinates
14699 */
14700 public void getLocationOnScreen(int[] location) {
14701 getLocationInWindow(location);
14702
14703 final AttachInfo info = mAttachInfo;
Romain Guy779398e2009-06-16 13:17:50 -070014704 if (info != null) {
14705 location[0] += info.mWindowLeft;
14706 location[1] += info.mWindowTop;
14707 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014708 }
14709
14710 /**
14711 * <p>Computes the coordinates of this view in its window. The argument
14712 * must be an array of two integers. After the method returns, the array
14713 * contains the x and y location in that order.</p>
14714 *
14715 * @param location an array of two integers in which to hold the coordinates
14716 */
14717 public void getLocationInWindow(int[] location) {
14718 if (location == null || location.length < 2) {
Gilles Debunnecea45132011-11-24 02:19:27 +010014719 throw new IllegalArgumentException("location must be an array of two integers");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014720 }
14721
Gilles Debunne6583ce52011-12-06 18:09:02 -080014722 if (mAttachInfo == null) {
14723 // When the view is not attached to a window, this method does not make sense
14724 location[0] = location[1] = 0;
14725 return;
14726 }
14727
Gilles Debunnecea45132011-11-24 02:19:27 +010014728 float[] position = mAttachInfo.mTmpTransformLocation;
14729 position[0] = position[1] = 0.0f;
14730
14731 if (!hasIdentityMatrix()) {
14732 getMatrix().mapPoints(position);
Dianne Hackbornddb715b2011-09-09 14:43:39 -070014733 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014734
Gilles Debunnecea45132011-11-24 02:19:27 +010014735 position[0] += mLeft;
14736 position[1] += mTop;
14737
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014738 ViewParent viewParent = mParent;
14739 while (viewParent instanceof View) {
Gilles Debunnecea45132011-11-24 02:19:27 +010014740 final View view = (View) viewParent;
14741
14742 position[0] -= view.mScrollX;
14743 position[1] -= view.mScrollY;
14744
14745 if (!view.hasIdentityMatrix()) {
14746 view.getMatrix().mapPoints(position);
Dianne Hackbornddb715b2011-09-09 14:43:39 -070014747 }
Gilles Debunnecea45132011-11-24 02:19:27 +010014748
14749 position[0] += view.mLeft;
14750 position[1] += view.mTop;
14751
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014752 viewParent = view.mParent;
Svetoslav Ganov42138042012-03-20 11:51:39 -070014753 }
Romain Guy8506ab42009-06-11 17:35:47 -070014754
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070014755 if (viewParent instanceof ViewRootImpl) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014756 // *cough*
Gilles Debunnecea45132011-11-24 02:19:27 +010014757 final ViewRootImpl vr = (ViewRootImpl) viewParent;
14758 position[1] -= vr.mCurScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014759 }
Gilles Debunnecea45132011-11-24 02:19:27 +010014760
14761 location[0] = (int) (position[0] + 0.5f);
14762 location[1] = (int) (position[1] + 0.5f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014763 }
14764
14765 /**
14766 * {@hide}
14767 * @param id the id of the view to be found
14768 * @return the view of the specified id, null if cannot be found
14769 */
14770 protected View findViewTraversal(int id) {
14771 if (id == mID) {
14772 return this;
14773 }
14774 return null;
14775 }
14776
14777 /**
14778 * {@hide}
14779 * @param tag the tag of the view to be found
14780 * @return the view of specified tag, null if cannot be found
14781 */
14782 protected View findViewWithTagTraversal(Object tag) {
14783 if (tag != null && tag.equals(mTag)) {
14784 return this;
14785 }
14786 return null;
14787 }
14788
14789 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -080014790 * {@hide}
14791 * @param predicate The predicate to evaluate.
Jeff Brown4dfbec22011-08-15 14:55:37 -070014792 * @param childToSkip If not null, ignores this child during the recursive traversal.
Jeff Brown4e6319b2010-12-13 10:36:51 -080014793 * @return The first view that matches the predicate or null.
14794 */
Jeff Brown4dfbec22011-08-15 14:55:37 -070014795 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
Jeff Brown4e6319b2010-12-13 10:36:51 -080014796 if (predicate.apply(this)) {
14797 return this;
14798 }
14799 return null;
14800 }
14801
14802 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014803 * Look for a child view with the given id. If this view has the given
14804 * id, return this view.
14805 *
14806 * @param id The id to search for.
14807 * @return The view that has the given id in the hierarchy or null
14808 */
14809 public final View findViewById(int id) {
14810 if (id < 0) {
14811 return null;
14812 }
14813 return findViewTraversal(id);
14814 }
14815
14816 /**
Svetoslav Ganov2cdedff2011-10-03 14:18:42 -070014817 * Finds a view by its unuque and stable accessibility id.
14818 *
14819 * @param accessibilityId The searched accessibility id.
14820 * @return The found view.
14821 */
14822 final View findViewByAccessibilityId(int accessibilityId) {
14823 if (accessibilityId < 0) {
14824 return null;
14825 }
14826 return findViewByAccessibilityIdTraversal(accessibilityId);
14827 }
14828
14829 /**
14830 * Performs the traversal to find a view by its unuque and stable accessibility id.
14831 *
14832 * <strong>Note:</strong>This method does not stop at the root namespace
14833 * boundary since the user can touch the screen at an arbitrary location
14834 * potentially crossing the root namespace bounday which will send an
14835 * accessibility event to accessibility services and they should be able
14836 * to obtain the event source. Also accessibility ids are guaranteed to be
14837 * unique in the window.
14838 *
14839 * @param accessibilityId The accessibility id.
14840 * @return The found view.
14841 */
14842 View findViewByAccessibilityIdTraversal(int accessibilityId) {
14843 if (getAccessibilityViewId() == accessibilityId) {
14844 return this;
14845 }
14846 return null;
14847 }
14848
14849 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014850 * Look for a child view with the given tag. If this view has the given
14851 * tag, return this view.
14852 *
14853 * @param tag The tag to search for, using "tag.equals(getTag())".
14854 * @return The View that has the given tag in the hierarchy or null
14855 */
14856 public final View findViewWithTag(Object tag) {
14857 if (tag == null) {
14858 return null;
14859 }
14860 return findViewWithTagTraversal(tag);
14861 }
14862
14863 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -080014864 * {@hide}
14865 * Look for a child view that matches the specified predicate.
14866 * If this view matches the predicate, return this view.
14867 *
14868 * @param predicate The predicate to evaluate.
14869 * @return The first view that matches the predicate or null.
14870 */
14871 public final View findViewByPredicate(Predicate<View> predicate) {
Jeff Brown4dfbec22011-08-15 14:55:37 -070014872 return findViewByPredicateTraversal(predicate, null);
14873 }
14874
14875 /**
14876 * {@hide}
14877 * Look for a child view that matches the specified predicate,
14878 * starting with the specified view and its descendents and then
14879 * recusively searching the ancestors and siblings of that view
14880 * until this view is reached.
14881 *
14882 * This method is useful in cases where the predicate does not match
14883 * a single unique view (perhaps multiple views use the same id)
14884 * and we are trying to find the view that is "closest" in scope to the
14885 * starting view.
14886 *
14887 * @param start The view to start from.
14888 * @param predicate The predicate to evaluate.
14889 * @return The first view that matches the predicate or null.
14890 */
14891 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
14892 View childToSkip = null;
14893 for (;;) {
14894 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
14895 if (view != null || start == this) {
14896 return view;
14897 }
14898
14899 ViewParent parent = start.getParent();
14900 if (parent == null || !(parent instanceof View)) {
14901 return null;
14902 }
14903
14904 childToSkip = start;
14905 start = (View) parent;
14906 }
Jeff Brown4e6319b2010-12-13 10:36:51 -080014907 }
14908
14909 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014910 * Sets the identifier for this view. The identifier does not have to be
14911 * unique in this view's hierarchy. The identifier should be a positive
14912 * number.
14913 *
14914 * @see #NO_ID
Philip Milne6c8ea062012-04-03 17:38:43 -070014915 * @see #getId()
14916 * @see #findViewById(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014917 *
14918 * @param id a number used to identify the view
14919 *
14920 * @attr ref android.R.styleable#View_id
14921 */
14922 public void setId(int id) {
14923 mID = id;
14924 }
14925
14926 /**
14927 * {@hide}
14928 *
14929 * @param isRoot true if the view belongs to the root namespace, false
14930 * otherwise
14931 */
14932 public void setIsRootNamespace(boolean isRoot) {
14933 if (isRoot) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014934 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014935 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014936 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014937 }
14938 }
14939
14940 /**
14941 * {@hide}
14942 *
14943 * @return true if the view belongs to the root namespace, false otherwise
14944 */
14945 public boolean isRootNamespace() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014946 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014947 }
14948
14949 /**
14950 * Returns this view's identifier.
14951 *
14952 * @return a positive integer used to identify the view or {@link #NO_ID}
14953 * if the view has no ID
14954 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014955 * @see #setId(int)
14956 * @see #findViewById(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014957 * @attr ref android.R.styleable#View_id
14958 */
14959 @ViewDebug.CapturedViewProperty
14960 public int getId() {
14961 return mID;
14962 }
14963
14964 /**
14965 * Returns this view's tag.
14966 *
14967 * @return the Object stored in this view as a tag
Romain Guyd90a3312009-05-06 14:54:28 -070014968 *
14969 * @see #setTag(Object)
14970 * @see #getTag(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014971 */
14972 @ViewDebug.ExportedProperty
14973 public Object getTag() {
14974 return mTag;
14975 }
14976
14977 /**
14978 * Sets the tag associated with this view. A tag can be used to mark
14979 * a view in its hierarchy and does not have to be unique within the
14980 * hierarchy. Tags can also be used to store data within a view without
14981 * resorting to another data structure.
14982 *
14983 * @param tag an Object to tag the view with
Romain Guyd90a3312009-05-06 14:54:28 -070014984 *
14985 * @see #getTag()
14986 * @see #setTag(int, Object)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014987 */
14988 public void setTag(final Object tag) {
14989 mTag = tag;
14990 }
14991
14992 /**
Romain Guyd90a3312009-05-06 14:54:28 -070014993 * Returns the tag associated with this view and the specified key.
14994 *
14995 * @param key The key identifying the tag
14996 *
14997 * @return the Object stored in this view as a tag
14998 *
14999 * @see #setTag(int, Object)
Romain Guy8506ab42009-06-11 17:35:47 -070015000 * @see #getTag()
Romain Guyd90a3312009-05-06 14:54:28 -070015001 */
15002 public Object getTag(int key) {
Adam Powell7db82ac2011-09-22 19:44:04 -070015003 if (mKeyedTags != null) return mKeyedTags.get(key);
Romain Guyd90a3312009-05-06 14:54:28 -070015004 return null;
15005 }
15006
15007 /**
15008 * Sets a tag associated with this view and a key. A tag can be used
15009 * to mark a view in its hierarchy and does not have to be unique within
15010 * the hierarchy. Tags can also be used to store data within a view
15011 * without resorting to another data structure.
15012 *
15013 * The specified key should be an id declared in the resources of the
Scott Maindfe5c202010-06-08 15:54:52 -070015014 * application to ensure it is unique (see the <a
15015 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
15016 * Keys identified as belonging to
Romain Guyd90a3312009-05-06 14:54:28 -070015017 * the Android framework or not associated with any package will cause
15018 * an {@link IllegalArgumentException} to be thrown.
15019 *
15020 * @param key The key identifying the tag
15021 * @param tag An Object to tag the view with
15022 *
15023 * @throws IllegalArgumentException If they specified key is not valid
15024 *
15025 * @see #setTag(Object)
15026 * @see #getTag(int)
15027 */
15028 public void setTag(int key, final Object tag) {
15029 // If the package id is 0x00 or 0x01, it's either an undefined package
15030 // or a framework id
15031 if ((key >>> 24) < 2) {
15032 throw new IllegalArgumentException("The key must be an application-specific "
15033 + "resource id.");
15034 }
15035
Adam Powell2b2f6d62011-09-23 11:15:39 -070015036 setKeyedTag(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070015037 }
15038
15039 /**
15040 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
15041 * framework id.
15042 *
15043 * @hide
15044 */
15045 public void setTagInternal(int key, Object tag) {
15046 if ((key >>> 24) != 0x1) {
15047 throw new IllegalArgumentException("The key must be a framework-specific "
15048 + "resource id.");
15049 }
15050
Adam Powell2b2f6d62011-09-23 11:15:39 -070015051 setKeyedTag(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070015052 }
15053
Adam Powell2b2f6d62011-09-23 11:15:39 -070015054 private void setKeyedTag(int key, Object tag) {
Adam Powell7db82ac2011-09-22 19:44:04 -070015055 if (mKeyedTags == null) {
15056 mKeyedTags = new SparseArray<Object>();
Romain Guyd90a3312009-05-06 14:54:28 -070015057 }
15058
Adam Powell7db82ac2011-09-22 19:44:04 -070015059 mKeyedTags.put(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070015060 }
15061
15062 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015063 * Prints information about this view in the log output, with the tag
15064 * {@link #VIEW_LOG_TAG}.
15065 *
15066 * @hide
15067 */
15068 public void debug() {
15069 debug(0);
15070 }
15071
15072 /**
15073 * Prints information about this view in the log output, with the tag
15074 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
15075 * indentation defined by the <code>depth</code>.
15076 *
15077 * @param depth the indentation level
15078 *
15079 * @hide
15080 */
15081 protected void debug(int depth) {
15082 String output = debugIndent(depth - 1);
15083
15084 output += "+ " + this;
15085 int id = getId();
15086 if (id != -1) {
15087 output += " (id=" + id + ")";
15088 }
15089 Object tag = getTag();
15090 if (tag != null) {
15091 output += " (tag=" + tag + ")";
15092 }
15093 Log.d(VIEW_LOG_TAG, output);
15094
Dianne Hackborn4702a852012-08-17 15:18:29 -070015095 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015096 output = debugIndent(depth) + " FOCUSED";
15097 Log.d(VIEW_LOG_TAG, output);
15098 }
15099
15100 output = debugIndent(depth);
15101 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
15102 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
15103 + "} ";
15104 Log.d(VIEW_LOG_TAG, output);
15105
15106 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
15107 || mPaddingBottom != 0) {
15108 output = debugIndent(depth);
15109 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
15110 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
15111 Log.d(VIEW_LOG_TAG, output);
15112 }
15113
15114 output = debugIndent(depth);
15115 output += "mMeasureWidth=" + mMeasuredWidth +
15116 " mMeasureHeight=" + mMeasuredHeight;
15117 Log.d(VIEW_LOG_TAG, output);
15118
15119 output = debugIndent(depth);
15120 if (mLayoutParams == null) {
15121 output += "BAD! no layout params";
15122 } else {
15123 output = mLayoutParams.debug(output);
15124 }
15125 Log.d(VIEW_LOG_TAG, output);
15126
15127 output = debugIndent(depth);
15128 output += "flags={";
15129 output += View.printFlags(mViewFlags);
15130 output += "}";
15131 Log.d(VIEW_LOG_TAG, output);
15132
15133 output = debugIndent(depth);
15134 output += "privateFlags={";
15135 output += View.printPrivateFlags(mPrivateFlags);
15136 output += "}";
15137 Log.d(VIEW_LOG_TAG, output);
15138 }
15139
15140 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090015141 * Creates a string of whitespaces used for indentation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015142 *
15143 * @param depth the indentation level
15144 * @return a String containing (depth * 2 + 3) * 2 white spaces
15145 *
15146 * @hide
15147 */
15148 protected static String debugIndent(int depth) {
15149 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
15150 for (int i = 0; i < (depth * 2) + 3; i++) {
15151 spaces.append(' ').append(' ');
15152 }
15153 return spaces.toString();
15154 }
15155
15156 /**
15157 * <p>Return the offset of the widget's text baseline from the widget's top
15158 * boundary. If this widget does not support baseline alignment, this
15159 * method returns -1. </p>
15160 *
15161 * @return the offset of the baseline within the widget's bounds or -1
15162 * if baseline alignment is not supported
15163 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070015164 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015165 public int getBaseline() {
15166 return -1;
15167 }
15168
15169 /**
15170 * Call this when something has changed which has invalidated the
15171 * layout of this view. This will schedule a layout pass of the view
15172 * tree.
15173 */
15174 public void requestLayout() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015175 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15176 mPrivateFlags |= PFLAG_INVALIDATED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015177
Fabrice Di Meglio4a5268852012-03-30 15:56:48 -070015178 if (mParent != null && !mParent.isLayoutRequested()) {
15179 mParent.requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015180 }
15181 }
15182
15183 /**
15184 * Forces this view to be laid out during the next layout pass.
15185 * This method does not call requestLayout() or forceLayout()
15186 * on the parent.
15187 */
15188 public void forceLayout() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015189 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15190 mPrivateFlags |= PFLAG_INVALIDATED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015191 }
15192
15193 /**
15194 * <p>
15195 * This is called to find out how big a view should be. The parent
15196 * supplies constraint information in the width and height parameters.
15197 * </p>
15198 *
15199 * <p>
Romain Guy967e2bf2012-02-07 17:04:34 -080015200 * The actual measurement work of a view is performed in
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015201 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
Romain Guy967e2bf2012-02-07 17:04:34 -080015202 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015203 * </p>
15204 *
15205 *
15206 * @param widthMeasureSpec Horizontal space requirements as imposed by the
15207 * parent
15208 * @param heightMeasureSpec Vertical space requirements as imposed by the
15209 * parent
15210 *
15211 * @see #onMeasure(int, int)
15212 */
15213 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015214 if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015215 widthMeasureSpec != mOldWidthMeasureSpec ||
15216 heightMeasureSpec != mOldHeightMeasureSpec) {
15217
15218 // first clears the measured dimension flag
Dianne Hackborn4702a852012-08-17 15:18:29 -070015219 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015220
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070015221 if (!isPaddingResolved()) {
Adam Powell0090f202012-08-07 17:15:30 -070015222 resolvePadding();
15223 }
15224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015225 // measure ourselves, this should set the measured dimension flag back
15226 onMeasure(widthMeasureSpec, heightMeasureSpec);
15227
15228 // flag not set, setMeasuredDimension() was not invoked, we raise
15229 // an exception to warn the developer
Dianne Hackborn4702a852012-08-17 15:18:29 -070015230 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015231 throw new IllegalStateException("onMeasure() did not set the"
15232 + " measured dimension by calling"
15233 + " setMeasuredDimension()");
15234 }
15235
Dianne Hackborn4702a852012-08-17 15:18:29 -070015236 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015237 }
15238
15239 mOldWidthMeasureSpec = widthMeasureSpec;
15240 mOldHeightMeasureSpec = heightMeasureSpec;
15241 }
15242
15243 /**
15244 * <p>
15245 * Measure the view and its content to determine the measured width and the
15246 * measured height. This method is invoked by {@link #measure(int, int)} and
15247 * should be overriden by subclasses to provide accurate and efficient
15248 * measurement of their contents.
15249 * </p>
15250 *
15251 * <p>
15252 * <strong>CONTRACT:</strong> When overriding this method, you
15253 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15254 * measured width and height of this view. Failure to do so will trigger an
15255 * <code>IllegalStateException</code>, thrown by
15256 * {@link #measure(int, int)}. Calling the superclass'
15257 * {@link #onMeasure(int, int)} is a valid use.
15258 * </p>
15259 *
15260 * <p>
15261 * The base class implementation of measure defaults to the background size,
15262 * unless a larger size is allowed by the MeasureSpec. Subclasses should
15263 * override {@link #onMeasure(int, int)} to provide better measurements of
15264 * their content.
15265 * </p>
15266 *
15267 * <p>
15268 * If this method is overridden, it is the subclass's responsibility to make
15269 * sure the measured height and width are at least the view's minimum height
15270 * and width ({@link #getSuggestedMinimumHeight()} and
15271 * {@link #getSuggestedMinimumWidth()}).
15272 * </p>
15273 *
15274 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15275 * The requirements are encoded with
15276 * {@link android.view.View.MeasureSpec}.
15277 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15278 * The requirements are encoded with
15279 * {@link android.view.View.MeasureSpec}.
15280 *
15281 * @see #getMeasuredWidth()
15282 * @see #getMeasuredHeight()
15283 * @see #setMeasuredDimension(int, int)
15284 * @see #getSuggestedMinimumHeight()
15285 * @see #getSuggestedMinimumWidth()
15286 * @see android.view.View.MeasureSpec#getMode(int)
15287 * @see android.view.View.MeasureSpec#getSize(int)
15288 */
15289 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15290 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15291 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15292 }
15293
15294 /**
15295 * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
15296 * measured width and measured height. Failing to do so will trigger an
15297 * exception at measurement time.</p>
15298 *
Dianne Hackborn189ee182010-12-02 21:48:53 -080015299 * @param measuredWidth The measured width of this view. May be a complex
15300 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15301 * {@link #MEASURED_STATE_TOO_SMALL}.
15302 * @param measuredHeight The measured height of this view. May be a complex
15303 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15304 * {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015305 */
15306 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15307 mMeasuredWidth = measuredWidth;
15308 mMeasuredHeight = measuredHeight;
15309
Dianne Hackborn4702a852012-08-17 15:18:29 -070015310 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015311 }
15312
15313 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -080015314 * Merge two states as returned by {@link #getMeasuredState()}.
15315 * @param curState The current state as returned from a view or the result
15316 * of combining multiple views.
15317 * @param newState The new view state to combine.
15318 * @return Returns a new integer reflecting the combination of the two
15319 * states.
15320 */
15321 public static int combineMeasuredStates(int curState, int newState) {
15322 return curState | newState;
15323 }
15324
15325 /**
15326 * Version of {@link #resolveSizeAndState(int, int, int)}
15327 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15328 */
15329 public static int resolveSize(int size, int measureSpec) {
15330 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15331 }
15332
15333 /**
15334 * Utility to reconcile a desired size and state, with constraints imposed
15335 * by a MeasureSpec. Will take the desired size, unless a different size
15336 * is imposed by the constraints. The returned value is a compound integer,
15337 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15338 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15339 * size is smaller than the size the view wants to be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015340 *
15341 * @param size How big the view wants to be
15342 * @param measureSpec Constraints imposed by the parent
Dianne Hackborn189ee182010-12-02 21:48:53 -080015343 * @return Size information bit mask as defined by
15344 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015345 */
Dianne Hackborn189ee182010-12-02 21:48:53 -080015346 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015347 int result = size;
15348 int specMode = MeasureSpec.getMode(measureSpec);
15349 int specSize = MeasureSpec.getSize(measureSpec);
15350 switch (specMode) {
15351 case MeasureSpec.UNSPECIFIED:
15352 result = size;
15353 break;
15354 case MeasureSpec.AT_MOST:
Dianne Hackborn189ee182010-12-02 21:48:53 -080015355 if (specSize < size) {
15356 result = specSize | MEASURED_STATE_TOO_SMALL;
15357 } else {
15358 result = size;
15359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015360 break;
15361 case MeasureSpec.EXACTLY:
15362 result = specSize;
15363 break;
15364 }
Dianne Hackborn189ee182010-12-02 21:48:53 -080015365 return result | (childMeasuredState&MEASURED_STATE_MASK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015366 }
15367
15368 /**
15369 * Utility to return a default size. Uses the supplied size if the
Romain Guy98029c82011-06-17 15:47:07 -070015370 * MeasureSpec imposed no constraints. Will get larger if allowed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015371 * by the MeasureSpec.
15372 *
15373 * @param size Default size for this view
15374 * @param measureSpec Constraints imposed by the parent
15375 * @return The size this view should be.
15376 */
15377 public static int getDefaultSize(int size, int measureSpec) {
15378 int result = size;
15379 int specMode = MeasureSpec.getMode(measureSpec);
Romain Guy98029c82011-06-17 15:47:07 -070015380 int specSize = MeasureSpec.getSize(measureSpec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015381
15382 switch (specMode) {
15383 case MeasureSpec.UNSPECIFIED:
15384 result = size;
15385 break;
15386 case MeasureSpec.AT_MOST:
15387 case MeasureSpec.EXACTLY:
15388 result = specSize;
15389 break;
15390 }
15391 return result;
15392 }
15393
15394 /**
15395 * Returns the suggested minimum height that the view should use. This
15396 * returns the maximum of the view's minimum height
15397 * and the background's minimum height
15398 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
15399 * <p>
15400 * When being used in {@link #onMeasure(int, int)}, the caller should still
15401 * ensure the returned height is within the requirements of the parent.
15402 *
15403 * @return The suggested minimum height of the view.
15404 */
15405 protected int getSuggestedMinimumHeight() {
Philip Milne6c8ea062012-04-03 17:38:43 -070015406 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015407
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015408 }
15409
15410 /**
15411 * Returns the suggested minimum width that the view should use. This
15412 * returns the maximum of the view's minimum width)
15413 * and the background's minimum width
15414 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
15415 * <p>
15416 * When being used in {@link #onMeasure(int, int)}, the caller should still
15417 * ensure the returned width is within the requirements of the parent.
15418 *
15419 * @return The suggested minimum width of the view.
15420 */
15421 protected int getSuggestedMinimumWidth() {
Philip Milne6c8ea062012-04-03 17:38:43 -070015422 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
15423 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015424
Philip Milne6c8ea062012-04-03 17:38:43 -070015425 /**
15426 * Returns the minimum height of the view.
15427 *
15428 * @return the minimum height the view will try to be.
15429 *
15430 * @see #setMinimumHeight(int)
15431 *
15432 * @attr ref android.R.styleable#View_minHeight
15433 */
15434 public int getMinimumHeight() {
15435 return mMinHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015436 }
15437
15438 /**
15439 * Sets the minimum height of the view. It is not guaranteed the view will
15440 * be able to achieve this minimum height (for example, if its parent layout
15441 * constrains it with less available height).
15442 *
15443 * @param minHeight The minimum height the view will try to be.
Philip Milne6c8ea062012-04-03 17:38:43 -070015444 *
15445 * @see #getMinimumHeight()
15446 *
15447 * @attr ref android.R.styleable#View_minHeight
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015448 */
15449 public void setMinimumHeight(int minHeight) {
15450 mMinHeight = minHeight;
Philip Milne6c8ea062012-04-03 17:38:43 -070015451 requestLayout();
15452 }
15453
15454 /**
15455 * Returns the minimum width of the view.
15456 *
15457 * @return the minimum width the view will try to be.
15458 *
15459 * @see #setMinimumWidth(int)
15460 *
15461 * @attr ref android.R.styleable#View_minWidth
15462 */
15463 public int getMinimumWidth() {
15464 return mMinWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015465 }
15466
15467 /**
15468 * Sets the minimum width of the view. It is not guaranteed the view will
15469 * be able to achieve this minimum width (for example, if its parent layout
15470 * constrains it with less available width).
15471 *
15472 * @param minWidth The minimum width the view will try to be.
Philip Milne6c8ea062012-04-03 17:38:43 -070015473 *
15474 * @see #getMinimumWidth()
15475 *
15476 * @attr ref android.R.styleable#View_minWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015477 */
15478 public void setMinimumWidth(int minWidth) {
15479 mMinWidth = minWidth;
Philip Milne6c8ea062012-04-03 17:38:43 -070015480 requestLayout();
15481
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015482 }
15483
15484 /**
15485 * Get the animation currently associated with this view.
15486 *
15487 * @return The animation that is currently playing or
15488 * scheduled to play for this view.
15489 */
15490 public Animation getAnimation() {
15491 return mCurrentAnimation;
15492 }
15493
15494 /**
15495 * Start the specified animation now.
15496 *
15497 * @param animation the animation to start now
15498 */
15499 public void startAnimation(Animation animation) {
15500 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
15501 setAnimation(animation);
Romain Guy0fd89bf2011-01-26 15:41:30 -080015502 invalidateParentCaches();
15503 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015504 }
15505
15506 /**
15507 * Cancels any animations for this view.
15508 */
15509 public void clearAnimation() {
Romain Guy305a2eb2010-02-09 11:30:44 -080015510 if (mCurrentAnimation != null) {
Romain Guyb4a107d2010-02-09 18:50:08 -080015511 mCurrentAnimation.detach();
Romain Guy305a2eb2010-02-09 11:30:44 -080015512 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015513 mCurrentAnimation = null;
Romain Guy0fd89bf2011-01-26 15:41:30 -080015514 invalidateParentIfNeeded();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015515 }
15516
15517 /**
15518 * Sets the next animation to play for this view.
15519 * If you want the animation to play immediately, use
Chet Haase42428932012-05-11 15:39:07 -070015520 * {@link #startAnimation(android.view.animation.Animation)} instead.
15521 * This method provides allows fine-grained
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015522 * control over the start time and invalidation, but you
15523 * must make sure that 1) the animation has a start time set, and
Chet Haase42428932012-05-11 15:39:07 -070015524 * 2) the view's parent (which controls animations on its children)
15525 * will be invalidated when the animation is supposed to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015526 * start.
15527 *
15528 * @param animation The next animation, or null.
15529 */
15530 public void setAnimation(Animation animation) {
15531 mCurrentAnimation = animation;
Romain Guyeb378892012-04-12 11:33:14 -070015532
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015533 if (animation != null) {
Romain Guyeb378892012-04-12 11:33:14 -070015534 // If the screen is off assume the animation start time is now instead of
15535 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
15536 // would cause the animation to start when the screen turns back on
15537 if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
15538 animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
15539 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
15540 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015541 animation.reset();
15542 }
15543 }
15544
15545 /**
15546 * Invoked by a parent ViewGroup to notify the start of the animation
15547 * currently associated with this view. If you override this method,
15548 * always call super.onAnimationStart();
15549 *
15550 * @see #setAnimation(android.view.animation.Animation)
15551 * @see #getAnimation()
15552 */
15553 protected void onAnimationStart() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015554 mPrivateFlags |= PFLAG_ANIMATION_STARTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015555 }
15556
15557 /**
15558 * Invoked by a parent ViewGroup to notify the end of the animation
15559 * currently associated with this view. If you override this method,
15560 * always call super.onAnimationEnd();
15561 *
15562 * @see #setAnimation(android.view.animation.Animation)
15563 * @see #getAnimation()
15564 */
15565 protected void onAnimationEnd() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015566 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015567 }
15568
15569 /**
15570 * Invoked if there is a Transform that involves alpha. Subclass that can
15571 * draw themselves with the specified alpha should return true, and then
15572 * respect that alpha when their onDraw() is called. If this returns false
15573 * then the view may be redirected to draw into an offscreen buffer to
15574 * fulfill the request, which will look fine, but may be slower than if the
15575 * subclass handles it internally. The default implementation returns false.
15576 *
15577 * @param alpha The alpha (0..255) to apply to the view's drawing
15578 * @return true if the view can draw with the specified alpha.
15579 */
15580 protected boolean onSetAlpha(int alpha) {
15581 return false;
15582 }
15583
15584 /**
15585 * This is used by the RootView to perform an optimization when
15586 * the view hierarchy contains one or several SurfaceView.
15587 * SurfaceView is always considered transparent, but its children are not,
15588 * therefore all View objects remove themselves from the global transparent
15589 * region (passed as a parameter to this function).
15590 *
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070015591 * @param region The transparent region for this ViewAncestor (window).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015592 *
15593 * @return Returns true if the effective visibility of the view at this
15594 * point is opaque, regardless of the transparent region; returns false
15595 * if it is possible for underlying windows to be seen behind the view.
15596 *
15597 * {@hide}
15598 */
15599 public boolean gatherTransparentRegion(Region region) {
15600 final AttachInfo attachInfo = mAttachInfo;
15601 if (region != null && attachInfo != null) {
15602 final int pflags = mPrivateFlags;
Dianne Hackborn4702a852012-08-17 15:18:29 -070015603 if ((pflags & PFLAG_SKIP_DRAW) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015604 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
15605 // remove it from the transparent region.
15606 final int[] location = attachInfo.mTransparentLocation;
15607 getLocationInWindow(location);
15608 region.op(location[0], location[1], location[0] + mRight - mLeft,
15609 location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
Dianne Hackborn4702a852012-08-17 15:18:29 -070015610 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015611 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
15612 // exists, so we remove the background drawable's non-transparent
15613 // parts from this transparent region.
Philip Milne6c8ea062012-04-03 17:38:43 -070015614 applyDrawableToTransparentRegion(mBackground, region);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015615 }
15616 }
15617 return true;
15618 }
15619
15620 /**
15621 * Play a sound effect for this view.
15622 *
15623 * <p>The framework will play sound effects for some built in actions, such as
15624 * clicking, but you may wish to play these effects in your widget,
15625 * for instance, for internal navigation.
15626 *
15627 * <p>The sound effect will only be played if sound effects are enabled by the user, and
15628 * {@link #isSoundEffectsEnabled()} is true.
15629 *
15630 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
15631 */
15632 public void playSoundEffect(int soundConstant) {
15633 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
15634 return;
15635 }
15636 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
15637 }
15638
15639 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015640 * BZZZTT!!1!
Romain Guy8506ab42009-06-11 17:35:47 -070015641 *
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015642 * <p>Provide haptic feedback to the user for this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015643 *
15644 * <p>The framework will provide haptic feedback for some built in actions,
15645 * such as long presses, but you may wish to provide feedback for your
15646 * own widget.
15647 *
15648 * <p>The feedback will only be performed if
15649 * {@link #isHapticFeedbackEnabled()} is true.
15650 *
15651 * @param feedbackConstant One of the constants defined in
15652 * {@link HapticFeedbackConstants}
15653 */
15654 public boolean performHapticFeedback(int feedbackConstant) {
15655 return performHapticFeedback(feedbackConstant, 0);
15656 }
15657
15658 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015659 * BZZZTT!!1!
Romain Guy8506ab42009-06-11 17:35:47 -070015660 *
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015661 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015662 *
15663 * @param feedbackConstant One of the constants defined in
15664 * {@link HapticFeedbackConstants}
15665 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
15666 */
15667 public boolean performHapticFeedback(int feedbackConstant, int flags) {
15668 if (mAttachInfo == null) {
15669 return false;
15670 }
Romain Guyf607bdc2010-09-10 19:20:06 -070015671 //noinspection SimplifiableIfStatement
Romain Guy812ccbe2010-06-01 14:07:24 -070015672 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015673 && !isHapticFeedbackEnabled()) {
15674 return false;
15675 }
Romain Guy812ccbe2010-06-01 14:07:24 -070015676 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
15677 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015678 }
15679
15680 /**
Dianne Hackborn98014352012-04-05 18:31:41 -070015681 * Request that the visibility of the status bar or other screen/window
15682 * decorations be changed.
15683 *
15684 * <p>This method is used to put the over device UI into temporary modes
15685 * where the user's attention is focused more on the application content,
15686 * by dimming or hiding surrounding system affordances. This is typically
15687 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
15688 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
15689 * to be placed behind the action bar (and with these flags other system
15690 * affordances) so that smooth transitions between hiding and showing them
15691 * can be done.
15692 *
15693 * <p>Two representative examples of the use of system UI visibility is
15694 * implementing a content browsing application (like a magazine reader)
15695 * and a video playing application.
15696 *
15697 * <p>The first code shows a typical implementation of a View in a content
15698 * browsing application. In this implementation, the application goes
15699 * into a content-oriented mode by hiding the status bar and action bar,
15700 * and putting the navigation elements into lights out mode. The user can
15701 * then interact with content while in this mode. Such an application should
15702 * provide an easy way for the user to toggle out of the mode (such as to
15703 * check information in the status bar or access notifications). In the
15704 * implementation here, this is done simply by tapping on the content.
15705 *
15706 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
15707 * content}
15708 *
15709 * <p>This second code sample shows a typical implementation of a View
15710 * in a video playing application. In this situation, while the video is
15711 * playing the application would like to go into a complete full-screen mode,
15712 * to use as much of the display as possible for the video. When in this state
15713 * the user can not interact with the application; the system intercepts
Dianne Hackborncf675782012-05-10 15:07:24 -070015714 * touching on the screen to pop the UI out of full screen mode. See
15715 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
Dianne Hackborn98014352012-04-05 18:31:41 -070015716 *
15717 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
15718 * content}
15719 *
15720 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15721 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15722 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15723 * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
Joe Onorato664644d2011-01-23 17:53:23 -080015724 */
15725 public void setSystemUiVisibility(int visibility) {
Daniel Sandler70524062011-09-21 00:30:47 -040015726 if (visibility != mSystemUiVisibility) {
15727 mSystemUiVisibility = visibility;
15728 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15729 mParent.recomputeViewAttributes(this);
15730 }
Joe Onorato664644d2011-01-23 17:53:23 -080015731 }
15732 }
15733
15734 /**
Dianne Hackborn98014352012-04-05 18:31:41 -070015735 * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
15736 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15737 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15738 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15739 * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
Joe Onorato664644d2011-01-23 17:53:23 -080015740 */
Joe Onoratoe595cad2011-01-24 09:22:12 -080015741 public int getSystemUiVisibility() {
Joe Onorato664644d2011-01-23 17:53:23 -080015742 return mSystemUiVisibility;
15743 }
15744
Scott Mainec6331b2011-05-24 16:55:56 -070015745 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070015746 * Returns the current system UI visibility that is currently set for
15747 * the entire window. This is the combination of the
15748 * {@link #setSystemUiVisibility(int)} values supplied by all of the
15749 * views in the window.
15750 */
15751 public int getWindowSystemUiVisibility() {
15752 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
15753 }
15754
15755 /**
15756 * Override to find out when the window's requested system UI visibility
15757 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
15758 * This is different from the callbacks recieved through
15759 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
15760 * in that this is only telling you about the local request of the window,
15761 * not the actual values applied by the system.
15762 */
15763 public void onWindowSystemUiVisibilityChanged(int visible) {
15764 }
15765
15766 /**
15767 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
15768 * the view hierarchy.
15769 */
15770 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
15771 onWindowSystemUiVisibilityChanged(visible);
15772 }
15773
15774 /**
Scott Mainec6331b2011-05-24 16:55:56 -070015775 * Set a listener to receive callbacks when the visibility of the system bar changes.
15776 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
15777 */
Joe Onorato664644d2011-01-23 17:53:23 -080015778 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015779 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
Joe Onorato664644d2011-01-23 17:53:23 -080015780 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15781 mParent.recomputeViewAttributes(this);
15782 }
15783 }
15784
15785 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015786 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
15787 * the view hierarchy.
Joe Onorato664644d2011-01-23 17:53:23 -080015788 */
15789 public void dispatchSystemUiVisibilityChanged(int visibility) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015790 ListenerInfo li = mListenerInfo;
15791 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15792 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
Joe Onorato6ab77bd2011-01-31 11:21:10 -080015793 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
Joe Onorato664644d2011-01-23 17:53:23 -080015794 }
15795 }
15796
Dianne Hackborncf675782012-05-10 15:07:24 -070015797 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015798 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
15799 if (val != mSystemUiVisibility) {
15800 setSystemUiVisibility(val);
Dianne Hackborncf675782012-05-10 15:07:24 -070015801 return true;
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015802 }
Dianne Hackborncf675782012-05-10 15:07:24 -070015803 return false;
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015804 }
15805
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070015806 /** @hide */
15807 public void setDisabledSystemUiVisibility(int flags) {
15808 if (mAttachInfo != null) {
15809 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
15810 mAttachInfo.mDisabledSystemUiVisibility = flags;
15811 if (mParent != null) {
15812 mParent.recomputeViewAttributes(this);
15813 }
15814 }
15815 }
15816 }
15817
Joe Onorato664644d2011-01-23 17:53:23 -080015818 /**
Joe Malin32736f02011-01-19 16:14:20 -080015819 * Creates an image that the system displays during the drag and drop
15820 * operation. This is called a &quot;drag shadow&quot;. The default implementation
15821 * for a DragShadowBuilder based on a View returns an image that has exactly the same
15822 * appearance as the given View. The default also positions the center of the drag shadow
15823 * directly under the touch point. If no View is provided (the constructor with no parameters
15824 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
15825 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
15826 * default is an invisible drag shadow.
15827 * <p>
15828 * You are not required to use the View you provide to the constructor as the basis of the
15829 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
15830 * anything you want as the drag shadow.
15831 * </p>
15832 * <p>
15833 * You pass a DragShadowBuilder object to the system when you start the drag. The system
15834 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
15835 * size and position of the drag shadow. It uses this data to construct a
15836 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
15837 * so that your application can draw the shadow image in the Canvas.
15838 * </p>
Joe Fernandez558459f2011-10-13 16:47:36 -070015839 *
15840 * <div class="special reference">
15841 * <h3>Developer Guides</h3>
15842 * <p>For a guide to implementing drag and drop features, read the
15843 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
15844 * </div>
Christopher Tate2c095f32010-10-04 14:13:40 -070015845 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015846 public static class DragShadowBuilder {
Christopher Tatea0374192010-10-05 13:06:41 -070015847 private final WeakReference<View> mView;
Christopher Tate2c095f32010-10-04 14:13:40 -070015848
15849 /**
Joe Malin32736f02011-01-19 16:14:20 -080015850 * Constructs a shadow image builder based on a View. By default, the resulting drag
15851 * shadow will have the same appearance and dimensions as the View, with the touch point
15852 * over the center of the View.
15853 * @param view A View. Any View in scope can be used.
Christopher Tate2c095f32010-10-04 14:13:40 -070015854 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015855 public DragShadowBuilder(View view) {
Christopher Tatea0374192010-10-05 13:06:41 -070015856 mView = new WeakReference<View>(view);
Christopher Tate2c095f32010-10-04 14:13:40 -070015857 }
15858
Christopher Tate17ed60c2011-01-18 12:50:26 -080015859 /**
15860 * Construct a shadow builder object with no associated View. This
15861 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
15862 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
15863 * to supply the drag shadow's dimensions and appearance without
Joe Malin32736f02011-01-19 16:14:20 -080015864 * reference to any View object. If they are not overridden, then the result is an
15865 * invisible drag shadow.
Christopher Tate17ed60c2011-01-18 12:50:26 -080015866 */
15867 public DragShadowBuilder() {
15868 mView = new WeakReference<View>(null);
15869 }
15870
15871 /**
15872 * Returns the View object that had been passed to the
15873 * {@link #View.DragShadowBuilder(View)}
15874 * constructor. If that View parameter was {@code null} or if the
15875 * {@link #View.DragShadowBuilder()}
15876 * constructor was used to instantiate the builder object, this method will return
15877 * null.
15878 *
15879 * @return The View object associate with this builder object.
15880 */
Romain Guy5c22a8c2011-05-13 11:48:45 -070015881 @SuppressWarnings({"JavadocReference"})
Chris Tate6b391282010-10-14 15:48:59 -070015882 final public View getView() {
15883 return mView.get();
15884 }
15885
Christopher Tate2c095f32010-10-04 14:13:40 -070015886 /**
Joe Malin32736f02011-01-19 16:14:20 -080015887 * Provides the metrics for the shadow image. These include the dimensions of
15888 * the shadow image, and the point within that shadow that should
Christopher Tate2c095f32010-10-04 14:13:40 -070015889 * be centered under the touch location while dragging.
15890 * <p>
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015891 * The default implementation sets the dimensions of the shadow to be the
Joe Malin32736f02011-01-19 16:14:20 -080015892 * same as the dimensions of the View itself and centers the shadow under
15893 * the touch point.
15894 * </p>
Christopher Tate2c095f32010-10-04 14:13:40 -070015895 *
Joe Malin32736f02011-01-19 16:14:20 -080015896 * @param shadowSize A {@link android.graphics.Point} containing the width and height
15897 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
15898 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
15899 * image.
15900 *
15901 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
15902 * shadow image that should be underneath the touch point during the drag and drop
15903 * operation. Your application must set {@link android.graphics.Point#x} to the
15904 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
Christopher Tate2c095f32010-10-04 14:13:40 -070015905 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015906 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
Christopher Tatea0374192010-10-05 13:06:41 -070015907 final View view = mView.get();
15908 if (view != null) {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015909 shadowSize.set(view.getWidth(), view.getHeight());
15910 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
Christopher Tatea0374192010-10-05 13:06:41 -070015911 } else {
15912 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
15913 }
Christopher Tate2c095f32010-10-04 14:13:40 -070015914 }
15915
15916 /**
Joe Malin32736f02011-01-19 16:14:20 -080015917 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
15918 * based on the dimensions it received from the
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015919 * {@link #onProvideShadowMetrics(Point, Point)} callback.
Christopher Tate2c095f32010-10-04 14:13:40 -070015920 *
Joe Malin32736f02011-01-19 16:14:20 -080015921 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
Christopher Tate2c095f32010-10-04 14:13:40 -070015922 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015923 public void onDrawShadow(Canvas canvas) {
Christopher Tatea0374192010-10-05 13:06:41 -070015924 final View view = mView.get();
15925 if (view != null) {
15926 view.draw(canvas);
15927 } else {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015928 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
Christopher Tatea0374192010-10-05 13:06:41 -070015929 }
Christopher Tate2c095f32010-10-04 14:13:40 -070015930 }
15931 }
15932
15933 /**
Joe Malin32736f02011-01-19 16:14:20 -080015934 * Starts a drag and drop operation. When your application calls this method, it passes a
15935 * {@link android.view.View.DragShadowBuilder} object to the system. The
15936 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
15937 * to get metrics for the drag shadow, and then calls the object's
15938 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
15939 * <p>
15940 * Once the system has the drag shadow, it begins the drag and drop operation by sending
15941 * drag events to all the View objects in your application that are currently visible. It does
15942 * this either by calling the View object's drag listener (an implementation of
15943 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
15944 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
15945 * Both are passed a {@link android.view.DragEvent} object that has a
15946 * {@link android.view.DragEvent#getAction()} value of
15947 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
15948 * </p>
15949 * <p>
15950 * Your application can invoke startDrag() on any attached View object. The View object does not
15951 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
15952 * be related to the View the user selected for dragging.
15953 * </p>
15954 * @param data A {@link android.content.ClipData} object pointing to the data to be
15955 * transferred by the drag and drop operation.
15956 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
15957 * drag shadow.
15958 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
15959 * drop operation. This Object is put into every DragEvent object sent by the system during the
15960 * current drag.
15961 * <p>
15962 * myLocalState is a lightweight mechanism for the sending information from the dragged View
15963 * to the target Views. For example, it can contain flags that differentiate between a
15964 * a copy operation and a move operation.
15965 * </p>
15966 * @param flags Flags that control the drag and drop operation. No flags are currently defined,
15967 * so the parameter should be set to 0.
15968 * @return {@code true} if the method completes successfully, or
15969 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
15970 * do a drag, and so no drag operation is in progress.
Christopher Tatea53146c2010-09-07 11:57:52 -070015971 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015972 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015973 Object myLocalState, int flags) {
Christopher Tate2c095f32010-10-04 14:13:40 -070015974 if (ViewDebug.DEBUG_DRAG) {
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015975 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
Christopher Tatea53146c2010-09-07 11:57:52 -070015976 }
15977 boolean okay = false;
15978
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015979 Point shadowSize = new Point();
15980 Point shadowTouchPoint = new Point();
15981 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
Christopher Tate2c095f32010-10-04 14:13:40 -070015982
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015983 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
15984 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
15985 throw new IllegalStateException("Drag shadow dimensions must not be negative");
Christopher Tate2c095f32010-10-04 14:13:40 -070015986 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015987
Chris Tatea32dcf72010-10-14 12:13:50 -070015988 if (ViewDebug.DEBUG_DRAG) {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015989 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
15990 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
Chris Tatea32dcf72010-10-14 12:13:50 -070015991 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015992 Surface surface = new Surface();
15993 try {
15994 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015995 flags, shadowSize.x, shadowSize.y, surface);
Christopher Tate2c095f32010-10-04 14:13:40 -070015996 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
Christopher Tatea53146c2010-09-07 11:57:52 -070015997 + " surface=" + surface);
15998 if (token != null) {
15999 Canvas canvas = surface.lockCanvas(null);
Romain Guy0bb56672010-10-01 00:25:02 -070016000 try {
Chris Tate6b391282010-10-14 15:48:59 -070016001 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
Christopher Tate36d4c3f2011-01-07 13:34:24 -080016002 shadowBuilder.onDrawShadow(canvas);
Romain Guy0bb56672010-10-01 00:25:02 -070016003 } finally {
16004 surface.unlockCanvasAndPost(canvas);
16005 }
Christopher Tatea53146c2010-09-07 11:57:52 -070016006
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070016007 final ViewRootImpl root = getViewRootImpl();
Christopher Tate407b4e92010-11-30 17:14:08 -080016008
16009 // Cache the local state object for delivery with DragEvents
16010 root.setLocalDragState(myLocalState);
16011
Christopher Tate36d4c3f2011-01-07 13:34:24 -080016012 // repurpose 'shadowSize' for the last touch point
16013 root.getLastTouchPoint(shadowSize);
Christopher Tate2c095f32010-10-04 14:13:40 -070016014
Christopher Tatea53146c2010-09-07 11:57:52 -070016015 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
Christopher Tate36d4c3f2011-01-07 13:34:24 -080016016 shadowSize.x, shadowSize.y,
16017 shadowTouchPoint.x, shadowTouchPoint.y, data);
Christopher Tate2c095f32010-10-04 14:13:40 -070016018 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
Christopher Tate8f73b5d2011-09-12 15:22:12 -070016019
16020 // Off and running! Release our local surface instance; the drag
16021 // shadow surface is now managed by the system process.
16022 surface.release();
Christopher Tatea53146c2010-09-07 11:57:52 -070016023 }
16024 } catch (Exception e) {
16025 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
16026 surface.destroy();
16027 }
16028
16029 return okay;
16030 }
16031
Christopher Tatea53146c2010-09-07 11:57:52 -070016032 /**
Joe Malin32736f02011-01-19 16:14:20 -080016033 * Handles drag events sent by the system following a call to
16034 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
16035 *<p>
16036 * When the system calls this method, it passes a
16037 * {@link android.view.DragEvent} object. A call to
16038 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
16039 * in DragEvent. The method uses these to determine what is happening in the drag and drop
16040 * operation.
16041 * @param event The {@link android.view.DragEvent} sent by the system.
16042 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
16043 * in DragEvent, indicating the type of drag event represented by this object.
16044 * @return {@code true} if the method was successful, otherwise {@code false}.
16045 * <p>
16046 * The method should return {@code true} in response to an action type of
16047 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
16048 * operation.
16049 * </p>
16050 * <p>
16051 * The method should also return {@code true} in response to an action type of
16052 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
16053 * {@code false} if it didn't.
16054 * </p>
Christopher Tatea53146c2010-09-07 11:57:52 -070016055 */
Christopher Tate5ada6cb2010-10-05 14:15:29 -070016056 public boolean onDragEvent(DragEvent event) {
Christopher Tatea53146c2010-09-07 11:57:52 -070016057 return false;
16058 }
16059
16060 /**
Joe Malin32736f02011-01-19 16:14:20 -080016061 * Detects if this View is enabled and has a drag event listener.
16062 * If both are true, then it calls the drag event listener with the
16063 * {@link android.view.DragEvent} it received. If the drag event listener returns
16064 * {@code true}, then dispatchDragEvent() returns {@code true}.
16065 * <p>
16066 * For all other cases, the method calls the
16067 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
16068 * method and returns its result.
16069 * </p>
16070 * <p>
16071 * This ensures that a drag event is always consumed, even if the View does not have a drag
16072 * event listener. However, if the View has a listener and the listener returns true, then
16073 * onDragEvent() is not called.
16074 * </p>
Christopher Tatea53146c2010-09-07 11:57:52 -070016075 */
16076 public boolean dispatchDragEvent(DragEvent event) {
Romain Guy676b1732011-02-14 14:45:33 -080016077 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070016078 ListenerInfo li = mListenerInfo;
16079 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
16080 && li.mOnDragListener.onDrag(this, event)) {
Chris Tate32affef2010-10-18 15:29:21 -070016081 return true;
16082 }
Christopher Tatea53146c2010-09-07 11:57:52 -070016083 return onDragEvent(event);
16084 }
16085
Christopher Tate3d4bf172011-03-28 16:16:46 -070016086 boolean canAcceptDrag() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016087 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
Christopher Tate3d4bf172011-03-28 16:16:46 -070016088 }
16089
Christopher Tatea53146c2010-09-07 11:57:52 -070016090 /**
Dianne Hackbornffa42482009-09-23 22:20:11 -070016091 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
16092 * it is ever exposed at all.
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -070016093 * @hide
Dianne Hackbornffa42482009-09-23 22:20:11 -070016094 */
16095 public void onCloseSystemDialogs(String reason) {
16096 }
Joe Malin32736f02011-01-19 16:14:20 -080016097
Dianne Hackbornffa42482009-09-23 22:20:11 -070016098 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016099 * Given a Drawable whose bounds have been set to draw into this view,
Romain Guy5c22a8c2011-05-13 11:48:45 -070016100 * update a Region being computed for
16101 * {@link #gatherTransparentRegion(android.graphics.Region)} so
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016102 * that any non-transparent parts of the Drawable are removed from the
16103 * given transparent region.
16104 *
16105 * @param dr The Drawable whose transparency is to be applied to the region.
16106 * @param region A Region holding the current transparency information,
16107 * where any parts of the region that are set are considered to be
16108 * transparent. On return, this region will be modified to have the
16109 * transparency information reduced by the corresponding parts of the
16110 * Drawable that are not transparent.
16111 * {@hide}
16112 */
16113 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
16114 if (DBG) {
16115 Log.i("View", "Getting transparent region for: " + this);
16116 }
16117 final Region r = dr.getTransparentRegion();
16118 final Rect db = dr.getBounds();
16119 final AttachInfo attachInfo = mAttachInfo;
16120 if (r != null && attachInfo != null) {
16121 final int w = getRight()-getLeft();
16122 final int h = getBottom()-getTop();
16123 if (db.left > 0) {
16124 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
16125 r.op(0, 0, db.left, h, Region.Op.UNION);
16126 }
16127 if (db.right < w) {
16128 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
16129 r.op(db.right, 0, w, h, Region.Op.UNION);
16130 }
16131 if (db.top > 0) {
16132 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
16133 r.op(0, 0, w, db.top, Region.Op.UNION);
16134 }
16135 if (db.bottom < h) {
16136 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
16137 r.op(0, db.bottom, w, h, Region.Op.UNION);
16138 }
16139 final int[] location = attachInfo.mTransparentLocation;
16140 getLocationInWindow(location);
16141 r.translate(location[0], location[1]);
16142 region.op(r, Region.Op.INTERSECT);
16143 } else {
16144 region.op(db, Region.Op.DIFFERENCE);
16145 }
16146 }
16147
Patrick Dubroye0a799a2011-05-04 16:19:22 -070016148 private void checkForLongClick(int delayOffset) {
16149 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
16150 mHasPerformedLongPress = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016151
Patrick Dubroye0a799a2011-05-04 16:19:22 -070016152 if (mPendingCheckForLongPress == null) {
16153 mPendingCheckForLongPress = new CheckForLongPress();
16154 }
16155 mPendingCheckForLongPress.rememberWindowAttachCount();
16156 postDelayed(mPendingCheckForLongPress,
16157 ViewConfiguration.getLongPressTimeout() - delayOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016158 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016159 }
16160
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016161 /**
16162 * Inflate a view from an XML resource. This convenience method wraps the {@link
16163 * LayoutInflater} class, which provides a full range of options for view inflation.
16164 *
16165 * @param context The Context object for your activity or application.
16166 * @param resource The resource ID to inflate
16167 * @param root A view group that will be the parent. Used to properly inflate the
16168 * layout_* parameters.
16169 * @see LayoutInflater
16170 */
16171 public static View inflate(Context context, int resource, ViewGroup root) {
16172 LayoutInflater factory = LayoutInflater.from(context);
16173 return factory.inflate(resource, root);
16174 }
Romain Guy33e72ae2010-07-17 12:40:29 -070016175
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016176 /**
Adam Powell637d3372010-08-25 14:37:03 -070016177 * Scroll the view with standard behavior for scrolling beyond the normal
16178 * content boundaries. Views that call this method should override
16179 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16180 * results of an over-scroll operation.
16181 *
16182 * Views can use this method to handle any touch or fling-based scrolling.
16183 *
16184 * @param deltaX Change in X in pixels
16185 * @param deltaY Change in Y in pixels
16186 * @param scrollX Current X scroll value in pixels before applying deltaX
16187 * @param scrollY Current Y scroll value in pixels before applying deltaY
16188 * @param scrollRangeX Maximum content scroll range along the X axis
16189 * @param scrollRangeY Maximum content scroll range along the Y axis
16190 * @param maxOverScrollX Number of pixels to overscroll by in either direction
16191 * along the X axis.
16192 * @param maxOverScrollY Number of pixels to overscroll by in either direction
16193 * along the Y axis.
16194 * @param isTouchEvent true if this scroll operation is the result of a touch event.
16195 * @return true if scrolling was clamped to an over-scroll boundary along either
16196 * axis, false otherwise.
16197 */
Romain Guy7b5b6ab2011-03-14 18:05:08 -070016198 @SuppressWarnings({"UnusedParameters"})
Adam Powell637d3372010-08-25 14:37:03 -070016199 protected boolean overScrollBy(int deltaX, int deltaY,
16200 int scrollX, int scrollY,
16201 int scrollRangeX, int scrollRangeY,
16202 int maxOverScrollX, int maxOverScrollY,
16203 boolean isTouchEvent) {
16204 final int overScrollMode = mOverScrollMode;
16205 final boolean canScrollHorizontal =
16206 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16207 final boolean canScrollVertical =
16208 computeVerticalScrollRange() > computeVerticalScrollExtent();
16209 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16210 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16211 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16212 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16213
16214 int newScrollX = scrollX + deltaX;
16215 if (!overScrollHorizontal) {
16216 maxOverScrollX = 0;
16217 }
16218
16219 int newScrollY = scrollY + deltaY;
16220 if (!overScrollVertical) {
16221 maxOverScrollY = 0;
16222 }
16223
16224 // Clamp values if at the limits and record
16225 final int left = -maxOverScrollX;
16226 final int right = maxOverScrollX + scrollRangeX;
16227 final int top = -maxOverScrollY;
16228 final int bottom = maxOverScrollY + scrollRangeY;
16229
16230 boolean clampedX = false;
16231 if (newScrollX > right) {
16232 newScrollX = right;
16233 clampedX = true;
16234 } else if (newScrollX < left) {
16235 newScrollX = left;
16236 clampedX = true;
16237 }
16238
16239 boolean clampedY = false;
16240 if (newScrollY > bottom) {
16241 newScrollY = bottom;
16242 clampedY = true;
16243 } else if (newScrollY < top) {
16244 newScrollY = top;
16245 clampedY = true;
16246 }
16247
16248 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16249
16250 return clampedX || clampedY;
16251 }
16252
16253 /**
16254 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16255 * respond to the results of an over-scroll operation.
16256 *
16257 * @param scrollX New X scroll value in pixels
16258 * @param scrollY New Y scroll value in pixels
16259 * @param clampedX True if scrollX was clamped to an over-scroll boundary
16260 * @param clampedY True if scrollY was clamped to an over-scroll boundary
16261 */
16262 protected void onOverScrolled(int scrollX, int scrollY,
16263 boolean clampedX, boolean clampedY) {
16264 // Intentionally empty.
16265 }
16266
16267 /**
16268 * Returns the over-scroll mode for this view. The result will be
16269 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16270 * (allow over-scrolling only if the view content is larger than the container),
16271 * or {@link #OVER_SCROLL_NEVER}.
16272 *
16273 * @return This view's over-scroll mode.
16274 */
16275 public int getOverScrollMode() {
16276 return mOverScrollMode;
16277 }
16278
16279 /**
16280 * Set the over-scroll mode for this view. Valid over-scroll modes are
16281 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16282 * (allow over-scrolling only if the view content is larger than the container),
16283 * or {@link #OVER_SCROLL_NEVER}.
16284 *
16285 * Setting the over-scroll mode of a view will have an effect only if the
16286 * view is capable of scrolling.
16287 *
16288 * @param overScrollMode The new over-scroll mode for this view.
16289 */
16290 public void setOverScrollMode(int overScrollMode) {
16291 if (overScrollMode != OVER_SCROLL_ALWAYS &&
16292 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16293 overScrollMode != OVER_SCROLL_NEVER) {
16294 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16295 }
16296 mOverScrollMode = overScrollMode;
16297 }
16298
16299 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -080016300 * Gets a scale factor that determines the distance the view should scroll
16301 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16302 * @return The vertical scroll scale factor.
16303 * @hide
16304 */
16305 protected float getVerticalScrollFactor() {
16306 if (mVerticalScrollFactor == 0) {
16307 TypedValue outValue = new TypedValue();
16308 if (!mContext.getTheme().resolveAttribute(
16309 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16310 throw new IllegalStateException(
16311 "Expected theme to define listPreferredItemHeight.");
16312 }
16313 mVerticalScrollFactor = outValue.getDimension(
16314 mContext.getResources().getDisplayMetrics());
16315 }
16316 return mVerticalScrollFactor;
16317 }
16318
16319 /**
16320 * Gets a scale factor that determines the distance the view should scroll
16321 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16322 * @return The horizontal scroll scale factor.
16323 * @hide
16324 */
16325 protected float getHorizontalScrollFactor() {
16326 // TODO: Should use something else.
16327 return getVerticalScrollFactor();
16328 }
16329
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016330 /**
16331 * Return the value specifying the text direction or policy that was set with
16332 * {@link #setTextDirection(int)}.
16333 *
16334 * @return the defined text direction. It can be one of:
16335 *
16336 * {@link #TEXT_DIRECTION_INHERIT},
16337 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16338 * {@link #TEXT_DIRECTION_ANY_RTL},
16339 * {@link #TEXT_DIRECTION_LTR},
16340 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016341 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016342 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016343 @ViewDebug.ExportedProperty(category = "text", mapping = {
16344 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16345 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16346 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16347 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16348 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16349 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16350 })
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016351 public int getTextDirection() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016352 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016353 }
16354
16355 /**
16356 * Set the text direction.
16357 *
16358 * @param textDirection the direction to set. Should be one of:
16359 *
16360 * {@link #TEXT_DIRECTION_INHERIT},
16361 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16362 * {@link #TEXT_DIRECTION_ANY_RTL},
16363 * {@link #TEXT_DIRECTION_LTR},
16364 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016365 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016366 */
16367 public void setTextDirection(int textDirection) {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016368 if (getTextDirection() != textDirection) {
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016369 // Reset the current text direction and the resolved one
Dianne Hackborn4702a852012-08-17 15:18:29 -070016370 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016371 resetResolvedTextDirection();
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016372 // Set the new text direction
Dianne Hackborn4702a852012-08-17 15:18:29 -070016373 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016374 // Refresh
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016375 requestLayout();
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016376 invalidate(true);
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016377 }
16378 }
16379
16380 /**
16381 * Return the resolved text direction.
16382 *
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016383 * This needs resolution if the value is TEXT_DIRECTION_INHERIT. The resolution matches
16384 * {@link #getTextDirection()}if it is not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds
16385 * up the parent chain of the view. if there is no parent, then it will return the default
16386 * {@link #TEXT_DIRECTION_FIRST_STRONG}.
16387 *
16388 * @return the resolved text direction. Returns one of:
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016389 *
Doug Feltcb3791202011-07-07 11:57:48 -070016390 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16391 * {@link #TEXT_DIRECTION_ANY_RTL},
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016392 * {@link #TEXT_DIRECTION_LTR},
16393 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016394 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016395 */
16396 public int getResolvedTextDirection() {
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070016397 // The text direction will be resolved only if needed
Dianne Hackborn4702a852012-08-17 15:18:29 -070016398 if ((mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) != PFLAG2_TEXT_DIRECTION_RESOLVED) {
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016399 resolveTextDirection();
16400 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070016401 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016402 }
16403
16404 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016405 * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
16406 * resolution is done.
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016407 */
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016408 public void resolveTextDirection() {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016409 // Reset any previous text direction resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070016410 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016411
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016412 if (hasRtlSupport()) {
16413 // Set resolved text direction flag depending on text direction flag
16414 final int textDirection = getTextDirection();
16415 switch(textDirection) {
16416 case TEXT_DIRECTION_INHERIT:
16417 if (canResolveTextDirection()) {
16418 ViewGroup viewGroup = ((ViewGroup) mParent);
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016419
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016420 // Set current resolved direction to the same value as the parent's one
16421 final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
16422 switch (parentResolvedDirection) {
16423 case TEXT_DIRECTION_FIRST_STRONG:
16424 case TEXT_DIRECTION_ANY_RTL:
16425 case TEXT_DIRECTION_LTR:
16426 case TEXT_DIRECTION_RTL:
16427 case TEXT_DIRECTION_LOCALE:
16428 mPrivateFlags2 |=
Dianne Hackborn4702a852012-08-17 15:18:29 -070016429 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016430 break;
16431 default:
16432 // Default resolved direction is "first strong" heuristic
Dianne Hackborn4702a852012-08-17 15:18:29 -070016433 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016434 }
16435 } else {
16436 // We cannot do the resolution if there is no parent, so use the default one
Dianne Hackborn4702a852012-08-17 15:18:29 -070016437 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016438 }
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016439 break;
16440 case TEXT_DIRECTION_FIRST_STRONG:
16441 case TEXT_DIRECTION_ANY_RTL:
16442 case TEXT_DIRECTION_LTR:
16443 case TEXT_DIRECTION_RTL:
16444 case TEXT_DIRECTION_LOCALE:
16445 // Resolved direction is the same as text direction
Dianne Hackborn4702a852012-08-17 15:18:29 -070016446 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016447 break;
16448 default:
16449 // Default resolved direction is "first strong" heuristic
Dianne Hackborn4702a852012-08-17 15:18:29 -070016450 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016451 }
16452 } else {
16453 // Default resolved direction is "first strong" heuristic
Dianne Hackborn4702a852012-08-17 15:18:29 -070016454 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016455 }
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016456
16457 // Set to resolved
Dianne Hackborn4702a852012-08-17 15:18:29 -070016458 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016459 onResolvedTextDirectionChanged();
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016460 }
16461
16462 /**
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016463 * Called when text direction has been resolved. Subclasses that care about text direction
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016464 * resolution should override this method.
16465 *
16466 * The default implementation does nothing.
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016467 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016468 public void onResolvedTextDirectionChanged() {
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016469 }
16470
16471 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016472 * Check if text direction resolution can be done.
16473 *
16474 * @return true if text direction resolution can be done otherwise return false.
16475 */
16476 public boolean canResolveTextDirection() {
16477 switch (getTextDirection()) {
16478 case TEXT_DIRECTION_INHERIT:
16479 return (mParent != null) && (mParent instanceof ViewGroup);
16480 default:
16481 return true;
16482 }
16483 }
16484
16485 /**
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016486 * Reset resolved text direction. Text direction can be resolved with a call to
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016487 * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016488 * reset is done.
16489 */
16490 public void resetResolvedTextDirection() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016491 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016492 onResolvedTextDirectionReset();
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016493 }
16494
16495 /**
16496 * Called when text direction is reset. Subclasses that care about text direction reset should
16497 * override this method and do a reset of the text direction of their children. The default
16498 * implementation does nothing.
16499 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016500 public void onResolvedTextDirectionReset() {
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016501 }
16502
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016503 /**
16504 * Return the value specifying the text alignment or policy that was set with
16505 * {@link #setTextAlignment(int)}.
16506 *
16507 * @return the defined text alignment. It can be one of:
16508 *
16509 * {@link #TEXT_ALIGNMENT_INHERIT},
16510 * {@link #TEXT_ALIGNMENT_GRAVITY},
16511 * {@link #TEXT_ALIGNMENT_CENTER},
16512 * {@link #TEXT_ALIGNMENT_TEXT_START},
16513 * {@link #TEXT_ALIGNMENT_TEXT_END},
16514 * {@link #TEXT_ALIGNMENT_VIEW_START},
16515 * {@link #TEXT_ALIGNMENT_VIEW_END}
16516 */
16517 @ViewDebug.ExportedProperty(category = "text", mapping = {
16518 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16519 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16520 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16521 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16522 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16523 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16524 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16525 })
16526 public int getTextAlignment() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016527 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016528 }
16529
16530 /**
16531 * Set the text alignment.
16532 *
16533 * @param textAlignment The text alignment to set. Should be one of
16534 *
16535 * {@link #TEXT_ALIGNMENT_INHERIT},
16536 * {@link #TEXT_ALIGNMENT_GRAVITY},
16537 * {@link #TEXT_ALIGNMENT_CENTER},
16538 * {@link #TEXT_ALIGNMENT_TEXT_START},
16539 * {@link #TEXT_ALIGNMENT_TEXT_END},
16540 * {@link #TEXT_ALIGNMENT_VIEW_START},
16541 * {@link #TEXT_ALIGNMENT_VIEW_END}
16542 *
16543 * @attr ref android.R.styleable#View_textAlignment
16544 */
16545 public void setTextAlignment(int textAlignment) {
16546 if (textAlignment != getTextAlignment()) {
16547 // Reset the current and resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016548 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016549 resetResolvedTextAlignment();
16550 // Set the new text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016551 mPrivateFlags2 |= ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016552 // Refresh
16553 requestLayout();
16554 invalidate(true);
16555 }
16556 }
16557
16558 /**
16559 * Return the resolved text alignment.
16560 *
16561 * The resolved text alignment. This needs resolution if the value is
16562 * TEXT_ALIGNMENT_INHERIT. The resolution matches {@link #setTextAlignment(int)} if it is
16563 * not TEXT_ALIGNMENT_INHERIT, otherwise resolution proceeds up the parent chain of the view.
16564 *
16565 * @return the resolved text alignment. Returns one of:
16566 *
16567 * {@link #TEXT_ALIGNMENT_GRAVITY},
16568 * {@link #TEXT_ALIGNMENT_CENTER},
16569 * {@link #TEXT_ALIGNMENT_TEXT_START},
16570 * {@link #TEXT_ALIGNMENT_TEXT_END},
16571 * {@link #TEXT_ALIGNMENT_VIEW_START},
16572 * {@link #TEXT_ALIGNMENT_VIEW_END}
16573 */
16574 @ViewDebug.ExportedProperty(category = "text", mapping = {
16575 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16576 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16577 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16578 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16579 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16580 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16581 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16582 })
16583 public int getResolvedTextAlignment() {
16584 // If text alignment is not resolved, then resolve it
Dianne Hackborn4702a852012-08-17 15:18:29 -070016585 if ((mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) != PFLAG2_TEXT_ALIGNMENT_RESOLVED) {
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016586 resolveTextAlignment();
16587 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070016588 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016589 }
16590
16591 /**
16592 * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
16593 * resolution is done.
16594 */
16595 public void resolveTextAlignment() {
16596 // Reset any previous text alignment resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070016597 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016598
16599 if (hasRtlSupport()) {
16600 // Set resolved text alignment flag depending on text alignment flag
16601 final int textAlignment = getTextAlignment();
16602 switch (textAlignment) {
16603 case TEXT_ALIGNMENT_INHERIT:
16604 // Check if we can resolve the text alignment
16605 if (canResolveLayoutDirection() && mParent instanceof View) {
16606 View view = (View) mParent;
16607
16608 final int parentResolvedTextAlignment = view.getResolvedTextAlignment();
16609 switch (parentResolvedTextAlignment) {
16610 case TEXT_ALIGNMENT_GRAVITY:
16611 case TEXT_ALIGNMENT_TEXT_START:
16612 case TEXT_ALIGNMENT_TEXT_END:
16613 case TEXT_ALIGNMENT_CENTER:
16614 case TEXT_ALIGNMENT_VIEW_START:
16615 case TEXT_ALIGNMENT_VIEW_END:
16616 // Resolved text alignment is the same as the parent resolved
16617 // text alignment
16618 mPrivateFlags2 |=
Dianne Hackborn4702a852012-08-17 15:18:29 -070016619 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016620 break;
16621 default:
16622 // Use default resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016623 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016624 }
16625 }
16626 else {
16627 // We cannot do the resolution if there is no parent so use the default
Dianne Hackborn4702a852012-08-17 15:18:29 -070016628 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016629 }
16630 break;
16631 case TEXT_ALIGNMENT_GRAVITY:
16632 case TEXT_ALIGNMENT_TEXT_START:
16633 case TEXT_ALIGNMENT_TEXT_END:
16634 case TEXT_ALIGNMENT_CENTER:
16635 case TEXT_ALIGNMENT_VIEW_START:
16636 case TEXT_ALIGNMENT_VIEW_END:
16637 // Resolved text alignment is the same as text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016638 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016639 break;
16640 default:
16641 // Use default resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016642 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016643 }
16644 } else {
16645 // Use default resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016646 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016647 }
16648
16649 // Set the resolved
Dianne Hackborn4702a852012-08-17 15:18:29 -070016650 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016651 onResolvedTextAlignmentChanged();
16652 }
16653
16654 /**
16655 * Check if text alignment resolution can be done.
16656 *
16657 * @return true if text alignment resolution can be done otherwise return false.
16658 */
16659 public boolean canResolveTextAlignment() {
16660 switch (getTextAlignment()) {
16661 case TEXT_DIRECTION_INHERIT:
16662 return (mParent != null);
16663 default:
16664 return true;
16665 }
16666 }
16667
16668 /**
16669 * Called when text alignment has been resolved. Subclasses that care about text alignment
16670 * resolution should override this method.
16671 *
16672 * The default implementation does nothing.
16673 */
16674 public void onResolvedTextAlignmentChanged() {
16675 }
16676
16677 /**
16678 * Reset resolved text alignment. Text alignment can be resolved with a call to
16679 * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
16680 * reset is done.
16681 */
16682 public void resetResolvedTextAlignment() {
16683 // Reset any previous text alignment resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070016684 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016685 onResolvedTextAlignmentReset();
16686 }
16687
16688 /**
16689 * Called when text alignment is reset. Subclasses that care about text alignment reset should
16690 * override this method and do a reset of the text alignment of their children. The default
16691 * implementation does nothing.
16692 */
16693 public void onResolvedTextAlignmentReset() {
16694 }
16695
Adam Powella9108a22012-07-18 11:18:09 -070016696 /**
16697 * Generate a value suitable for use in {@link #setId(int)}.
16698 * This value will not collide with ID values generated at build time by aapt for R.id.
16699 *
16700 * @return a generated ID value
16701 */
16702 public static int generateViewId() {
16703 for (;;) {
16704 final int result = sNextGeneratedId.get();
16705 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
16706 int newValue = result + 1;
16707 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
16708 if (sNextGeneratedId.compareAndSet(result, newValue)) {
16709 return result;
16710 }
16711 }
16712 }
16713
Chet Haaseb39f0512011-05-24 14:36:40 -070016714 //
16715 // Properties
16716 //
16717 /**
16718 * A Property wrapper around the <code>alpha</code> functionality handled by the
16719 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
16720 */
Chet Haased47f1532011-12-16 11:18:52 -080016721 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016722 @Override
16723 public void setValue(View object, float value) {
16724 object.setAlpha(value);
16725 }
16726
16727 @Override
16728 public Float get(View object) {
16729 return object.getAlpha();
16730 }
16731 };
16732
16733 /**
16734 * A Property wrapper around the <code>translationX</code> functionality handled by the
16735 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
16736 */
Chet Haased47f1532011-12-16 11:18:52 -080016737 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016738 @Override
16739 public void setValue(View object, float value) {
16740 object.setTranslationX(value);
16741 }
16742
16743 @Override
16744 public Float get(View object) {
16745 return object.getTranslationX();
16746 }
16747 };
16748
16749 /**
16750 * A Property wrapper around the <code>translationY</code> functionality handled by the
16751 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
16752 */
Chet Haased47f1532011-12-16 11:18:52 -080016753 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016754 @Override
16755 public void setValue(View object, float value) {
16756 object.setTranslationY(value);
16757 }
16758
16759 @Override
16760 public Float get(View object) {
16761 return object.getTranslationY();
16762 }
16763 };
16764
16765 /**
16766 * A Property wrapper around the <code>x</code> functionality handled by the
16767 * {@link View#setX(float)} and {@link View#getX()} methods.
16768 */
Chet Haased47f1532011-12-16 11:18:52 -080016769 public static final Property<View, Float> X = new FloatProperty<View>("x") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016770 @Override
16771 public void setValue(View object, float value) {
16772 object.setX(value);
16773 }
16774
16775 @Override
16776 public Float get(View object) {
16777 return object.getX();
16778 }
16779 };
16780
16781 /**
16782 * A Property wrapper around the <code>y</code> functionality handled by the
16783 * {@link View#setY(float)} and {@link View#getY()} methods.
16784 */
Chet Haased47f1532011-12-16 11:18:52 -080016785 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016786 @Override
16787 public void setValue(View object, float value) {
16788 object.setY(value);
16789 }
16790
16791 @Override
16792 public Float get(View object) {
16793 return object.getY();
16794 }
16795 };
16796
16797 /**
16798 * A Property wrapper around the <code>rotation</code> functionality handled by the
16799 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
16800 */
Chet Haased47f1532011-12-16 11:18:52 -080016801 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016802 @Override
16803 public void setValue(View object, float value) {
16804 object.setRotation(value);
16805 }
16806
16807 @Override
16808 public Float get(View object) {
16809 return object.getRotation();
16810 }
16811 };
16812
16813 /**
16814 * A Property wrapper around the <code>rotationX</code> functionality handled by the
16815 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
16816 */
Chet Haased47f1532011-12-16 11:18:52 -080016817 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016818 @Override
16819 public void setValue(View object, float value) {
16820 object.setRotationX(value);
16821 }
16822
16823 @Override
16824 public Float get(View object) {
16825 return object.getRotationX();
16826 }
16827 };
16828
16829 /**
16830 * A Property wrapper around the <code>rotationY</code> functionality handled by the
16831 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
16832 */
Chet Haased47f1532011-12-16 11:18:52 -080016833 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016834 @Override
16835 public void setValue(View object, float value) {
16836 object.setRotationY(value);
16837 }
16838
16839 @Override
16840 public Float get(View object) {
16841 return object.getRotationY();
16842 }
16843 };
16844
16845 /**
16846 * A Property wrapper around the <code>scaleX</code> functionality handled by the
16847 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
16848 */
Chet Haased47f1532011-12-16 11:18:52 -080016849 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016850 @Override
16851 public void setValue(View object, float value) {
16852 object.setScaleX(value);
16853 }
16854
16855 @Override
16856 public Float get(View object) {
16857 return object.getScaleX();
16858 }
16859 };
16860
16861 /**
16862 * A Property wrapper around the <code>scaleY</code> functionality handled by the
16863 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
16864 */
Chet Haased47f1532011-12-16 11:18:52 -080016865 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016866 @Override
16867 public void setValue(View object, float value) {
16868 object.setScaleY(value);
16869 }
16870
16871 @Override
16872 public Float get(View object) {
16873 return object.getScaleY();
16874 }
16875 };
16876
Jeff Brown33bbfd22011-02-24 20:55:35 -080016877 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016878 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
16879 * Each MeasureSpec represents a requirement for either the width or the height.
16880 * A MeasureSpec is comprised of a size and a mode. There are three possible
16881 * modes:
16882 * <dl>
16883 * <dt>UNSPECIFIED</dt>
16884 * <dd>
16885 * The parent has not imposed any constraint on the child. It can be whatever size
16886 * it wants.
16887 * </dd>
16888 *
16889 * <dt>EXACTLY</dt>
16890 * <dd>
16891 * The parent has determined an exact size for the child. The child is going to be
16892 * given those bounds regardless of how big it wants to be.
16893 * </dd>
16894 *
16895 * <dt>AT_MOST</dt>
16896 * <dd>
16897 * The child can be as large as it wants up to the specified size.
16898 * </dd>
16899 * </dl>
16900 *
16901 * MeasureSpecs are implemented as ints to reduce object allocation. This class
16902 * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
16903 */
16904 public static class MeasureSpec {
16905 private static final int MODE_SHIFT = 30;
16906 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
16907
16908 /**
16909 * Measure specification mode: The parent has not imposed any constraint
16910 * on the child. It can be whatever size it wants.
16911 */
16912 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
16913
16914 /**
16915 * Measure specification mode: The parent has determined an exact size
16916 * for the child. The child is going to be given those bounds regardless
16917 * of how big it wants to be.
16918 */
16919 public static final int EXACTLY = 1 << MODE_SHIFT;
16920
16921 /**
16922 * Measure specification mode: The child can be as large as it wants up
16923 * to the specified size.
16924 */
16925 public static final int AT_MOST = 2 << MODE_SHIFT;
16926
16927 /**
16928 * Creates a measure specification based on the supplied size and mode.
16929 *
16930 * The mode must always be one of the following:
16931 * <ul>
16932 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
16933 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
16934 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
16935 * </ul>
16936 *
16937 * @param size the size of the measure specification
16938 * @param mode the mode of the measure specification
16939 * @return the measure specification based on size and mode
16940 */
16941 public static int makeMeasureSpec(int size, int mode) {
16942 return size + mode;
16943 }
16944
16945 /**
16946 * Extracts the mode from the supplied measure specification.
16947 *
16948 * @param measureSpec the measure specification to extract the mode from
16949 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
16950 * {@link android.view.View.MeasureSpec#AT_MOST} or
16951 * {@link android.view.View.MeasureSpec#EXACTLY}
16952 */
16953 public static int getMode(int measureSpec) {
16954 return (measureSpec & MODE_MASK);
16955 }
16956
16957 /**
16958 * Extracts the size from the supplied measure specification.
16959 *
16960 * @param measureSpec the measure specification to extract the size from
16961 * @return the size in pixels defined in the supplied measure specification
16962 */
16963 public static int getSize(int measureSpec) {
16964 return (measureSpec & ~MODE_MASK);
16965 }
16966
16967 /**
16968 * Returns a String representation of the specified measure
16969 * specification.
16970 *
16971 * @param measureSpec the measure specification to convert to a String
16972 * @return a String with the following format: "MeasureSpec: MODE SIZE"
16973 */
16974 public static String toString(int measureSpec) {
16975 int mode = getMode(measureSpec);
16976 int size = getSize(measureSpec);
16977
16978 StringBuilder sb = new StringBuilder("MeasureSpec: ");
16979
16980 if (mode == UNSPECIFIED)
16981 sb.append("UNSPECIFIED ");
16982 else if (mode == EXACTLY)
16983 sb.append("EXACTLY ");
16984 else if (mode == AT_MOST)
16985 sb.append("AT_MOST ");
16986 else
16987 sb.append(mode).append(" ");
16988
16989 sb.append(size);
16990 return sb.toString();
16991 }
16992 }
16993
16994 class CheckForLongPress implements Runnable {
16995
16996 private int mOriginalWindowAttachCount;
16997
16998 public void run() {
The Android Open Source Project10592532009-03-18 17:39:46 -070016999 if (isPressed() && (mParent != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017000 && mOriginalWindowAttachCount == mWindowAttachCount) {
17001 if (performLongClick()) {
17002 mHasPerformedLongPress = true;
17003 }
17004 }
17005 }
17006
17007 public void rememberWindowAttachCount() {
17008 mOriginalWindowAttachCount = mWindowAttachCount;
17009 }
17010 }
Joe Malin32736f02011-01-19 16:14:20 -080017011
Adam Powelle14579b2009-12-16 18:39:52 -080017012 private final class CheckForTap implements Runnable {
17013 public void run() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070017014 mPrivateFlags &= ~PFLAG_PREPRESSED;
Adam Powell4d6f0662012-02-21 15:11:11 -080017015 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -070017016 checkForLongClick(ViewConfiguration.getTapTimeout());
Adam Powelle14579b2009-12-16 18:39:52 -080017017 }
17018 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017019
Adam Powella35d7682010-03-12 14:48:13 -080017020 private final class PerformClick implements Runnable {
17021 public void run() {
17022 performClick();
17023 }
17024 }
17025
Dianne Hackborn63042d62011-01-26 18:56:29 -080017026 /** @hide */
17027 public void hackTurnOffWindowResizeAnim(boolean off) {
17028 mAttachInfo.mTurnOffWindowResizeAnim = off;
17029 }
Joe Malin32736f02011-01-19 16:14:20 -080017030
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017031 /**
Chet Haasea00f3862011-02-22 06:34:40 -080017032 * This method returns a ViewPropertyAnimator object, which can be used to animate
17033 * specific properties on this View.
17034 *
17035 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
17036 */
17037 public ViewPropertyAnimator animate() {
17038 if (mAnimator == null) {
17039 mAnimator = new ViewPropertyAnimator(this);
17040 }
17041 return mAnimator;
17042 }
17043
17044 /**
Jean Chalard405bc512012-05-29 19:12:34 +090017045 * Interface definition for a callback to be invoked when a hardware key event is
17046 * dispatched to this view. The callback will be invoked before the key event is
17047 * given to the view. This is only useful for hardware keyboards; a software input
17048 * method has no obligation to trigger this listener.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017049 */
17050 public interface OnKeyListener {
17051 /**
Jean Chalard405bc512012-05-29 19:12:34 +090017052 * Called when a hardware key is dispatched to a view. This allows listeners to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017053 * get a chance to respond before the target view.
Jean Chalard405bc512012-05-29 19:12:34 +090017054 * <p>Key presses in software keyboards will generally NOT trigger this method,
17055 * although some may elect to do so in some situations. Do not assume a
17056 * software input method has to be key-based; even if it is, it may use key presses
17057 * in a different way than you expect, so there is no way to reliably catch soft
17058 * input key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017059 *
17060 * @param v The view the key has been dispatched to.
17061 * @param keyCode The code for the physical key that was pressed
17062 * @param event The KeyEvent object containing full information about
17063 * the event.
17064 * @return True if the listener has consumed the event, false otherwise.
17065 */
17066 boolean onKey(View v, int keyCode, KeyEvent event);
17067 }
17068
17069 /**
17070 * Interface definition for a callback to be invoked when a touch event is
17071 * dispatched to this view. The callback will be invoked before the touch
17072 * event is given to the view.
17073 */
17074 public interface OnTouchListener {
17075 /**
17076 * Called when a touch event is dispatched to a view. This allows listeners to
17077 * get a chance to respond before the target view.
17078 *
17079 * @param v The view the touch event has been dispatched to.
17080 * @param event The MotionEvent object containing full information about
17081 * the event.
17082 * @return True if the listener has consumed the event, false otherwise.
17083 */
17084 boolean onTouch(View v, MotionEvent event);
17085 }
17086
17087 /**
Jeff Brown10b62902011-06-20 16:40:37 -070017088 * Interface definition for a callback to be invoked when a hover event is
17089 * dispatched to this view. The callback will be invoked before the hover
17090 * event is given to the view.
17091 */
17092 public interface OnHoverListener {
17093 /**
17094 * Called when a hover event is dispatched to a view. This allows listeners to
17095 * get a chance to respond before the target view.
17096 *
17097 * @param v The view the hover event has been dispatched to.
17098 * @param event The MotionEvent object containing full information about
17099 * the event.
17100 * @return True if the listener has consumed the event, false otherwise.
17101 */
17102 boolean onHover(View v, MotionEvent event);
17103 }
17104
17105 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -080017106 * Interface definition for a callback to be invoked when a generic motion event is
17107 * dispatched to this view. The callback will be invoked before the generic motion
17108 * event is given to the view.
17109 */
17110 public interface OnGenericMotionListener {
17111 /**
17112 * Called when a generic motion event is dispatched to a view. This allows listeners to
17113 * get a chance to respond before the target view.
17114 *
17115 * @param v The view the generic motion event has been dispatched to.
17116 * @param event The MotionEvent object containing full information about
17117 * the event.
17118 * @return True if the listener has consumed the event, false otherwise.
17119 */
17120 boolean onGenericMotion(View v, MotionEvent event);
17121 }
17122
17123 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017124 * Interface definition for a callback to be invoked when a view has been clicked and held.
17125 */
17126 public interface OnLongClickListener {
17127 /**
17128 * Called when a view has been clicked and held.
17129 *
17130 * @param v The view that was clicked and held.
17131 *
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -080017132 * @return true if the callback consumed the long click, false otherwise.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017133 */
17134 boolean onLongClick(View v);
17135 }
17136
17137 /**
Chris Tate32affef2010-10-18 15:29:21 -070017138 * Interface definition for a callback to be invoked when a drag is being dispatched
17139 * to this view. The callback will be invoked before the hosting view's own
17140 * onDrag(event) method. If the listener wants to fall back to the hosting view's
17141 * onDrag(event) behavior, it should return 'false' from this callback.
Joe Fernandez558459f2011-10-13 16:47:36 -070017142 *
17143 * <div class="special reference">
17144 * <h3>Developer Guides</h3>
17145 * <p>For a guide to implementing drag and drop features, read the
17146 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17147 * </div>
Chris Tate32affef2010-10-18 15:29:21 -070017148 */
17149 public interface OnDragListener {
17150 /**
17151 * Called when a drag event is dispatched to a view. This allows listeners
17152 * to get a chance to override base View behavior.
17153 *
Joe Malin32736f02011-01-19 16:14:20 -080017154 * @param v The View that received the drag event.
17155 * @param event The {@link android.view.DragEvent} object for the drag event.
17156 * @return {@code true} if the drag event was handled successfully, or {@code false}
17157 * if the drag event was not handled. Note that {@code false} will trigger the View
17158 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
Chris Tate32affef2010-10-18 15:29:21 -070017159 */
17160 boolean onDrag(View v, DragEvent event);
17161 }
17162
17163 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017164 * Interface definition for a callback to be invoked when the focus state of
17165 * a view changed.
17166 */
17167 public interface OnFocusChangeListener {
17168 /**
17169 * Called when the focus state of a view has changed.
17170 *
17171 * @param v The view whose state has changed.
17172 * @param hasFocus The new focus state of v.
17173 */
17174 void onFocusChange(View v, boolean hasFocus);
17175 }
17176
17177 /**
17178 * Interface definition for a callback to be invoked when a view is clicked.
17179 */
17180 public interface OnClickListener {
17181 /**
17182 * Called when a view has been clicked.
17183 *
17184 * @param v The view that was clicked.
17185 */
17186 void onClick(View v);
17187 }
17188
17189 /**
17190 * Interface definition for a callback to be invoked when the context menu
17191 * for this view is being built.
17192 */
17193 public interface OnCreateContextMenuListener {
17194 /**
17195 * Called when the context menu for this view is being built. It is not
17196 * safe to hold onto the menu after this method returns.
17197 *
17198 * @param menu The context menu that is being built
17199 * @param v The view for which the context menu is being built
17200 * @param menuInfo Extra information about the item for which the
17201 * context menu should be shown. This information will vary
17202 * depending on the class of v.
17203 */
17204 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17205 }
17206
Joe Onorato664644d2011-01-23 17:53:23 -080017207 /**
17208 * Interface definition for a callback to be invoked when the status bar changes
Dianne Hackborn9a230e02011-10-06 11:51:27 -070017209 * visibility. This reports <strong>global</strong> changes to the system UI
Dianne Hackborncf675782012-05-10 15:07:24 -070017210 * state, not what the application is requesting.
Joe Onorato664644d2011-01-23 17:53:23 -080017211 *
Philip Milne6c8ea062012-04-03 17:38:43 -070017212 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
Joe Onorato664644d2011-01-23 17:53:23 -080017213 */
17214 public interface OnSystemUiVisibilityChangeListener {
17215 /**
17216 * Called when the status bar changes visibility because of a call to
Romain Guy5c22a8c2011-05-13 11:48:45 -070017217 * {@link View#setSystemUiVisibility(int)}.
Joe Onorato664644d2011-01-23 17:53:23 -080017218 *
Dianne Hackborncf675782012-05-10 15:07:24 -070017219 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17220 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17221 * This tells you the <strong>global</strong> state of these UI visibility
17222 * flags, not what your app is currently applying.
Joe Onorato664644d2011-01-23 17:53:23 -080017223 */
17224 public void onSystemUiVisibilityChange(int visibility);
17225 }
17226
Adam Powell4afd62b2011-02-18 15:02:18 -080017227 /**
17228 * Interface definition for a callback to be invoked when this view is attached
17229 * or detached from its window.
17230 */
17231 public interface OnAttachStateChangeListener {
17232 /**
17233 * Called when the view is attached to a window.
17234 * @param v The view that was attached
17235 */
17236 public void onViewAttachedToWindow(View v);
17237 /**
17238 * Called when the view is detached from a window.
17239 * @param v The view that was detached
17240 */
17241 public void onViewDetachedFromWindow(View v);
17242 }
17243
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017244 private final class UnsetPressedState implements Runnable {
17245 public void run() {
17246 setPressed(false);
17247 }
17248 }
17249
17250 /**
17251 * Base class for derived classes that want to save and restore their own
17252 * state in {@link android.view.View#onSaveInstanceState()}.
17253 */
17254 public static class BaseSavedState extends AbsSavedState {
17255 /**
17256 * Constructor used when reading from a parcel. Reads the state of the superclass.
17257 *
17258 * @param source
17259 */
17260 public BaseSavedState(Parcel source) {
17261 super(source);
17262 }
17263
17264 /**
17265 * Constructor called by derived classes when creating their SavedState objects
17266 *
17267 * @param superState The state of the superclass of this view
17268 */
17269 public BaseSavedState(Parcelable superState) {
17270 super(superState);
17271 }
17272
17273 public static final Parcelable.Creator<BaseSavedState> CREATOR =
17274 new Parcelable.Creator<BaseSavedState>() {
17275 public BaseSavedState createFromParcel(Parcel in) {
17276 return new BaseSavedState(in);
17277 }
17278
17279 public BaseSavedState[] newArray(int size) {
17280 return new BaseSavedState[size];
17281 }
17282 };
17283 }
17284
17285 /**
17286 * A set of information given to a view when it is attached to its parent
17287 * window.
17288 */
17289 static class AttachInfo {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017290 interface Callbacks {
17291 void playSoundEffect(int effectId);
17292 boolean performHapticFeedback(int effectId, boolean always);
17293 }
17294
17295 /**
17296 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17297 * to a Handler. This class contains the target (View) to invalidate and
17298 * the coordinates of the dirty rectangle.
17299 *
17300 * For performance purposes, this class also implements a pool of up to
17301 * POOL_LIMIT objects that get reused. This reduces memory allocations
17302 * whenever possible.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017303 */
Romain Guyd928d682009-03-31 17:52:16 -070017304 static class InvalidateInfo implements Poolable<InvalidateInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017305 private static final int POOL_LIMIT = 10;
Romain Guy2e9bbce2009-04-01 10:40:10 -070017306 private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
17307 Pools.finitePool(new PoolableManager<InvalidateInfo>() {
Romain Guyd928d682009-03-31 17:52:16 -070017308 public InvalidateInfo newInstance() {
17309 return new InvalidateInfo();
17310 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017311
Romain Guyd928d682009-03-31 17:52:16 -070017312 public void onAcquired(InvalidateInfo element) {
17313 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017314
Romain Guyd928d682009-03-31 17:52:16 -070017315 public void onReleased(InvalidateInfo element) {
Romain Guy40c18f52011-09-01 17:01:18 -070017316 element.target = null;
Romain Guyd928d682009-03-31 17:52:16 -070017317 }
17318 }, POOL_LIMIT)
17319 );
17320
17321 private InvalidateInfo mNext;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017322 private boolean mIsPooled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017323
17324 View target;
17325
17326 int left;
17327 int top;
17328 int right;
17329 int bottom;
17330
Romain Guyd928d682009-03-31 17:52:16 -070017331 public void setNextPoolable(InvalidateInfo element) {
17332 mNext = element;
17333 }
17334
17335 public InvalidateInfo getNextPoolable() {
17336 return mNext;
17337 }
17338
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017339 static InvalidateInfo acquire() {
Romain Guyd928d682009-03-31 17:52:16 -070017340 return sPool.acquire();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017341 }
17342
17343 void release() {
Romain Guyd928d682009-03-31 17:52:16 -070017344 sPool.release(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017345 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017346
17347 public boolean isPooled() {
17348 return mIsPooled;
17349 }
17350
17351 public void setPooled(boolean isPooled) {
17352 mIsPooled = isPooled;
17353 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017354 }
17355
17356 final IWindowSession mSession;
17357
17358 final IWindow mWindow;
17359
17360 final IBinder mWindowToken;
17361
Jeff Brown98365d72012-08-19 20:30:52 -070017362 final Display mDisplay;
17363
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017364 final Callbacks mRootCallbacks;
17365
Romain Guy59a12ca2011-06-09 17:48:21 -070017366 HardwareCanvas mHardwareCanvas;
Chet Haasedaf98e92011-01-10 14:10:36 -080017367
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017368 /**
17369 * The top view of the hierarchy.
17370 */
17371 View mRootView;
Romain Guy8506ab42009-06-11 17:35:47 -070017372
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017373 IBinder mPanelParentWindowToken;
17374 Surface mSurface;
17375
Romain Guyb051e892010-09-28 19:09:36 -070017376 boolean mHardwareAccelerated;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080017377 boolean mHardwareAccelerationRequested;
Romain Guyb051e892010-09-28 19:09:36 -070017378 HardwareRenderer mHardwareRenderer;
Joe Malin32736f02011-01-19 16:14:20 -080017379
Romain Guy7e4e5612012-03-05 14:37:29 -080017380 boolean mScreenOn;
17381
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017382 /**
Romain Guy8506ab42009-06-11 17:35:47 -070017383 * Scale factor used by the compatibility mode
17384 */
17385 float mApplicationScale;
17386
17387 /**
17388 * Indicates whether the application is in compatibility mode
17389 */
17390 boolean mScalingRequired;
17391
17392 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070017393 * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
Dianne Hackborn63042d62011-01-26 18:56:29 -080017394 */
17395 boolean mTurnOffWindowResizeAnim;
Joe Malin32736f02011-01-19 16:14:20 -080017396
Dianne Hackborn63042d62011-01-26 18:56:29 -080017397 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017398 * Left position of this view's window
17399 */
17400 int mWindowLeft;
17401
17402 /**
17403 * Top position of this view's window
17404 */
17405 int mWindowTop;
17406
17407 /**
Adam Powell26153a32010-11-08 15:22:27 -080017408 * Indicates whether views need to use 32-bit drawing caches
Romain Guy35b38ce2009-10-07 13:38:55 -070017409 */
Adam Powell26153a32010-11-08 15:22:27 -080017410 boolean mUse32BitDrawingCache;
Romain Guy35b38ce2009-10-07 13:38:55 -070017411
17412 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017413 * For windows that are full-screen but using insets to layout inside
17414 * of the screen decorations, these are the current insets for the
17415 * content of the window.
17416 */
17417 final Rect mContentInsets = new Rect();
17418
17419 /**
17420 * For windows that are full-screen but using insets to layout inside
17421 * of the screen decorations, these are the current insets for the
17422 * actual visible parts of the window.
17423 */
17424 final Rect mVisibleInsets = new Rect();
17425
17426 /**
17427 * The internal insets given by this window. This value is
17428 * supplied by the client (through
17429 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
17430 * be given to the window manager when changed to be used in laying
17431 * out windows behind it.
17432 */
17433 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
17434 = new ViewTreeObserver.InternalInsetsInfo();
17435
17436 /**
17437 * All views in the window's hierarchy that serve as scroll containers,
17438 * used to determine if the window can be resized or must be panned
17439 * to adjust for a soft input area.
17440 */
17441 final ArrayList<View> mScrollContainers = new ArrayList<View>();
17442
Dianne Hackborn83fe3f52009-09-12 23:38:30 -070017443 final KeyEvent.DispatcherState mKeyDispatchState
17444 = new KeyEvent.DispatcherState();
17445
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017446 /**
17447 * Indicates whether the view's window currently has the focus.
17448 */
17449 boolean mHasWindowFocus;
17450
17451 /**
17452 * The current visibility of the window.
17453 */
17454 int mWindowVisibility;
17455
17456 /**
17457 * Indicates the time at which drawing started to occur.
17458 */
17459 long mDrawingTime;
17460
17461 /**
Romain Guy5bcdff42009-05-14 21:27:18 -070017462 * Indicates whether or not ignoring the DIRTY_MASK flags.
17463 */
17464 boolean mIgnoreDirtyState;
17465
17466 /**
Romain Guy02ccac62011-06-24 13:20:23 -070017467 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
17468 * to avoid clearing that flag prematurely.
17469 */
17470 boolean mSetIgnoreDirtyState = false;
17471
17472 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017473 * Indicates whether the view's window is currently in touch mode.
17474 */
17475 boolean mInTouchMode;
17476
17477 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070017478 * Indicates that ViewAncestor should trigger a global layout change
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017479 * the next time it performs a traversal
17480 */
17481 boolean mRecomputeGlobalAttributes;
17482
17483 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -070017484 * Always report new attributes at next traversal.
17485 */
17486 boolean mForceReportNewAttributes;
17487
17488 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017489 * Set during a traveral if any views want to keep the screen on.
17490 */
17491 boolean mKeepScreenOn;
17492
17493 /**
Joe Onorato664644d2011-01-23 17:53:23 -080017494 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
17495 */
17496 int mSystemUiVisibility;
17497
17498 /**
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070017499 * Hack to force certain system UI visibility flags to be cleared.
17500 */
17501 int mDisabledSystemUiVisibility;
17502
17503 /**
Dianne Hackborncf675782012-05-10 15:07:24 -070017504 * Last global system UI visibility reported by the window manager.
17505 */
17506 int mGlobalSystemUiVisibility;
17507
17508 /**
Joe Onorato664644d2011-01-23 17:53:23 -080017509 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
17510 * attached.
17511 */
17512 boolean mHasSystemUiListeners;
17513
17514 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017515 * Set if the visibility of any views has changed.
17516 */
17517 boolean mViewVisibilityChanged;
17518
17519 /**
17520 * Set to true if a view has been scrolled.
17521 */
17522 boolean mViewScrollChanged;
17523
17524 /**
17525 * Global to the view hierarchy used as a temporary for dealing with
17526 * x/y points in the transparent region computations.
17527 */
17528 final int[] mTransparentLocation = new int[2];
17529
17530 /**
17531 * Global to the view hierarchy used as a temporary for dealing with
17532 * x/y points in the ViewGroup.invalidateChild implementation.
17533 */
17534 final int[] mInvalidateChildLocation = new int[2];
17535
Chet Haasec3aa3612010-06-17 08:50:37 -070017536
17537 /**
17538 * Global to the view hierarchy used as a temporary for dealing with
17539 * x/y location when view is transformed.
17540 */
17541 final float[] mTmpTransformLocation = new float[2];
17542
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017543 /**
17544 * The view tree observer used to dispatch global events like
17545 * layout, pre-draw, touch mode change, etc.
17546 */
17547 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
17548
17549 /**
17550 * A Canvas used by the view hierarchy to perform bitmap caching.
17551 */
17552 Canvas mCanvas;
17553
17554 /**
Jeff Browna175a5b2012-02-15 19:18:31 -080017555 * The view root impl.
17556 */
17557 final ViewRootImpl mViewRootImpl;
17558
17559 /**
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070017560 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017561 * handler can be used to pump events in the UI events queue.
17562 */
17563 final Handler mHandler;
17564
17565 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017566 * Temporary for use in computing invalidate rectangles while
17567 * calling up the hierarchy.
17568 */
17569 final Rect mTmpInvalRect = new Rect();
svetoslavganov75986cf2009-05-14 22:28:01 -070017570
17571 /**
Chet Haasec3aa3612010-06-17 08:50:37 -070017572 * Temporary for use in computing hit areas with transformed views
17573 */
17574 final RectF mTmpTransformRect = new RectF();
17575
17576 /**
Chet Haase599913d2012-07-23 16:22:05 -070017577 * Temporary for use in transforming invalidation rect
17578 */
17579 final Matrix mTmpMatrix = new Matrix();
17580
17581 /**
17582 * Temporary for use in transforming invalidation rect
17583 */
17584 final Transformation mTmpTransformation = new Transformation();
17585
17586 /**
svetoslavganov75986cf2009-05-14 22:28:01 -070017587 * Temporary list for use in collecting focusable descendents of a view.
17588 */
Svetoslav Ganov42138042012-03-20 11:51:39 -070017589 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
svetoslavganov75986cf2009-05-14 22:28:01 -070017590
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017591 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017592 * The id of the window for accessibility purposes.
17593 */
17594 int mAccessibilityWindowId = View.NO_ID;
17595
17596 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -070017597 * Whether to ingore not exposed for accessibility Views when
17598 * reporting the view tree to accessibility services.
17599 */
17600 boolean mIncludeNotImportantViews;
17601
17602 /**
17603 * The drawable for highlighting accessibility focus.
17604 */
17605 Drawable mAccessibilityFocusDrawable;
17606
17607 /**
Philip Milne10ca24a2012-04-23 15:38:27 -070017608 * Show where the margins, bounds and layout bounds are for each view.
17609 */
Dianne Hackborna53de062012-05-08 18:53:51 -070017610 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
Philip Milne10ca24a2012-04-23 15:38:27 -070017611
17612 /**
Romain Guyab4c4f4f2012-05-06 13:11:24 -070017613 * Point used to compute visible regions.
17614 */
17615 final Point mPoint = new Point();
17616
17617 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017618 * Creates a new set of attachment information with the specified
17619 * events handler and thread.
17620 *
17621 * @param handler the events handler the view must use
17622 */
Jeff Brown98365d72012-08-19 20:30:52 -070017623 AttachInfo(IWindowSession session, IWindow window, Display display,
Jeff Browna175a5b2012-02-15 19:18:31 -080017624 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017625 mSession = session;
17626 mWindow = window;
17627 mWindowToken = window.asBinder();
Jeff Brown98365d72012-08-19 20:30:52 -070017628 mDisplay = display;
Jeff Browna175a5b2012-02-15 19:18:31 -080017629 mViewRootImpl = viewRootImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017630 mHandler = handler;
17631 mRootCallbacks = effectPlayer;
17632 }
17633 }
17634
17635 /**
17636 * <p>ScrollabilityCache holds various fields used by a View when scrolling
17637 * is supported. This avoids keeping too many unused fields in most
17638 * instances of View.</p>
17639 */
Mike Cleronf116bf82009-09-27 19:14:12 -070017640 private static class ScrollabilityCache implements Runnable {
Joe Malin32736f02011-01-19 16:14:20 -080017641
Mike Cleronf116bf82009-09-27 19:14:12 -070017642 /**
17643 * Scrollbars are not visible
17644 */
17645 public static final int OFF = 0;
17646
17647 /**
17648 * Scrollbars are visible
17649 */
17650 public static final int ON = 1;
17651
17652 /**
17653 * Scrollbars are fading away
17654 */
17655 public static final int FADING = 2;
17656
17657 public boolean fadeScrollBars;
Joe Malin32736f02011-01-19 16:14:20 -080017658
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017659 public int fadingEdgeLength;
Mike Cleronf116bf82009-09-27 19:14:12 -070017660 public int scrollBarDefaultDelayBeforeFade;
17661 public int scrollBarFadeDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017662
17663 public int scrollBarSize;
17664 public ScrollBarDrawable scrollBar;
Mike Cleronf116bf82009-09-27 19:14:12 -070017665 public float[] interpolatorValues;
17666 public View host;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017667
17668 public final Paint paint;
17669 public final Matrix matrix;
17670 public Shader shader;
17671
Mike Cleronf116bf82009-09-27 19:14:12 -070017672 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
17673
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017674 private static final float[] OPAQUE = { 255 };
17675 private static final float[] TRANSPARENT = { 0.0f };
Joe Malin32736f02011-01-19 16:14:20 -080017676
Mike Cleronf116bf82009-09-27 19:14:12 -070017677 /**
17678 * When fading should start. This time moves into the future every time
17679 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
17680 */
17681 public long fadeStartTime;
17682
17683
17684 /**
17685 * The current state of the scrollbars: ON, OFF, or FADING
17686 */
17687 public int state = OFF;
17688
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017689 private int mLastColor;
17690
Mike Cleronf116bf82009-09-27 19:14:12 -070017691 public ScrollabilityCache(ViewConfiguration configuration, View host) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017692 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
17693 scrollBarSize = configuration.getScaledScrollBarSize();
Romain Guy35b38ce2009-10-07 13:38:55 -070017694 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
17695 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017696
17697 paint = new Paint();
17698 matrix = new Matrix();
17699 // use use a height of 1, and then wack the matrix each time we
17700 // actually use it.
17701 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017702 paint.setShader(shader);
17703 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Romain Guyd679b572012-08-29 21:49:00 -070017704
Mike Cleronf116bf82009-09-27 19:14:12 -070017705 this.host = host;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017706 }
Romain Guy8506ab42009-06-11 17:35:47 -070017707
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017708 public void setFadeColor(int color) {
Romain Guyd679b572012-08-29 21:49:00 -070017709 if (color != mLastColor) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017710 mLastColor = color;
Romain Guy8506ab42009-06-11 17:35:47 -070017711
Romain Guyd679b572012-08-29 21:49:00 -070017712 if (color != 0) {
17713 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
17714 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
17715 paint.setShader(shader);
17716 // Restore the default transfer mode (src_over)
17717 paint.setXfermode(null);
17718 } else {
17719 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
17720 paint.setShader(shader);
17721 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
17722 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017723 }
17724 }
Joe Malin32736f02011-01-19 16:14:20 -080017725
Mike Cleronf116bf82009-09-27 19:14:12 -070017726 public void run() {
Mike Cleron3ecd58c2009-09-28 11:39:02 -070017727 long now = AnimationUtils.currentAnimationTimeMillis();
Mike Cleronf116bf82009-09-27 19:14:12 -070017728 if (now >= fadeStartTime) {
17729
17730 // the animation fades the scrollbars out by changing
17731 // the opacity (alpha) from fully opaque to fully
17732 // transparent
17733 int nextFrame = (int) now;
17734 int framesCount = 0;
17735
17736 Interpolator interpolator = scrollBarInterpolator;
17737
17738 // Start opaque
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017739 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
Mike Cleronf116bf82009-09-27 19:14:12 -070017740
17741 // End transparent
17742 nextFrame += scrollBarFadeDuration;
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017743 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
Mike Cleronf116bf82009-09-27 19:14:12 -070017744
17745 state = FADING;
17746
17747 // Kick off the fade animation
Romain Guy0fd89bf2011-01-26 15:41:30 -080017748 host.invalidate(true);
Mike Cleronf116bf82009-09-27 19:14:12 -070017749 }
17750 }
Svetoslav Ganova0156172011-06-26 17:55:44 -070017751 }
Mike Cleronf116bf82009-09-27 19:14:12 -070017752
Svetoslav Ganova0156172011-06-26 17:55:44 -070017753 /**
17754 * Resuable callback for sending
17755 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
17756 */
17757 private class SendViewScrolledAccessibilityEvent implements Runnable {
17758 public volatile boolean mIsPending;
17759
17760 public void run() {
17761 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
17762 mIsPending = false;
17763 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017764 }
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017765
17766 /**
17767 * <p>
17768 * This class represents a delegate that can be registered in a {@link View}
17769 * to enhance accessibility support via composition rather via inheritance.
17770 * It is specifically targeted to widget developers that extend basic View
17771 * classes i.e. classes in package android.view, that would like their
17772 * applications to be backwards compatible.
17773 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080017774 * <div class="special reference">
17775 * <h3>Developer Guides</h3>
17776 * <p>For more information about making applications accessible, read the
17777 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
17778 * developer guide.</p>
17779 * </div>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017780 * <p>
17781 * A scenario in which a developer would like to use an accessibility delegate
17782 * is overriding a method introduced in a later API version then the minimal API
17783 * version supported by the application. For example, the method
17784 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
17785 * in API version 4 when the accessibility APIs were first introduced. If a
17786 * developer would like his application to run on API version 4 devices (assuming
17787 * all other APIs used by the application are version 4 or lower) and take advantage
17788 * of this method, instead of overriding the method which would break the application's
17789 * backwards compatibility, he can override the corresponding method in this
17790 * delegate and register the delegate in the target View if the API version of
17791 * the system is high enough i.e. the API version is same or higher to the API
17792 * version that introduced
17793 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
17794 * </p>
17795 * <p>
17796 * Here is an example implementation:
17797 * </p>
17798 * <code><pre><p>
17799 * if (Build.VERSION.SDK_INT >= 14) {
17800 * // If the API version is equal of higher than the version in
17801 * // which onInitializeAccessibilityNodeInfo was introduced we
17802 * // register a delegate with a customized implementation.
17803 * View view = findViewById(R.id.view_id);
17804 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
17805 * public void onInitializeAccessibilityNodeInfo(View host,
17806 * AccessibilityNodeInfo info) {
17807 * // Let the default implementation populate the info.
17808 * super.onInitializeAccessibilityNodeInfo(host, info);
17809 * // Set some other information.
17810 * info.setEnabled(host.isEnabled());
17811 * }
17812 * });
17813 * }
17814 * </code></pre></p>
17815 * <p>
17816 * This delegate contains methods that correspond to the accessibility methods
17817 * in View. If a delegate has been specified the implementation in View hands
17818 * off handling to the corresponding method in this delegate. The default
17819 * implementation the delegate methods behaves exactly as the corresponding
17820 * method in View for the case of no accessibility delegate been set. Hence,
17821 * to customize the behavior of a View method, clients can override only the
17822 * corresponding delegate method without altering the behavior of the rest
17823 * accessibility related methods of the host view.
17824 * </p>
17825 */
17826 public static class AccessibilityDelegate {
17827
17828 /**
17829 * Sends an accessibility event of the given type. If accessibility is not
17830 * enabled this method has no effect.
17831 * <p>
17832 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
17833 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
17834 * been set.
17835 * </p>
17836 *
17837 * @param host The View hosting the delegate.
17838 * @param eventType The type of the event to send.
17839 *
17840 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
17841 */
17842 public void sendAccessibilityEvent(View host, int eventType) {
17843 host.sendAccessibilityEventInternal(eventType);
17844 }
17845
17846 /**
alanv8eeefef2012-05-07 16:57:53 -070017847 * Performs the specified accessibility action on the view. For
17848 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
17849 * <p>
17850 * The default implementation behaves as
17851 * {@link View#performAccessibilityAction(int, Bundle)
17852 * View#performAccessibilityAction(int, Bundle)} for the case of
17853 * no accessibility delegate been set.
17854 * </p>
17855 *
17856 * @param action The action to perform.
17857 * @return Whether the action was performed.
17858 *
17859 * @see View#performAccessibilityAction(int, Bundle)
17860 * View#performAccessibilityAction(int, Bundle)
17861 */
17862 public boolean performAccessibilityAction(View host, int action, Bundle args) {
17863 return host.performAccessibilityActionInternal(action, args);
17864 }
17865
17866 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017867 * Sends an accessibility event. This method behaves exactly as
17868 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
17869 * empty {@link AccessibilityEvent} and does not perform a check whether
17870 * accessibility is enabled.
17871 * <p>
17872 * The default implementation behaves as
17873 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17874 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
17875 * the case of no accessibility delegate been set.
17876 * </p>
17877 *
17878 * @param host The View hosting the delegate.
17879 * @param event The event to send.
17880 *
17881 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17882 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17883 */
17884 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
17885 host.sendAccessibilityEventUncheckedInternal(event);
17886 }
17887
17888 /**
17889 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
17890 * to its children for adding their text content to the event.
17891 * <p>
17892 * The default implementation behaves as
17893 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17894 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
17895 * the case of no accessibility delegate been set.
17896 * </p>
17897 *
17898 * @param host The View hosting the delegate.
17899 * @param event The event.
17900 * @return True if the event population was completed.
17901 *
17902 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17903 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17904 */
17905 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17906 return host.dispatchPopulateAccessibilityEventInternal(event);
17907 }
17908
17909 /**
17910 * Gives a chance to the host View to populate the accessibility event with its
17911 * text content.
17912 * <p>
17913 * The default implementation behaves as
17914 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
17915 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
17916 * the case of no accessibility delegate been set.
17917 * </p>
17918 *
17919 * @param host The View hosting the delegate.
17920 * @param event The accessibility event which to populate.
17921 *
17922 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
17923 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
17924 */
17925 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17926 host.onPopulateAccessibilityEventInternal(event);
17927 }
17928
17929 /**
17930 * Initializes an {@link AccessibilityEvent} with information about the
17931 * the host View which is the event source.
17932 * <p>
17933 * The default implementation behaves as
17934 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
17935 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
17936 * the case of no accessibility delegate been set.
17937 * </p>
17938 *
17939 * @param host The View hosting the delegate.
17940 * @param event The event to initialize.
17941 *
17942 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
17943 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
17944 */
17945 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
17946 host.onInitializeAccessibilityEventInternal(event);
17947 }
17948
17949 /**
17950 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
17951 * <p>
17952 * The default implementation behaves as
17953 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17954 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
17955 * the case of no accessibility delegate been set.
17956 * </p>
17957 *
17958 * @param host The View hosting the delegate.
17959 * @param info The instance to initialize.
17960 *
17961 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17962 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17963 */
17964 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
17965 host.onInitializeAccessibilityNodeInfoInternal(info);
17966 }
17967
17968 /**
17969 * Called when a child of the host View has requested sending an
17970 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
17971 * to augment the event.
17972 * <p>
17973 * The default implementation behaves as
17974 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17975 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
17976 * the case of no accessibility delegate been set.
17977 * </p>
17978 *
17979 * @param host The View hosting the delegate.
17980 * @param child The child which requests sending the event.
17981 * @param event The event to be sent.
17982 * @return True if the event should be sent
17983 *
17984 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17985 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17986 */
17987 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
17988 AccessibilityEvent event) {
17989 return host.onRequestSendAccessibilityEventInternal(child, event);
17990 }
Svetoslav Ganov02107852011-10-03 17:06:56 -070017991
17992 /**
17993 * Gets the provider for managing a virtual view hierarchy rooted at this View
17994 * and reported to {@link android.accessibilityservice.AccessibilityService}s
17995 * that explore the window content.
17996 * <p>
17997 * The default implementation behaves as
17998 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
17999 * the case of no accessibility delegate been set.
18000 * </p>
18001 *
18002 * @return The provider.
18003 *
18004 * @see AccessibilityNodeProvider
18005 */
18006 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
18007 return null;
18008 }
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070018009 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080018010}