blob: 9338a51351243d184f135b0de1dbe8ced2915e06 [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 Brown98365d72012-08-19 20:30:52 -070042import android.hardware.display.DisplayManager;
Jeff Brownbd6e1502012-08-28 03:27:37 -070043import android.hardware.display.DisplayManagerGlobal;
Svetoslav Ganovaa780c12012-04-19 23:01:39 -070044import android.os.Bundle;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080045import android.os.Handler;
46import android.os.IBinder;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080047import android.os.Parcel;
48import android.os.Parcelable;
49import android.os.RemoteException;
50import android.os.SystemClock;
Philip Milne10ca24a2012-04-23 15:38:27 -070051import android.os.SystemProperties;
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;
54import android.util.LocaleUtil;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080055import android.util.Log;
Romain Guyd928d682009-03-31 17:52:16 -070056import android.util.Pool;
svetoslavganov75986cf2009-05-14 22:28:01 -070057import android.util.Poolable;
Romain Guyd928d682009-03-31 17:52:16 -070058import android.util.PoolableManager;
svetoslavganov75986cf2009-05-14 22:28:01 -070059import android.util.Pools;
Doug Feltcb3791202011-07-07 11:57:48 -070060import android.util.Property;
svetoslavganov75986cf2009-05-14 22:28:01 -070061import android.util.SparseArray;
Jeff Brown33bbfd22011-02-24 20:55:35 -080062import android.util.TypedValue;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080063import android.view.ContextMenu.ContextMenuInfo;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -070064import android.view.AccessibilityIterators.TextSegmentIterator;
65import android.view.AccessibilityIterators.CharacterTextSegmentIterator;
66import android.view.AccessibilityIterators.WordTextSegmentIterator;
67import android.view.AccessibilityIterators.ParagraphTextSegmentIterator;
svetoslavganov75986cf2009-05-14 22:28:01 -070068import android.view.accessibility.AccessibilityEvent;
69import android.view.accessibility.AccessibilityEventSource;
70import android.view.accessibility.AccessibilityManager;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070071import android.view.accessibility.AccessibilityNodeInfo;
Svetoslav Ganov02107852011-10-03 17:06:56 -070072import android.view.accessibility.AccessibilityNodeProvider;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080073import android.view.animation.Animation;
Mike Cleron3ecd58c2009-09-28 11:39:02 -070074import android.view.animation.AnimationUtils;
Chet Haase64a48c12012-02-13 16:33:29 -080075import android.view.animation.Transformation;
svetoslavganov75986cf2009-05-14 22:28:01 -070076import android.view.inputmethod.EditorInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077import android.view.inputmethod.InputConnection;
78import android.view.inputmethod.InputMethodManager;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080079import android.widget.ScrollBarDrawable;
80
Romain Guy1ef3fdb2011-09-09 15:30:30 -070081import static android.os.Build.VERSION_CODES.*;
Philip Milne6c8ea062012-04-03 17:38:43 -070082import static java.lang.Math.max;
Romain Guy1ef3fdb2011-09-09 15:30:30 -070083
Doug Feltcb3791202011-07-07 11:57:48 -070084import com.android.internal.R;
85import com.android.internal.util.Predicate;
86import com.android.internal.view.menu.MenuBuilder;
87
Christopher Tatea0374192010-10-05 13:06:41 -070088import java.lang.ref.WeakReference;
svetoslavganov75986cf2009-05-14 22:28:01 -070089import java.lang.reflect.InvocationTargetException;
90import java.lang.reflect.Method;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091import java.util.ArrayList;
92import java.util.Arrays;
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070093import java.util.Locale;
Adam Powell4afd62b2011-02-18 15:02:18 -080094import java.util.concurrent.CopyOnWriteArrayList;
Adam Powella9108a22012-07-18 11:18:09 -070095import java.util.concurrent.atomic.AtomicInteger;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080096
97/**
98 * <p>
99 * This class represents the basic building block for user interface components. A View
100 * occupies a rectangular area on the screen and is responsible for drawing and
101 * event handling. View is the base class for <em>widgets</em>, which are
Romain Guy8506ab42009-06-11 17:35:47 -0700102 * used to create interactive UI components (buttons, text fields, etc.). The
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800103 * {@link android.view.ViewGroup} subclass is the base class for <em>layouts</em>, which
104 * are invisible containers that hold other Views (or other ViewGroups) and define
105 * their layout properties.
106 * </p>
107 *
Joe Fernandezb54e7a32011-10-03 15:09:50 -0700108 * <div class="special reference">
109 * <h3>Developer Guides</h3>
110 * <p>For information about using this class to develop your application's user interface,
111 * 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 -0800112 * </div>
Romain Guy8506ab42009-06-11 17:35:47 -0700113 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800114 * <a name="Using"></a>
115 * <h3>Using Views</h3>
116 * <p>
117 * All of the views in a window are arranged in a single tree. You can add views
118 * either from code or by specifying a tree of views in one or more XML layout
119 * files. There are many specialized subclasses of views that act as controls or
120 * are capable of displaying text, images, or other content.
121 * </p>
122 * <p>
123 * Once you have created a tree of views, there are typically a few types of
124 * common operations you may wish to perform:
125 * <ul>
126 * <li><strong>Set properties:</strong> for example setting the text of a
127 * {@link android.widget.TextView}. The available properties and the methods
128 * that set them will vary among the different subclasses of views. Note that
129 * properties that are known at build time can be set in the XML layout
130 * files.</li>
131 * <li><strong>Set focus:</strong> The framework will handled moving focus in
132 * response to user input. To force focus to a specific view, call
133 * {@link #requestFocus}.</li>
134 * <li><strong>Set up listeners:</strong> Views allow clients to set listeners
135 * that will be notified when something interesting happens to the view. For
136 * example, all views will let you set a listener to be notified when the view
137 * gains or loses focus. You can register such a listener using
Romain Guy5c22a8c2011-05-13 11:48:45 -0700138 * {@link #setOnFocusChangeListener(android.view.View.OnFocusChangeListener)}.
Philip Milne6c8ea062012-04-03 17:38:43 -0700139 * Other view subclasses offer more specialized listeners. For example, a Button
Romain Guy5c22a8c2011-05-13 11:48:45 -0700140 * exposes a listener to notify clients when the button is clicked.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 * <li><strong>Set visibility:</strong> You can hide or show views using
Romain Guy5c22a8c2011-05-13 11:48:45 -0700142 * {@link #setVisibility(int)}.</li>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800143 * </ul>
144 * </p>
145 * <p><em>
146 * Note: The Android framework is responsible for measuring, laying out and
147 * drawing views. You should not call methods that perform these actions on
148 * views yourself unless you are actually implementing a
149 * {@link android.view.ViewGroup}.
150 * </em></p>
151 *
152 * <a name="Lifecycle"></a>
153 * <h3>Implementing a Custom View</h3>
154 *
155 * <p>
156 * To implement a custom view, you will usually begin by providing overrides for
157 * some of the standard methods that the framework calls on all views. You do
158 * not need to override all of these methods. In fact, you can start by just
159 * overriding {@link #onDraw(android.graphics.Canvas)}.
160 * <table border="2" width="85%" align="center" cellpadding="5">
161 * <thead>
162 * <tr><th>Category</th> <th>Methods</th> <th>Description</th></tr>
163 * </thead>
164 *
165 * <tbody>
166 * <tr>
167 * <td rowspan="2">Creation</td>
168 * <td>Constructors</td>
169 * <td>There is a form of the constructor that are called when the view
170 * is created from code and a form that is called when the view is
171 * inflated from a layout file. The second form should parse and apply
172 * any attributes defined in the layout file.
173 * </td>
174 * </tr>
175 * <tr>
176 * <td><code>{@link #onFinishInflate()}</code></td>
177 * <td>Called after a view and all of its children has been inflated
178 * from XML.</td>
179 * </tr>
180 *
181 * <tr>
182 * <td rowspan="3">Layout</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700183 * <td><code>{@link #onMeasure(int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800184 * <td>Called to determine the size requirements for this view and all
185 * of its children.
186 * </td>
187 * </tr>
188 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700189 * <td><code>{@link #onLayout(boolean, int, int, int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800190 * <td>Called when this view should assign a size and position to all
191 * of its children.
192 * </td>
193 * </tr>
194 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700195 * <td><code>{@link #onSizeChanged(int, int, int, int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800196 * <td>Called when the size of this view has changed.
197 * </td>
198 * </tr>
199 *
200 * <tr>
201 * <td>Drawing</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700202 * <td><code>{@link #onDraw(android.graphics.Canvas)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800203 * <td>Called when the view should render its content.
204 * </td>
205 * </tr>
206 *
207 * <tr>
208 * <td rowspan="4">Event processing</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700209 * <td><code>{@link #onKeyDown(int, KeyEvent)}</code></td>
Jean Chalard405bc512012-05-29 19:12:34 +0900210 * <td>Called when a new hardware key event occurs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800211 * </td>
212 * </tr>
213 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700214 * <td><code>{@link #onKeyUp(int, KeyEvent)}</code></td>
Jean Chalard405bc512012-05-29 19:12:34 +0900215 * <td>Called when a hardware key up event occurs.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800216 * </td>
217 * </tr>
218 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700219 * <td><code>{@link #onTrackballEvent(MotionEvent)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800220 * <td>Called when a trackball motion event occurs.
221 * </td>
222 * </tr>
223 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700224 * <td><code>{@link #onTouchEvent(MotionEvent)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800225 * <td>Called when a touch screen motion event occurs.
226 * </td>
227 * </tr>
228 *
229 * <tr>
230 * <td rowspan="2">Focus</td>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700231 * <td><code>{@link #onFocusChanged(boolean, int, android.graphics.Rect)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800232 * <td>Called when the view gains or loses focus.
233 * </td>
234 * </tr>
235 *
236 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700237 * <td><code>{@link #onWindowFocusChanged(boolean)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800238 * <td>Called when the window containing the view gains or loses focus.
239 * </td>
240 * </tr>
241 *
242 * <tr>
243 * <td rowspan="3">Attaching</td>
244 * <td><code>{@link #onAttachedToWindow()}</code></td>
245 * <td>Called when the view is attached to a window.
246 * </td>
247 * </tr>
248 *
249 * <tr>
250 * <td><code>{@link #onDetachedFromWindow}</code></td>
251 * <td>Called when the view is detached from its window.
252 * </td>
253 * </tr>
254 *
255 * <tr>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700256 * <td><code>{@link #onWindowVisibilityChanged(int)}</code></td>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800257 * <td>Called when the visibility of the window containing the view
258 * has changed.
259 * </td>
260 * </tr>
261 * </tbody>
262 *
263 * </table>
264 * </p>
265 *
266 * <a name="IDs"></a>
267 * <h3>IDs</h3>
268 * Views may have an integer id associated with them. These ids are typically
269 * assigned in the layout XML files, and are used to find specific views within
270 * the view tree. A common pattern is to:
271 * <ul>
272 * <li>Define a Button in the layout file and assign it a unique ID.
273 * <pre>
Gilles Debunne0243caf2010-08-24 23:06:35 -0700274 * &lt;Button
275 * android:id="@+id/my_button"
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800276 * android:layout_width="wrap_content"
277 * android:layout_height="wrap_content"
278 * android:text="@string/my_button_text"/&gt;
279 * </pre></li>
280 * <li>From the onCreate method of an Activity, find the Button
281 * <pre class="prettyprint">
282 * Button myButton = (Button) findViewById(R.id.my_button);
283 * </pre></li>
284 * </ul>
285 * <p>
286 * View IDs need not be unique throughout the tree, but it is good practice to
287 * ensure that they are at least unique within the part of the tree you are
288 * searching.
289 * </p>
290 *
291 * <a name="Position"></a>
292 * <h3>Position</h3>
293 * <p>
294 * The geometry of a view is that of a rectangle. A view has a location,
295 * expressed as a pair of <em>left</em> and <em>top</em> coordinates, and
296 * two dimensions, expressed as a width and a height. The unit for location
297 * and dimensions is the pixel.
298 * </p>
299 *
300 * <p>
301 * It is possible to retrieve the location of a view by invoking the methods
302 * {@link #getLeft()} and {@link #getTop()}. The former returns the left, or X,
303 * coordinate of the rectangle representing the view. The latter returns the
304 * top, or Y, coordinate of the rectangle representing the view. These methods
305 * both return the location of the view relative to its parent. For instance,
306 * when getLeft() returns 20, that means the view is located 20 pixels to the
307 * right of the left edge of its direct parent.
308 * </p>
309 *
310 * <p>
311 * In addition, several convenience methods are offered to avoid unnecessary
312 * computations, namely {@link #getRight()} and {@link #getBottom()}.
313 * These methods return the coordinates of the right and bottom edges of the
314 * rectangle representing the view. For instance, calling {@link #getRight()}
315 * is similar to the following computation: <code>getLeft() + getWidth()</code>
316 * (see <a href="#SizePaddingMargins">Size</a> for more information about the width.)
317 * </p>
318 *
319 * <a name="SizePaddingMargins"></a>
320 * <h3>Size, padding and margins</h3>
321 * <p>
322 * The size of a view is expressed with a width and a height. A view actually
323 * possess two pairs of width and height values.
324 * </p>
325 *
326 * <p>
327 * The first pair is known as <em>measured width</em> and
328 * <em>measured height</em>. These dimensions define how big a view wants to be
329 * within its parent (see <a href="#Layout">Layout</a> for more details.) The
330 * measured dimensions can be obtained by calling {@link #getMeasuredWidth()}
331 * and {@link #getMeasuredHeight()}.
332 * </p>
333 *
334 * <p>
335 * The second pair is simply known as <em>width</em> and <em>height</em>, or
336 * sometimes <em>drawing width</em> and <em>drawing height</em>. These
337 * dimensions define the actual size of the view on screen, at drawing time and
338 * after layout. These values may, but do not have to, be different from the
339 * measured width and height. The width and height can be obtained by calling
340 * {@link #getWidth()} and {@link #getHeight()}.
341 * </p>
342 *
343 * <p>
344 * To measure its dimensions, a view takes into account its padding. The padding
345 * is expressed in pixels for the left, top, right and bottom parts of the view.
346 * Padding can be used to offset the content of the view by a specific amount of
347 * pixels. For instance, a left padding of 2 will push the view's content by
348 * 2 pixels to the right of the left edge. Padding can be set using the
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -0700349 * {@link #setPadding(int, int, int, int)} or {@link #setPaddingRelative(int, int, int, int)}
350 * method and queried by calling {@link #getPaddingLeft()}, {@link #getPaddingTop()},
351 * {@link #getPaddingRight()}, {@link #getPaddingBottom()}, {@link #getPaddingStart()},
352 * {@link #getPaddingEnd()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800353 * </p>
354 *
355 * <p>
356 * Even though a view can define a padding, it does not provide any support for
357 * margins. However, view groups provide such a support. Refer to
358 * {@link android.view.ViewGroup} and
359 * {@link android.view.ViewGroup.MarginLayoutParams} for further information.
360 * </p>
361 *
362 * <a name="Layout"></a>
363 * <h3>Layout</h3>
364 * <p>
365 * Layout is a two pass process: a measure pass and a layout pass. The measuring
366 * pass is implemented in {@link #measure(int, int)} and is a top-down traversal
367 * of the view tree. Each view pushes dimension specifications down the tree
368 * during the recursion. At the end of the measure pass, every view has stored
369 * its measurements. The second pass happens in
370 * {@link #layout(int,int,int,int)} and is also top-down. During
371 * this pass each parent is responsible for positioning all of its children
372 * using the sizes computed in the measure pass.
373 * </p>
374 *
375 * <p>
376 * When a view's measure() method returns, its {@link #getMeasuredWidth()} and
377 * {@link #getMeasuredHeight()} values must be set, along with those for all of
378 * that view's descendants. A view's measured width and measured height values
379 * must respect the constraints imposed by the view's parents. This guarantees
380 * that at the end of the measure pass, all parents accept all of their
381 * children's measurements. A parent view may call measure() more than once on
382 * its children. For example, the parent may measure each child once with
383 * unspecified dimensions to find out how big they want to be, then call
384 * measure() on them again with actual numbers if the sum of all the children's
385 * unconstrained sizes is too big or too small.
386 * </p>
387 *
388 * <p>
389 * The measure pass uses two classes to communicate dimensions. The
390 * {@link MeasureSpec} class is used by views to tell their parents how they
391 * want to be measured and positioned. The base LayoutParams class just
392 * describes how big the view wants to be for both width and height. For each
393 * dimension, it can specify one of:
394 * <ul>
395 * <li> an exact number
Romain Guy980a9382010-01-08 15:06:28 -0800396 * <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 -0800397 * (minus padding)
398 * <li> WRAP_CONTENT, which means that the view wants to be just big enough to
399 * enclose its content (plus padding).
400 * </ul>
401 * There are subclasses of LayoutParams for different subclasses of ViewGroup.
402 * For example, AbsoluteLayout has its own subclass of LayoutParams which adds
403 * an X and Y value.
404 * </p>
405 *
406 * <p>
407 * MeasureSpecs are used to push requirements down the tree from parent to
408 * child. A MeasureSpec can be in one of three modes:
409 * <ul>
410 * <li>UNSPECIFIED: This is used by a parent to determine the desired dimension
411 * of a child view. For example, a LinearLayout may call measure() on its child
412 * with the height set to UNSPECIFIED and a width of EXACTLY 240 to find out how
413 * tall the child view wants to be given a width of 240 pixels.
414 * <li>EXACTLY: This is used by the parent to impose an exact size on the
415 * child. The child must use this size, and guarantee that all of its
416 * descendants will fit within this size.
417 * <li>AT_MOST: This is used by the parent to impose a maximum size on the
418 * child. The child must gurantee that it and all of its descendants will fit
419 * within this size.
420 * </ul>
421 * </p>
422 *
423 * <p>
424 * To intiate a layout, call {@link #requestLayout}. This method is typically
425 * called by a view on itself when it believes that is can no longer fit within
426 * its current bounds.
427 * </p>
428 *
429 * <a name="Drawing"></a>
430 * <h3>Drawing</h3>
431 * <p>
432 * Drawing is handled by walking the tree and rendering each view that
Joe Fernandez558459f2011-10-13 16:47:36 -0700433 * intersects the invalid region. Because the tree is traversed in-order,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800434 * this means that parents will draw before (i.e., behind) their children, with
435 * siblings drawn in the order they appear in the tree.
436 * If you set a background drawable for a View, then the View will draw it for you
437 * before calling back to its <code>onDraw()</code> method.
438 * </p>
439 *
440 * <p>
Romain Guy8506ab42009-06-11 17:35:47 -0700441 * 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 -0800442 * </p>
443 *
444 * <p>
445 * To force a view to draw, call {@link #invalidate()}.
446 * </p>
447 *
448 * <a name="EventHandlingThreading"></a>
449 * <h3>Event Handling and Threading</h3>
450 * <p>
451 * The basic cycle of a view is as follows:
452 * <ol>
453 * <li>An event comes in and is dispatched to the appropriate view. The view
454 * handles the event and notifies any listeners.</li>
455 * <li>If in the course of processing the event, the view's bounds may need
456 * to be changed, the view will call {@link #requestLayout()}.</li>
457 * <li>Similarly, if in the course of processing the event the view's appearance
458 * may need to be changed, the view will call {@link #invalidate()}.</li>
459 * <li>If either {@link #requestLayout()} or {@link #invalidate()} were called,
460 * the framework will take care of measuring, laying out, and drawing the tree
461 * as appropriate.</li>
462 * </ol>
463 * </p>
464 *
465 * <p><em>Note: The entire view tree is single threaded. You must always be on
466 * the UI thread when calling any method on any view.</em>
467 * If you are doing work on other threads and want to update the state of a view
468 * from that thread, you should use a {@link Handler}.
469 * </p>
470 *
471 * <a name="FocusHandling"></a>
472 * <h3>Focus Handling</h3>
473 * <p>
474 * The framework will handle routine focus movement in response to user input.
475 * This includes changing the focus as views are removed or hidden, or as new
476 * views become available. Views indicate their willingness to take focus
477 * through the {@link #isFocusable} method. To change whether a view can take
478 * focus, call {@link #setFocusable(boolean)}. When in touch mode (see notes below)
479 * views indicate whether they still would like focus via {@link #isFocusableInTouchMode}
480 * and can change this via {@link #setFocusableInTouchMode(boolean)}.
481 * </p>
482 * <p>
483 * Focus movement is based on an algorithm which finds the nearest neighbor in a
484 * given direction. In rare cases, the default algorithm may not match the
485 * intended behavior of the developer. In these situations, you can provide
486 * explicit overrides by using these XML attributes in the layout file:
487 * <pre>
488 * nextFocusDown
489 * nextFocusLeft
490 * nextFocusRight
491 * nextFocusUp
492 * </pre>
493 * </p>
494 *
495 *
496 * <p>
497 * To get a particular view to take focus, call {@link #requestFocus()}.
498 * </p>
499 *
500 * <a name="TouchMode"></a>
501 * <h3>Touch Mode</h3>
502 * <p>
503 * When a user is navigating a user interface via directional keys such as a D-pad, it is
504 * necessary to give focus to actionable items such as buttons so the user can see
505 * what will take input. If the device has touch capabilities, however, and the user
506 * begins interacting with the interface by touching it, it is no longer necessary to
507 * always highlight, or give focus to, a particular view. This motivates a mode
508 * for interaction named 'touch mode'.
509 * </p>
510 * <p>
511 * For a touch capable device, once the user touches the screen, the device
512 * will enter touch mode. From this point onward, only views for which
513 * {@link #isFocusableInTouchMode} is true will be focusable, such as text editing widgets.
514 * Other views that are touchable, like buttons, will not take focus when touched; they will
515 * only fire the on click listeners.
516 * </p>
517 * <p>
518 * Any time a user hits a directional key, such as a D-pad direction, the view device will
519 * exit touch mode, and find a view to take focus, so that the user may resume interacting
520 * with the user interface without touching the screen again.
521 * </p>
522 * <p>
523 * The touch mode state is maintained across {@link android.app.Activity}s. Call
524 * {@link #isInTouchMode} to see whether the device is currently in touch mode.
525 * </p>
526 *
527 * <a name="Scrolling"></a>
528 * <h3>Scrolling</h3>
529 * <p>
530 * The framework provides basic support for views that wish to internally
531 * scroll their content. This includes keeping track of the X and Y scroll
532 * offset as well as mechanisms for drawing scrollbars. See
Joe Malin32736f02011-01-19 16:14:20 -0800533 * {@link #scrollBy(int, int)}, {@link #scrollTo(int, int)}, and
Mike Cleronf116bf82009-09-27 19:14:12 -0700534 * {@link #awakenScrollBars()} for more details.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800535 * </p>
536 *
537 * <a name="Tags"></a>
538 * <h3>Tags</h3>
539 * <p>
540 * Unlike IDs, tags are not used to identify views. Tags are essentially an
541 * extra piece of information that can be associated with a view. They are most
542 * often used as a convenience to store data related to views in the views
543 * themselves rather than by putting them in a separate structure.
544 * </p>
545 *
Chet Haasecb150fe2012-05-03 15:15:05 -0700546 * <a name="Properties"></a>
547 * <h3>Properties</h3>
548 * <p>
549 * The View class exposes an {@link #ALPHA} property, as well as several transform-related
550 * properties, such as {@link #TRANSLATION_X} and {@link #TRANSLATION_Y}. These properties are
551 * available both in the {@link Property} form as well as in similarly-named setter/getter
552 * methods (such as {@link #setAlpha(float)} for {@link #ALPHA}). These properties can
553 * be used to set persistent state associated with these rendering-related properties on the view.
554 * The properties and methods can also be used in conjunction with
555 * {@link android.animation.Animator Animator}-based animations, described more in the
556 * <a href="#Animation">Animation</a> section.
557 * </p>
558 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800559 * <a name="Animation"></a>
560 * <h3>Animation</h3>
561 * <p>
Chet Haasecb150fe2012-05-03 15:15:05 -0700562 * Starting with Android 3.0, the preferred way of animating views is to use the
563 * {@link android.animation} package APIs. These {@link android.animation.Animator Animator}-based
564 * classes change actual properties of the View object, such as {@link #setAlpha(float) alpha} and
565 * {@link #setTranslationX(float) translationX}. This behavior is contrasted to that of the pre-3.0
566 * {@link android.view.animation.Animation Animation}-based classes, which instead animate only
567 * how the view is drawn on the display. In particular, the {@link ViewPropertyAnimator} class
568 * makes animating these View properties particularly easy and efficient.
569 * </p>
570 * <p>
571 * 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 -0800572 * You can attach an {@link Animation} object to a view using
573 * {@link #setAnimation(Animation)} or
574 * {@link #startAnimation(Animation)}. The animation can alter the scale,
575 * rotation, translation and alpha of a view over time. If the animation is
576 * attached to a view that has children, the animation will affect the entire
577 * subtree rooted by that node. When an animation is started, the framework will
578 * take care of redrawing the appropriate views until the animation completes.
579 * </p>
580 *
Jeff Brown85a31762010-09-01 17:01:00 -0700581 * <a name="Security"></a>
582 * <h3>Security</h3>
583 * <p>
584 * Sometimes it is essential that an application be able to verify that an action
585 * is being performed with the full knowledge and consent of the user, such as
586 * granting a permission request, making a purchase or clicking on an advertisement.
587 * Unfortunately, a malicious application could try to spoof the user into
588 * performing these actions, unaware, by concealing the intended purpose of the view.
589 * As a remedy, the framework offers a touch filtering mechanism that can be used to
590 * improve the security of views that provide access to sensitive functionality.
591 * </p><p>
Romain Guy5c22a8c2011-05-13 11:48:45 -0700592 * To enable touch filtering, call {@link #setFilterTouchesWhenObscured(boolean)} or set the
Jeff Brown49ed71d2010-12-06 17:13:33 -0800593 * android:filterTouchesWhenObscured layout attribute to true. When enabled, the framework
Jeff Brown85a31762010-09-01 17:01:00 -0700594 * will discard touches that are received whenever the view's window is obscured by
595 * another visible window. As a result, the view will not receive touches whenever a
596 * toast, dialog or other window appears above the view's window.
597 * </p><p>
598 * For more fine-grained control over security, consider overriding the
Romain Guy5c22a8c2011-05-13 11:48:45 -0700599 * {@link #onFilterTouchEventForSecurity(MotionEvent)} method to implement your own
600 * security policy. See also {@link MotionEvent#FLAG_WINDOW_IS_OBSCURED}.
Jeff Brown85a31762010-09-01 17:01:00 -0700601 * </p>
602 *
Romain Guy171c5922011-01-06 10:04:23 -0800603 * @attr ref android.R.styleable#View_alpha
Romain Guyd6a463a2009-05-21 23:10:10 -0700604 * @attr ref android.R.styleable#View_background
605 * @attr ref android.R.styleable#View_clickable
606 * @attr ref android.R.styleable#View_contentDescription
607 * @attr ref android.R.styleable#View_drawingCacheQuality
608 * @attr ref android.R.styleable#View_duplicateParentState
609 * @attr ref android.R.styleable#View_id
Romain Guy1ef3fdb2011-09-09 15:30:30 -0700610 * @attr ref android.R.styleable#View_requiresFadingEdge
Philip Milne6c8ea062012-04-03 17:38:43 -0700611 * @attr ref android.R.styleable#View_fadeScrollbars
Romain Guyd6a463a2009-05-21 23:10:10 -0700612 * @attr ref android.R.styleable#View_fadingEdgeLength
Jeff Brown85a31762010-09-01 17:01:00 -0700613 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800614 * @attr ref android.R.styleable#View_fitsSystemWindows
Romain Guyd6a463a2009-05-21 23:10:10 -0700615 * @attr ref android.R.styleable#View_isScrollContainer
616 * @attr ref android.R.styleable#View_focusable
617 * @attr ref android.R.styleable#View_focusableInTouchMode
618 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
619 * @attr ref android.R.styleable#View_keepScreenOn
Romain Guy171c5922011-01-06 10:04:23 -0800620 * @attr ref android.R.styleable#View_layerType
Romain Guyd6a463a2009-05-21 23:10:10 -0700621 * @attr ref android.R.styleable#View_longClickable
622 * @attr ref android.R.styleable#View_minHeight
623 * @attr ref android.R.styleable#View_minWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800624 * @attr ref android.R.styleable#View_nextFocusDown
625 * @attr ref android.R.styleable#View_nextFocusLeft
626 * @attr ref android.R.styleable#View_nextFocusRight
627 * @attr ref android.R.styleable#View_nextFocusUp
Romain Guyd6a463a2009-05-21 23:10:10 -0700628 * @attr ref android.R.styleable#View_onClick
629 * @attr ref android.R.styleable#View_padding
630 * @attr ref android.R.styleable#View_paddingBottom
631 * @attr ref android.R.styleable#View_paddingLeft
632 * @attr ref android.R.styleable#View_paddingRight
633 * @attr ref android.R.styleable#View_paddingTop
Fabrice Di Meglio101d5aa2012-02-16 18:36:06 -0800634 * @attr ref android.R.styleable#View_paddingStart
635 * @attr ref android.R.styleable#View_paddingEnd
Romain Guyd6a463a2009-05-21 23:10:10 -0700636 * @attr ref android.R.styleable#View_saveEnabled
Chet Haase73066682010-11-29 15:55:32 -0800637 * @attr ref android.R.styleable#View_rotation
638 * @attr ref android.R.styleable#View_rotationX
639 * @attr ref android.R.styleable#View_rotationY
640 * @attr ref android.R.styleable#View_scaleX
641 * @attr ref android.R.styleable#View_scaleY
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800642 * @attr ref android.R.styleable#View_scrollX
643 * @attr ref android.R.styleable#View_scrollY
Romain Guyd6a463a2009-05-21 23:10:10 -0700644 * @attr ref android.R.styleable#View_scrollbarSize
645 * @attr ref android.R.styleable#View_scrollbarStyle
646 * @attr ref android.R.styleable#View_scrollbars
Mike Cleronf116bf82009-09-27 19:14:12 -0700647 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
648 * @attr ref android.R.styleable#View_scrollbarFadeDuration
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800649 * @attr ref android.R.styleable#View_scrollbarTrackHorizontal
650 * @attr ref android.R.styleable#View_scrollbarThumbHorizontal
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800651 * @attr ref android.R.styleable#View_scrollbarThumbVertical
652 * @attr ref android.R.styleable#View_scrollbarTrackVertical
653 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawHorizontalTrack
654 * @attr ref android.R.styleable#View_scrollbarAlwaysDrawVerticalTrack
Romain Guyd6a463a2009-05-21 23:10:10 -0700655 * @attr ref android.R.styleable#View_soundEffectsEnabled
656 * @attr ref android.R.styleable#View_tag
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -0700657 * @attr ref android.R.styleable#View_textAlignment
Chet Haase73066682010-11-29 15:55:32 -0800658 * @attr ref android.R.styleable#View_transformPivotX
659 * @attr ref android.R.styleable#View_transformPivotY
660 * @attr ref android.R.styleable#View_translationX
661 * @attr ref android.R.styleable#View_translationY
Romain Guyd6a463a2009-05-21 23:10:10 -0700662 * @attr ref android.R.styleable#View_visibility
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800663 *
664 * @see android.view.ViewGroup
665 */
Fabrice Di Megliob03b4342012-06-04 12:55:30 -0700666public class View implements Drawable.Callback, KeyEvent.Callback,
Adam Powell8fc54f92011-09-07 16:40:45 -0700667 AccessibilityEventSource {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800668 private static final boolean DBG = false;
669
670 /**
671 * The logging tag used by this class with android.util.Log.
672 */
673 protected static final String VIEW_LOG_TAG = "View";
674
675 /**
Guang Zhu0d607fb2012-05-11 19:34:56 -0700676 * When set to true, apps will draw debugging information about their layouts.
Romain Guy4b8c4f82012-04-27 15:48:35 -0700677 *
678 * @hide
679 */
680 public static final String DEBUG_LAYOUT_PROPERTY = "debug.layout";
681
682 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800683 * Used to mark a View that has no ID.
684 */
685 public static final int NO_ID = -1;
686
687 /**
688 * This view does not want keystrokes. Use with TAKES_FOCUS_MASK when
689 * calling setFlags.
690 */
691 private static final int NOT_FOCUSABLE = 0x00000000;
692
693 /**
694 * This view wants keystrokes. Use with TAKES_FOCUS_MASK when calling
695 * setFlags.
696 */
697 private static final int FOCUSABLE = 0x00000001;
698
699 /**
700 * Mask for use with setFlags indicating bits used for focus.
701 */
702 private static final int FOCUSABLE_MASK = 0x00000001;
703
704 /**
705 * This view will adjust its padding to fit sytem windows (e.g. status bar)
706 */
707 private static final int FITS_SYSTEM_WINDOWS = 0x00000002;
708
709 /**
Scott Main812634c22011-07-27 13:22:35 -0700710 * This view is visible.
711 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
712 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800713 */
714 public static final int VISIBLE = 0x00000000;
715
716 /**
717 * This view is invisible, but it still takes up space for layout purposes.
Scott Main812634c22011-07-27 13:22:35 -0700718 * Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
719 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800720 */
721 public static final int INVISIBLE = 0x00000004;
722
723 /**
724 * This view is invisible, and it doesn't take any space for layout
Scott Main812634c22011-07-27 13:22:35 -0700725 * purposes. Use with {@link #setVisibility} and <a href="#attr_android:visibility">{@code
726 * android:visibility}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800727 */
728 public static final int GONE = 0x00000008;
729
730 /**
731 * Mask for use with setFlags indicating bits used for visibility.
732 * {@hide}
733 */
734 static final int VISIBILITY_MASK = 0x0000000C;
735
736 private static final int[] VISIBILITY_FLAGS = {VISIBLE, INVISIBLE, GONE};
737
738 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -0700739 * This view is enabled. Interpretation varies by subclass.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800740 * Use with ENABLED_MASK when calling setFlags.
741 * {@hide}
742 */
743 static final int ENABLED = 0x00000000;
744
745 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -0700746 * This view is disabled. Interpretation varies by subclass.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800747 * Use with ENABLED_MASK when calling setFlags.
748 * {@hide}
749 */
750 static final int DISABLED = 0x00000020;
751
752 /**
753 * Mask for use with setFlags indicating bits used for indicating whether
754 * this view is enabled
755 * {@hide}
756 */
757 static final int ENABLED_MASK = 0x00000020;
758
759 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -0700760 * This view won't draw. {@link #onDraw(android.graphics.Canvas)} won't be
761 * called and further optimizations will be performed. It is okay to have
762 * this flag set and a background. Use with DRAW_MASK when calling setFlags.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800763 * {@hide}
764 */
765 static final int WILL_NOT_DRAW = 0x00000080;
766
767 /**
768 * Mask for use with setFlags indicating bits used for indicating whether
769 * this view is will draw
770 * {@hide}
771 */
772 static final int DRAW_MASK = 0x00000080;
773
774 /**
775 * <p>This view doesn't show scrollbars.</p>
776 * {@hide}
777 */
778 static final int SCROLLBARS_NONE = 0x00000000;
779
780 /**
781 * <p>This view shows horizontal scrollbars.</p>
782 * {@hide}
783 */
784 static final int SCROLLBARS_HORIZONTAL = 0x00000100;
785
786 /**
787 * <p>This view shows vertical scrollbars.</p>
788 * {@hide}
789 */
790 static final int SCROLLBARS_VERTICAL = 0x00000200;
791
792 /**
793 * <p>Mask for use with setFlags indicating bits used for indicating which
794 * scrollbars are enabled.</p>
795 * {@hide}
796 */
797 static final int SCROLLBARS_MASK = 0x00000300;
798
Jeff Brown85a31762010-09-01 17:01:00 -0700799 /**
800 * Indicates that the view should filter touches when its window is obscured.
801 * Refer to the class comments for more information about this security feature.
802 * {@hide}
803 */
804 static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400;
805
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -0700806 /**
807 * Set for framework elements that use FITS_SYSTEM_WINDOWS, to indicate
808 * that they are optional and should be skipped if the window has
809 * requested system UI flags that ignore those insets for layout.
810 */
811 static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800812
813 /**
814 * <p>This view doesn't show fading edges.</p>
815 * {@hide}
816 */
817 static final int FADING_EDGE_NONE = 0x00000000;
818
819 /**
820 * <p>This view shows horizontal fading edges.</p>
821 * {@hide}
822 */
823 static final int FADING_EDGE_HORIZONTAL = 0x00001000;
824
825 /**
826 * <p>This view shows vertical fading edges.</p>
827 * {@hide}
828 */
829 static final int FADING_EDGE_VERTICAL = 0x00002000;
830
831 /**
832 * <p>Mask for use with setFlags indicating bits used for indicating which
833 * fading edges are enabled.</p>
834 * {@hide}
835 */
836 static final int FADING_EDGE_MASK = 0x00003000;
837
838 /**
839 * <p>Indicates this view can be clicked. When clickable, a View reacts
840 * to clicks by notifying the OnClickListener.<p>
841 * {@hide}
842 */
843 static final int CLICKABLE = 0x00004000;
844
845 /**
846 * <p>Indicates this view is caching its drawing into a bitmap.</p>
847 * {@hide}
848 */
849 static final int DRAWING_CACHE_ENABLED = 0x00008000;
850
851 /**
852 * <p>Indicates that no icicle should be saved for this view.<p>
853 * {@hide}
854 */
855 static final int SAVE_DISABLED = 0x000010000;
856
857 /**
858 * <p>Mask for use with setFlags indicating bits used for the saveEnabled
859 * property.</p>
860 * {@hide}
861 */
862 static final int SAVE_DISABLED_MASK = 0x000010000;
863
864 /**
865 * <p>Indicates that no drawing cache should ever be created for this view.<p>
866 * {@hide}
867 */
868 static final int WILL_NOT_CACHE_DRAWING = 0x000020000;
869
870 /**
871 * <p>Indicates this view can take / keep focus when int touch mode.</p>
872 * {@hide}
873 */
874 static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000;
875
876 /**
877 * <p>Enables low quality mode for the drawing cache.</p>
878 */
879 public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000;
880
881 /**
882 * <p>Enables high quality mode for the drawing cache.</p>
883 */
884 public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000;
885
886 /**
887 * <p>Enables automatic quality mode for the drawing cache.</p>
888 */
889 public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000;
890
891 private static final int[] DRAWING_CACHE_QUALITY_FLAGS = {
892 DRAWING_CACHE_QUALITY_AUTO, DRAWING_CACHE_QUALITY_LOW, DRAWING_CACHE_QUALITY_HIGH
893 };
894
895 /**
896 * <p>Mask for use with setFlags indicating bits used for the cache
897 * quality property.</p>
898 * {@hide}
899 */
900 static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000;
901
902 /**
903 * <p>
904 * Indicates this view can be long clicked. When long clickable, a View
905 * reacts to long clicks by notifying the OnLongClickListener or showing a
906 * context menu.
907 * </p>
908 * {@hide}
909 */
910 static final int LONG_CLICKABLE = 0x00200000;
911
912 /**
913 * <p>Indicates that this view gets its drawable states from its direct parent
914 * and ignores its original internal states.</p>
915 *
916 * @hide
917 */
918 static final int DUPLICATE_PARENT_STATE = 0x00400000;
919
920 /**
921 * The scrollbar style to display the scrollbars inside the content area,
922 * without increasing the padding. The scrollbars will be overlaid with
923 * translucency on the view's content.
924 */
925 public static final int SCROLLBARS_INSIDE_OVERLAY = 0;
926
927 /**
928 * The scrollbar style to display the scrollbars inside the padded area,
929 * increasing the padding of the view. The scrollbars will not overlap the
930 * content area of the view.
931 */
932 public static final int SCROLLBARS_INSIDE_INSET = 0x01000000;
933
934 /**
935 * The scrollbar style to display the scrollbars at the edge of the view,
936 * without increasing the padding. The scrollbars will be overlaid with
937 * translucency.
938 */
939 public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000;
940
941 /**
942 * The scrollbar style to display the scrollbars at the edge of the view,
943 * increasing the padding of the view. The scrollbars will only overlap the
944 * background, if any.
945 */
946 public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000;
947
948 /**
949 * Mask to check if the scrollbar style is overlay or inset.
950 * {@hide}
951 */
952 static final int SCROLLBARS_INSET_MASK = 0x01000000;
953
954 /**
955 * Mask to check if the scrollbar style is inside or outside.
956 * {@hide}
957 */
958 static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000;
959
960 /**
961 * Mask for scrollbar style.
962 * {@hide}
963 */
964 static final int SCROLLBARS_STYLE_MASK = 0x03000000;
965
966 /**
967 * View flag indicating that the screen should remain on while the
968 * window containing this view is visible to the user. This effectively
969 * takes care of automatically setting the WindowManager's
970 * {@link WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON}.
971 */
972 public static final int KEEP_SCREEN_ON = 0x04000000;
973
974 /**
975 * View flag indicating whether this view should have sound effects enabled
976 * for events such as clicking and touching.
977 */
978 public static final int SOUND_EFFECTS_ENABLED = 0x08000000;
979
980 /**
981 * View flag indicating whether this view should have haptic feedback
982 * enabled for events such as long presses.
983 */
984 public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000;
985
986 /**
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -0700987 * <p>Indicates that the view hierarchy should stop saving state when
988 * it reaches this view. If state saving is initiated immediately at
989 * the view, it will be allowed.
990 * {@hide}
991 */
992 static final int PARENT_SAVE_DISABLED = 0x20000000;
993
994 /**
995 * <p>Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED.</p>
996 * {@hide}
997 */
998 static final int PARENT_SAVE_DISABLED_MASK = 0x20000000;
999
1000 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07001001 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1002 * should add all focusable Views regardless if they are focusable in touch mode.
1003 */
1004 public static final int FOCUSABLES_ALL = 0x00000000;
1005
1006 /**
1007 * View flag indicating whether {@link #addFocusables(ArrayList, int, int)}
1008 * should add only Views focusable in touch mode.
1009 */
1010 public static final int FOCUSABLES_TOUCH_MODE = 0x00000001;
1011
1012 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001013 * Use with {@link #focusSearch(int)}. Move focus to the previous selectable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001014 * item.
1015 */
1016 public static final int FOCUS_BACKWARD = 0x00000001;
1017
1018 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001019 * Use with {@link #focusSearch(int)}. Move focus to the next selectable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001020 * item.
1021 */
1022 public static final int FOCUS_FORWARD = 0x00000002;
1023
1024 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001025 * Use with {@link #focusSearch(int)}. Move focus to the left.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001026 */
1027 public static final int FOCUS_LEFT = 0x00000011;
1028
1029 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001030 * Use with {@link #focusSearch(int)}. Move focus up.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001031 */
1032 public static final int FOCUS_UP = 0x00000021;
1033
1034 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001035 * Use with {@link #focusSearch(int)}. Move focus to the right.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001036 */
1037 public static final int FOCUS_RIGHT = 0x00000042;
1038
1039 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07001040 * Use with {@link #focusSearch(int)}. Move focus down.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001041 */
1042 public static final int FOCUS_DOWN = 0x00000082;
1043
Svetoslav Ganov42138042012-03-20 11:51:39 -07001044 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08001045 * Bits of {@link #getMeasuredWidthAndState()} and
1046 * {@link #getMeasuredWidthAndState()} that provide the actual measured size.
1047 */
1048 public static final int MEASURED_SIZE_MASK = 0x00ffffff;
1049
1050 /**
1051 * Bits of {@link #getMeasuredWidthAndState()} and
1052 * {@link #getMeasuredWidthAndState()} that provide the additional state bits.
1053 */
1054 public static final int MEASURED_STATE_MASK = 0xff000000;
1055
1056 /**
1057 * Bit shift of {@link #MEASURED_STATE_MASK} to get to the height bits
1058 * for functions that combine both width and height into a single int,
1059 * such as {@link #getMeasuredState()} and the childState argument of
1060 * {@link #resolveSizeAndState(int, int, int)}.
1061 */
1062 public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;
1063
1064 /**
1065 * Bit of {@link #getMeasuredWidthAndState()} and
1066 * {@link #getMeasuredWidthAndState()} that indicates the measured size
1067 * is smaller that the space the view would like to have.
1068 */
1069 public static final int MEASURED_STATE_TOO_SMALL = 0x01000000;
1070
1071 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001072 * Base View state sets
1073 */
1074 // Singles
1075 /**
1076 * Indicates the view has no states set. States are used with
1077 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1078 * view depending on its state.
1079 *
1080 * @see android.graphics.drawable.Drawable
1081 * @see #getDrawableState()
1082 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001083 protected static final int[] EMPTY_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001084 /**
1085 * Indicates the view is enabled. States are used with
1086 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1087 * view depending on its state.
1088 *
1089 * @see android.graphics.drawable.Drawable
1090 * @see #getDrawableState()
1091 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001092 protected static final int[] ENABLED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001093 /**
1094 * Indicates the view is focused. States are used with
1095 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1096 * view depending on its state.
1097 *
1098 * @see android.graphics.drawable.Drawable
1099 * @see #getDrawableState()
1100 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001101 protected static final int[] FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001102 /**
1103 * Indicates the view is selected. States are used with
1104 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1105 * view depending on its state.
1106 *
1107 * @see android.graphics.drawable.Drawable
1108 * @see #getDrawableState()
1109 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001110 protected static final int[] SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001111 /**
1112 * Indicates the view is pressed. States are used with
1113 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1114 * view depending on its state.
1115 *
1116 * @see android.graphics.drawable.Drawable
1117 * @see #getDrawableState()
1118 * @hide
1119 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001120 protected static final int[] PRESSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001121 /**
1122 * Indicates the view's window has focus. States are used with
1123 * {@link android.graphics.drawable.Drawable} to change the drawing of the
1124 * view depending on its state.
1125 *
1126 * @see android.graphics.drawable.Drawable
1127 * @see #getDrawableState()
1128 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001129 protected static final int[] WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001130 // Doubles
1131 /**
1132 * Indicates the view is enabled and has the focus.
1133 *
1134 * @see #ENABLED_STATE_SET
1135 * @see #FOCUSED_STATE_SET
1136 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001137 protected static final int[] ENABLED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001138 /**
1139 * Indicates the view is enabled and selected.
1140 *
1141 * @see #ENABLED_STATE_SET
1142 * @see #SELECTED_STATE_SET
1143 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001144 protected static final int[] ENABLED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001145 /**
1146 * Indicates the view is enabled and that its window has focus.
1147 *
1148 * @see #ENABLED_STATE_SET
1149 * @see #WINDOW_FOCUSED_STATE_SET
1150 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001151 protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001152 /**
1153 * Indicates the view is focused and selected.
1154 *
1155 * @see #FOCUSED_STATE_SET
1156 * @see #SELECTED_STATE_SET
1157 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001158 protected static final int[] FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001159 /**
1160 * Indicates the view has the focus and that its window has the focus.
1161 *
1162 * @see #FOCUSED_STATE_SET
1163 * @see #WINDOW_FOCUSED_STATE_SET
1164 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001165 protected static final int[] FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001166 /**
1167 * Indicates the view is selected and that its window has the focus.
1168 *
1169 * @see #SELECTED_STATE_SET
1170 * @see #WINDOW_FOCUSED_STATE_SET
1171 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001172 protected static final int[] SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001173 // Triples
1174 /**
1175 * Indicates the view is enabled, focused and selected.
1176 *
1177 * @see #ENABLED_STATE_SET
1178 * @see #FOCUSED_STATE_SET
1179 * @see #SELECTED_STATE_SET
1180 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001181 protected static final int[] ENABLED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001182 /**
1183 * Indicates the view is enabled, focused and its window has the focus.
1184 *
1185 * @see #ENABLED_STATE_SET
1186 * @see #FOCUSED_STATE_SET
1187 * @see #WINDOW_FOCUSED_STATE_SET
1188 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001189 protected static final int[] ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001190 /**
1191 * Indicates the view is enabled, selected and its window has the focus.
1192 *
1193 * @see #ENABLED_STATE_SET
1194 * @see #SELECTED_STATE_SET
1195 * @see #WINDOW_FOCUSED_STATE_SET
1196 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001197 protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001198 /**
1199 * Indicates the view is focused, selected and its window has the focus.
1200 *
1201 * @see #FOCUSED_STATE_SET
1202 * @see #SELECTED_STATE_SET
1203 * @see #WINDOW_FOCUSED_STATE_SET
1204 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001205 protected static final int[] FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001206 /**
1207 * Indicates the view is enabled, focused, selected and its window
1208 * has the focus.
1209 *
1210 * @see #ENABLED_STATE_SET
1211 * @see #FOCUSED_STATE_SET
1212 * @see #SELECTED_STATE_SET
1213 * @see #WINDOW_FOCUSED_STATE_SET
1214 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001215 protected static final int[] ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001216 /**
1217 * Indicates the view is pressed and its window has the focus.
1218 *
1219 * @see #PRESSED_STATE_SET
1220 * @see #WINDOW_FOCUSED_STATE_SET
1221 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001222 protected static final int[] PRESSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001223 /**
1224 * Indicates the view is pressed and selected.
1225 *
1226 * @see #PRESSED_STATE_SET
1227 * @see #SELECTED_STATE_SET
1228 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001229 protected static final int[] PRESSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001230 /**
1231 * Indicates the view is pressed, selected and its window has the focus.
1232 *
1233 * @see #PRESSED_STATE_SET
1234 * @see #SELECTED_STATE_SET
1235 * @see #WINDOW_FOCUSED_STATE_SET
1236 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001237 protected static final int[] PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001238 /**
1239 * Indicates the view is pressed and focused.
1240 *
1241 * @see #PRESSED_STATE_SET
1242 * @see #FOCUSED_STATE_SET
1243 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001244 protected static final int[] PRESSED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001245 /**
1246 * Indicates the view is pressed, focused and its window has the focus.
1247 *
1248 * @see #PRESSED_STATE_SET
1249 * @see #FOCUSED_STATE_SET
1250 * @see #WINDOW_FOCUSED_STATE_SET
1251 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001252 protected static final int[] PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001253 /**
1254 * Indicates the view is pressed, focused and selected.
1255 *
1256 * @see #PRESSED_STATE_SET
1257 * @see #SELECTED_STATE_SET
1258 * @see #FOCUSED_STATE_SET
1259 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001260 protected static final int[] PRESSED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001261 /**
1262 * Indicates the view is pressed, focused, selected and its window has the focus.
1263 *
1264 * @see #PRESSED_STATE_SET
1265 * @see #FOCUSED_STATE_SET
1266 * @see #SELECTED_STATE_SET
1267 * @see #WINDOW_FOCUSED_STATE_SET
1268 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001269 protected static final int[] PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001270 /**
1271 * Indicates the view is pressed and enabled.
1272 *
1273 * @see #PRESSED_STATE_SET
1274 * @see #ENABLED_STATE_SET
1275 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001276 protected static final int[] PRESSED_ENABLED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001277 /**
1278 * Indicates the view is pressed, enabled and its window has the focus.
1279 *
1280 * @see #PRESSED_STATE_SET
1281 * @see #ENABLED_STATE_SET
1282 * @see #WINDOW_FOCUSED_STATE_SET
1283 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001284 protected static final int[] PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001285 /**
1286 * Indicates the view is pressed, enabled and selected.
1287 *
1288 * @see #PRESSED_STATE_SET
1289 * @see #ENABLED_STATE_SET
1290 * @see #SELECTED_STATE_SET
1291 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001292 protected static final int[] PRESSED_ENABLED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001293 /**
1294 * Indicates the view is pressed, enabled, selected and its window has the
1295 * focus.
1296 *
1297 * @see #PRESSED_STATE_SET
1298 * @see #ENABLED_STATE_SET
1299 * @see #SELECTED_STATE_SET
1300 * @see #WINDOW_FOCUSED_STATE_SET
1301 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001302 protected static final int[] PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001303 /**
1304 * Indicates the view is pressed, enabled and focused.
1305 *
1306 * @see #PRESSED_STATE_SET
1307 * @see #ENABLED_STATE_SET
1308 * @see #FOCUSED_STATE_SET
1309 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001310 protected static final int[] PRESSED_ENABLED_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001311 /**
1312 * Indicates the view is pressed, enabled, focused and its window has the
1313 * focus.
1314 *
1315 * @see #PRESSED_STATE_SET
1316 * @see #ENABLED_STATE_SET
1317 * @see #FOCUSED_STATE_SET
1318 * @see #WINDOW_FOCUSED_STATE_SET
1319 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001320 protected static final int[] PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001321 /**
1322 * Indicates the view is pressed, enabled, focused and selected.
1323 *
1324 * @see #PRESSED_STATE_SET
1325 * @see #ENABLED_STATE_SET
1326 * @see #SELECTED_STATE_SET
1327 * @see #FOCUSED_STATE_SET
1328 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001329 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001330 /**
1331 * Indicates the view is pressed, enabled, focused, selected and its window
1332 * has the focus.
1333 *
1334 * @see #PRESSED_STATE_SET
1335 * @see #ENABLED_STATE_SET
1336 * @see #SELECTED_STATE_SET
1337 * @see #FOCUSED_STATE_SET
1338 * @see #WINDOW_FOCUSED_STATE_SET
1339 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001340 protected static final int[] PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001341
1342 /**
1343 * The order here is very important to {@link #getDrawableState()}
1344 */
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001345 private static final int[][] VIEW_STATE_SETS;
1346
Romain Guyb051e892010-09-28 19:09:36 -07001347 static final int VIEW_STATE_WINDOW_FOCUSED = 1;
1348 static final int VIEW_STATE_SELECTED = 1 << 1;
1349 static final int VIEW_STATE_FOCUSED = 1 << 2;
1350 static final int VIEW_STATE_ENABLED = 1 << 3;
1351 static final int VIEW_STATE_PRESSED = 1 << 4;
1352 static final int VIEW_STATE_ACTIVATED = 1 << 5;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001353 static final int VIEW_STATE_ACCELERATED = 1 << 6;
PY Laligandc33d8d49e2011-03-14 18:22:53 -07001354 static final int VIEW_STATE_HOVERED = 1 << 7;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001355 static final int VIEW_STATE_DRAG_CAN_ACCEPT = 1 << 8;
1356 static final int VIEW_STATE_DRAG_HOVERED = 1 << 9;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001357
1358 static final int[] VIEW_STATE_IDS = new int[] {
1359 R.attr.state_window_focused, VIEW_STATE_WINDOW_FOCUSED,
1360 R.attr.state_selected, VIEW_STATE_SELECTED,
1361 R.attr.state_focused, VIEW_STATE_FOCUSED,
1362 R.attr.state_enabled, VIEW_STATE_ENABLED,
1363 R.attr.state_pressed, VIEW_STATE_PRESSED,
1364 R.attr.state_activated, VIEW_STATE_ACTIVATED,
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001365 R.attr.state_accelerated, VIEW_STATE_ACCELERATED,
PY Laligandc33d8d49e2011-03-14 18:22:53 -07001366 R.attr.state_hovered, VIEW_STATE_HOVERED,
Christopher Tate3d4bf172011-03-28 16:16:46 -07001367 R.attr.state_drag_can_accept, VIEW_STATE_DRAG_CAN_ACCEPT,
Svetoslav Ganov42138042012-03-20 11:51:39 -07001368 R.attr.state_drag_hovered, VIEW_STATE_DRAG_HOVERED
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001369 };
1370
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001371 static {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -08001372 if ((VIEW_STATE_IDS.length/2) != R.styleable.ViewDrawableStates.length) {
1373 throw new IllegalStateException(
1374 "VIEW_STATE_IDs array length does not match ViewDrawableStates style array");
1375 }
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001376 int[] orderedIds = new int[VIEW_STATE_IDS.length];
Romain Guyb051e892010-09-28 19:09:36 -07001377 for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001378 int viewState = R.styleable.ViewDrawableStates[i];
Romain Guyb051e892010-09-28 19:09:36 -07001379 for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001380 if (VIEW_STATE_IDS[j] == viewState) {
Romain Guyb051e892010-09-28 19:09:36 -07001381 orderedIds[i * 2] = viewState;
1382 orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001383 }
1384 }
1385 }
Romain Guyb051e892010-09-28 19:09:36 -07001386 final int NUM_BITS = VIEW_STATE_IDS.length / 2;
1387 VIEW_STATE_SETS = new int[1 << NUM_BITS][];
1388 for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001389 int numBits = Integer.bitCount(i);
1390 int[] set = new int[numBits];
1391 int pos = 0;
Romain Guyb051e892010-09-28 19:09:36 -07001392 for (int j = 0; j < orderedIds.length; j += 2) {
1393 if ((i & orderedIds[j+1]) != 0) {
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001394 set[pos++] = orderedIds[j];
1395 }
1396 }
1397 VIEW_STATE_SETS[i] = set;
1398 }
1399
1400 EMPTY_STATE_SET = VIEW_STATE_SETS[0];
1401 WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_WINDOW_FOCUSED];
1402 SELECTED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_SELECTED];
1403 SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1404 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED];
1405 FOCUSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_FOCUSED];
1406 FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1407 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED];
1408 FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1409 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED];
1410 FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1411 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1412 | VIEW_STATE_FOCUSED];
1413 ENABLED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_ENABLED];
1414 ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1415 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED];
1416 ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1417 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED];
1418 ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1419 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1420 | VIEW_STATE_ENABLED];
1421 ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1422 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED];
1423 ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1424 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1425 | VIEW_STATE_ENABLED];
1426 ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1427 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1428 | VIEW_STATE_ENABLED];
1429 ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1430 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1431 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED];
1432
1433 PRESSED_STATE_SET = VIEW_STATE_SETS[VIEW_STATE_PRESSED];
1434 PRESSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1435 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_PRESSED];
1436 PRESSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1437 VIEW_STATE_SELECTED | VIEW_STATE_PRESSED];
1438 PRESSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1439 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1440 | VIEW_STATE_PRESSED];
1441 PRESSED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1442 VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1443 PRESSED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1444 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1445 | VIEW_STATE_PRESSED];
1446 PRESSED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1447 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1448 | VIEW_STATE_PRESSED];
1449 PRESSED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1450 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1451 | VIEW_STATE_FOCUSED | VIEW_STATE_PRESSED];
1452 PRESSED_ENABLED_STATE_SET = VIEW_STATE_SETS[
1453 VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1454 PRESSED_ENABLED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1455 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_ENABLED
1456 | VIEW_STATE_PRESSED];
1457 PRESSED_ENABLED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1458 VIEW_STATE_SELECTED | VIEW_STATE_ENABLED
1459 | VIEW_STATE_PRESSED];
1460 PRESSED_ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1461 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1462 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1463 PRESSED_ENABLED_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1464 VIEW_STATE_FOCUSED | VIEW_STATE_ENABLED
1465 | VIEW_STATE_PRESSED];
1466 PRESSED_ENABLED_FOCUSED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1467 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_FOCUSED
1468 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1469 PRESSED_ENABLED_FOCUSED_SELECTED_STATE_SET = VIEW_STATE_SETS[
1470 VIEW_STATE_SELECTED | VIEW_STATE_FOCUSED
1471 | VIEW_STATE_ENABLED | VIEW_STATE_PRESSED];
1472 PRESSED_ENABLED_FOCUSED_SELECTED_WINDOW_FOCUSED_STATE_SET = VIEW_STATE_SETS[
1473 VIEW_STATE_WINDOW_FOCUSED | VIEW_STATE_SELECTED
1474 | VIEW_STATE_FOCUSED| VIEW_STATE_ENABLED
1475 | VIEW_STATE_PRESSED];
1476 }
1477
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001478 /**
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07001479 * Accessibility event types that are dispatched for text population.
1480 */
1481 private static final int POPULATING_ACCESSIBILITY_EVENT_TYPES =
1482 AccessibilityEvent.TYPE_VIEW_CLICKED
1483 | AccessibilityEvent.TYPE_VIEW_LONG_CLICKED
1484 | AccessibilityEvent.TYPE_VIEW_SELECTED
1485 | AccessibilityEvent.TYPE_VIEW_FOCUSED
1486 | AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED
1487 | AccessibilityEvent.TYPE_VIEW_HOVER_ENTER
Svetoslav Ganov9920f4f2011-10-07 18:39:11 -07001488 | AccessibilityEvent.TYPE_VIEW_HOVER_EXIT
Svetoslav Ganov84dd52e2011-11-18 10:24:00 -08001489 | AccessibilityEvent.TYPE_VIEW_TEXT_CHANGED
Svetoslav Ganov42138042012-03-20 11:51:39 -07001490 | AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001491 | AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED
1492 | AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY;
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07001493
1494 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001495 * Temporary Rect currently for use in setBackground(). This will probably
1496 * be extended in the future to hold our own class with more than just
1497 * a Rect. :)
1498 */
1499 static final ThreadLocal<Rect> sThreadLocal = new ThreadLocal<Rect>();
Romain Guyd90a3312009-05-06 14:54:28 -07001500
1501 /**
1502 * Map used to store views' tags.
1503 */
Adam Powell7db82ac2011-09-22 19:44:04 -07001504 private SparseArray<Object> mKeyedTags;
Romain Guyd90a3312009-05-06 14:54:28 -07001505
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001506 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001507 * The next available accessiiblity id.
1508 */
1509 private static int sNextAccessibilityViewId;
1510
1511 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001512 * The animation currently associated with this view.
1513 * @hide
1514 */
1515 protected Animation mCurrentAnimation = null;
1516
1517 /**
1518 * Width as measured during measure pass.
1519 * {@hide}
1520 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001521 @ViewDebug.ExportedProperty(category = "measurement")
Romain Guy676b1732011-02-14 14:45:33 -08001522 int mMeasuredWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001523
1524 /**
1525 * Height as measured during measure pass.
1526 * {@hide}
1527 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07001528 @ViewDebug.ExportedProperty(category = "measurement")
Romain Guy676b1732011-02-14 14:45:33 -08001529 int mMeasuredHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001530
1531 /**
Chet Haasedaf98e92011-01-10 14:10:36 -08001532 * Flag to indicate that this view was marked INVALIDATED, or had its display list
1533 * invalidated, prior to the current drawing iteration. If true, the view must re-draw
1534 * its display list. This flag, used only when hw accelerated, allows us to clear the
1535 * flag while retaining this information until it's needed (at getDisplayList() time and
1536 * in drawChild(), when we decide to draw a view's children's display lists into our own).
1537 *
1538 * {@hide}
1539 */
1540 boolean mRecreateDisplayList = false;
1541
1542 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001543 * The view's identifier.
1544 * {@hide}
1545 *
1546 * @see #setId(int)
1547 * @see #getId()
1548 */
1549 @ViewDebug.ExportedProperty(resolveId = true)
1550 int mID = NO_ID;
1551
1552 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07001553 * The stable ID of this view for accessibility purposes.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07001554 */
1555 int mAccessibilityViewId = NO_ID;
1556
1557 /**
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001558 * @hide
1559 */
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07001560 private int mAccessibilityCursorPosition = ACCESSIBILITY_CURSOR_POSITION_UNDEFINED;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07001561
1562 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001563 * The view's tag.
1564 * {@hide}
1565 *
1566 * @see #setTag(Object)
1567 * @see #getTag()
1568 */
1569 protected Object mTag;
1570
1571 // for mPrivateFlags:
1572 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001573 static final int PFLAG_WANTS_FOCUS = 0x00000001;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001574 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001575 static final int PFLAG_FOCUSED = 0x00000002;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001576 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001577 static final int PFLAG_SELECTED = 0x00000004;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001578 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001579 static final int PFLAG_IS_ROOT_NAMESPACE = 0x00000008;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001580 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001581 static final int PFLAG_HAS_BOUNDS = 0x00000010;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001582 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001583 static final int PFLAG_DRAWN = 0x00000020;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001584 /**
1585 * When this flag is set, this view is running an animation on behalf of its
1586 * children and should therefore not cancel invalidate requests, even if they
1587 * lie outside of this view's bounds.
1588 *
1589 * {@hide}
1590 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001591 static final int PFLAG_DRAW_ANIMATION = 0x00000040;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001592 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001593 static final int PFLAG_SKIP_DRAW = 0x00000080;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001594 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001595 static final int PFLAG_ONLY_DRAWS_BACKGROUND = 0x00000100;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001596 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001597 static final int PFLAG_REQUEST_TRANSPARENT_REGIONS = 0x00000200;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001598 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001599 static final int PFLAG_DRAWABLE_STATE_DIRTY = 0x00000400;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001600 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001601 static final int PFLAG_MEASURED_DIMENSION_SET = 0x00000800;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001602 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001603 static final int PFLAG_FORCE_LAYOUT = 0x00001000;
Konstantin Lopyrevc6dc4572010-08-06 15:01:52 -07001604 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001605 static final int PFLAG_LAYOUT_REQUIRED = 0x00002000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001606
Dianne Hackborn4702a852012-08-17 15:18:29 -07001607 private static final int PFLAG_PRESSED = 0x00004000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001608
1609 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001610 static final int PFLAG_DRAWING_CACHE_VALID = 0x00008000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001611 /**
1612 * Flag used to indicate that this view should be drawn once more (and only once
1613 * more) after its animation has completed.
1614 * {@hide}
1615 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001616 static final int PFLAG_ANIMATION_STARTED = 0x00010000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001617
Dianne Hackborn4702a852012-08-17 15:18:29 -07001618 private static final int PFLAG_SAVE_STATE_CALLED = 0x00020000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001619
1620 /**
1621 * Indicates that the View returned true when onSetAlpha() was called and that
1622 * the alpha must be restored.
1623 * {@hide}
1624 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001625 static final int PFLAG_ALPHA_SET = 0x00040000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001626
1627 /**
1628 * Set by {@link #setScrollContainer(boolean)}.
1629 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001630 static final int PFLAG_SCROLL_CONTAINER = 0x00080000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001631
1632 /**
1633 * Set by {@link #setScrollContainer(boolean)}.
1634 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001635 static final int PFLAG_SCROLL_CONTAINER_ADDED = 0x00100000;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001636
1637 /**
Romain Guy809a7f62009-05-14 15:44:42 -07001638 * View flag indicating whether this view was invalidated (fully or partially.)
1639 *
1640 * @hide
1641 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001642 static final int PFLAG_DIRTY = 0x00200000;
Romain Guy809a7f62009-05-14 15:44:42 -07001643
1644 /**
1645 * View flag indicating whether this view was invalidated by an opaque
1646 * invalidate request.
1647 *
1648 * @hide
1649 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001650 static final int PFLAG_DIRTY_OPAQUE = 0x00400000;
Romain Guy809a7f62009-05-14 15:44:42 -07001651
1652 /**
Dianne Hackborn4702a852012-08-17 15:18:29 -07001653 * Mask for {@link #PFLAG_DIRTY} and {@link #PFLAG_DIRTY_OPAQUE}.
Romain Guy809a7f62009-05-14 15:44:42 -07001654 *
1655 * @hide
1656 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001657 static final int PFLAG_DIRTY_MASK = 0x00600000;
Romain Guy809a7f62009-05-14 15:44:42 -07001658
1659 /**
Romain Guy8f1344f52009-05-15 16:03:59 -07001660 * Indicates whether the background is opaque.
1661 *
1662 * @hide
1663 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001664 static final int PFLAG_OPAQUE_BACKGROUND = 0x00800000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001665
1666 /**
1667 * Indicates whether the scrollbars are opaque.
1668 *
1669 * @hide
1670 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001671 static final int PFLAG_OPAQUE_SCROLLBARS = 0x01000000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001672
1673 /**
1674 * Indicates whether the view is opaque.
1675 *
1676 * @hide
1677 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001678 static final int PFLAG_OPAQUE_MASK = 0x01800000;
Joe Malin32736f02011-01-19 16:14:20 -08001679
Adam Powelle14579b2009-12-16 18:39:52 -08001680 /**
1681 * Indicates a prepressed state;
1682 * the short time between ACTION_DOWN and recognizing
1683 * a 'real' press. Prepressed is used to recognize quick taps
1684 * even when they are shorter than ViewConfiguration.getTapTimeout().
Joe Malin32736f02011-01-19 16:14:20 -08001685 *
Adam Powelle14579b2009-12-16 18:39:52 -08001686 * @hide
1687 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001688 private static final int PFLAG_PREPRESSED = 0x02000000;
Joe Malin32736f02011-01-19 16:14:20 -08001689
Adam Powellc9fbaab2010-02-16 17:16:19 -08001690 /**
Romain Guy8afa5152010-02-26 11:56:30 -08001691 * Indicates whether the view is temporarily detached.
1692 *
1693 * @hide
1694 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001695 static final int PFLAG_CANCEL_NEXT_UP_EVENT = 0x04000000;
Joe Malin32736f02011-01-19 16:14:20 -08001696
Adam Powell8568c3a2010-04-19 14:26:11 -07001697 /**
1698 * Indicates that we should awaken scroll bars once attached
Joe Malin32736f02011-01-19 16:14:20 -08001699 *
Adam Powell8568c3a2010-04-19 14:26:11 -07001700 * @hide
1701 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001702 private static final int PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH = 0x08000000;
Romain Guy8f1344f52009-05-15 16:03:59 -07001703
1704 /**
Jeff Browna032cc02011-03-07 16:56:21 -08001705 * Indicates that the view has received HOVER_ENTER. Cleared on HOVER_EXIT.
1706 * @hide
1707 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001708 private static final int PFLAG_HOVERED = 0x10000000;
Jeff Browna032cc02011-03-07 16:56:21 -08001709
1710 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07001711 * Indicates that pivotX or pivotY were explicitly set and we should not assume the center
1712 * for transform operations
1713 *
1714 * @hide
1715 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001716 private static final int PFLAG_PIVOT_EXPLICITLY_SET = 0x20000000;
Chet Haasefd2b0022010-08-06 13:08:56 -07001717
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001718 /** {@hide} */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001719 static final int PFLAG_ACTIVATED = 0x40000000;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -07001720
Chet Haasefd2b0022010-08-06 13:08:56 -07001721 /**
Chet Haasedaf98e92011-01-10 14:10:36 -08001722 * Indicates that this view was specifically invalidated, not just dirtied because some
1723 * child view was invalidated. The flag is used to determine when we need to recreate
1724 * a view's display list (as opposed to just returning a reference to its existing
1725 * display list).
1726 *
1727 * @hide
1728 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001729 static final int PFLAG_INVALIDATED = 0x80000000;
Chet Haasedaf98e92011-01-10 14:10:36 -08001730
Christopher Tate3d4bf172011-03-28 16:16:46 -07001731 /* Masks for mPrivateFlags2 */
1732
1733 /**
1734 * Indicates that this view has reported that it can accept the current drag's content.
1735 * Cleared when the drag operation concludes.
1736 * @hide
1737 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001738 static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001739
1740 /**
1741 * Indicates that this view is currently directly under the drag location in a
1742 * drag-and-drop operation involving content that it can accept. Cleared when
1743 * the drag exits the view, or when the drag operation concludes.
1744 * @hide
1745 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001746 static final int PFLAG2_DRAG_HOVERED = 0x00000002;
Christopher Tate3d4bf172011-03-28 16:16:46 -07001747
Cibu Johny86666632010-02-22 13:01:02 -08001748 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001749 * Horizontal layout direction of this view is from Left to Right.
1750 * Use with {@link #setLayoutDirection}.
Cibu Johny86666632010-02-22 13:01:02 -08001751 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001752 public static final int LAYOUT_DIRECTION_LTR = 0;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001753
1754 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001755 * Horizontal layout direction of this view is from Right to Left.
1756 * Use with {@link #setLayoutDirection}.
1757 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001758 public static final int LAYOUT_DIRECTION_RTL = 1;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001759
1760 /**
1761 * Horizontal layout direction of this view is inherited from its parent.
1762 * Use with {@link #setLayoutDirection}.
1763 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001764 public static final int LAYOUT_DIRECTION_INHERIT = 2;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001765
1766 /**
1767 * Horizontal layout direction of this view is from deduced from the default language
1768 * script for the locale. Use with {@link #setLayoutDirection}.
1769 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001770 public static final int LAYOUT_DIRECTION_LOCALE = 3;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001771
1772 /**
1773 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001774 * @hide
1775 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001776 static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001777
1778 /**
1779 * Mask for use with private flags indicating bits used for horizontal layout direction.
1780 * @hide
1781 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001782 static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001783
1784 /**
1785 * Indicates whether the view horizontal layout direction has been resolved and drawn to the
1786 * right-to-left direction.
1787 * @hide
1788 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001789 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001790
1791 /**
1792 * Indicates whether the view horizontal layout direction has been resolved.
1793 * @hide
1794 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001795 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001796
1797 /**
1798 * Mask for use with private flags indicating bits used for resolved horizontal layout direction.
1799 * @hide
1800 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001801 static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C
1802 << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001803
1804 /*
1805 * Array of horizontal layout direction flags for mapping attribute "layoutDirection" to correct
1806 * flag value.
1807 * @hide
1808 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001809 private static final int[] LAYOUT_DIRECTION_FLAGS = {
1810 LAYOUT_DIRECTION_LTR,
1811 LAYOUT_DIRECTION_RTL,
1812 LAYOUT_DIRECTION_INHERIT,
1813 LAYOUT_DIRECTION_LOCALE
1814 };
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07001815
1816 /**
1817 * Default horizontal layout direction.
1818 * @hide
1819 */
1820 private static final int LAYOUT_DIRECTION_DEFAULT = LAYOUT_DIRECTION_INHERIT;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07001821
Adam Powell539ee872012-02-03 19:00:49 -08001822 /**
1823 * Indicates that the view is tracking some sort of transient state
1824 * that the app should not need to be aware of, but that the framework
1825 * should take special care to preserve.
1826 *
1827 * @hide
1828 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001829 static final int PFLAG2_HAS_TRANSIENT_STATE = 0x00000100;
Adam Powell539ee872012-02-03 19:00:49 -08001830
1831
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001832 /**
1833 * Text direction is inherited thru {@link ViewGroup}
1834 */
1835 public static final int TEXT_DIRECTION_INHERIT = 0;
1836
1837 /**
1838 * Text direction is using "first strong algorithm". The first strong directional character
1839 * determines the paragraph direction. If there is no strong directional character, the
1840 * paragraph direction is the view's resolved layout direction.
1841 */
1842 public static final int TEXT_DIRECTION_FIRST_STRONG = 1;
1843
1844 /**
1845 * Text direction is using "any-RTL" algorithm. The paragraph direction is RTL if it contains
1846 * any strong RTL character, otherwise it is LTR if it contains any strong LTR characters.
1847 * If there are neither, the paragraph direction is the view's resolved layout direction.
1848 */
1849 public static final int TEXT_DIRECTION_ANY_RTL = 2;
1850
1851 /**
1852 * Text direction is forced to LTR.
1853 */
1854 public static final int TEXT_DIRECTION_LTR = 3;
1855
1856 /**
1857 * Text direction is forced to RTL.
1858 */
1859 public static final int TEXT_DIRECTION_RTL = 4;
1860
1861 /**
1862 * Text direction is coming from the system Locale.
1863 */
1864 public static final int TEXT_DIRECTION_LOCALE = 5;
1865
1866 /**
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001867 * Default text direction is inherited
1868 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001869 public static int TEXT_DIRECTION_DEFAULT = TEXT_DIRECTION_INHERIT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001870
1871 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001872 * Bit shift to get the horizontal layout direction. (bits after LAYOUT_DIRECTION_RESOLVED)
1873 * @hide
1874 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001875 static final int PFLAG2_TEXT_DIRECTION_MASK_SHIFT = 6;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001876
1877 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001878 * Mask for use with private flags indicating bits used for text direction.
1879 * @hide
1880 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001881 static final int PFLAG2_TEXT_DIRECTION_MASK = 0x00000007
1882 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001883
1884 /**
1885 * Array of text direction flags for mapping attribute "textDirection" to correct
1886 * flag value.
1887 * @hide
1888 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001889 private static final int[] PFLAG2_TEXT_DIRECTION_FLAGS = {
1890 TEXT_DIRECTION_INHERIT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1891 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1892 TEXT_DIRECTION_ANY_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1893 TEXT_DIRECTION_LTR << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1894 TEXT_DIRECTION_RTL << PFLAG2_TEXT_DIRECTION_MASK_SHIFT,
1895 TEXT_DIRECTION_LOCALE << PFLAG2_TEXT_DIRECTION_MASK_SHIFT
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001896 };
1897
1898 /**
1899 * Indicates whether the view text direction has been resolved.
1900 * @hide
1901 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001902 static final int PFLAG2_TEXT_DIRECTION_RESOLVED = 0x00000008
1903 << PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001904
1905 /**
1906 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1907 * @hide
1908 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001909 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT = 10;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001910
1911 /**
1912 * Mask for use with private flags indicating bits used for resolved text direction.
1913 * @hide
1914 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001915 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_MASK = 0x00000007
1916 << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001917
1918 /**
1919 * Indicates whether the view text direction has been resolved to the "first strong" heuristic.
1920 * @hide
1921 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001922 static final int PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT =
1923 TEXT_DIRECTION_FIRST_STRONG << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07001924
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001925 /*
1926 * Default text alignment. The text alignment of this View is inherited from its parent.
1927 * Use with {@link #setTextAlignment(int)}
1928 */
1929 public static final int TEXT_ALIGNMENT_INHERIT = 0;
1930
1931 /**
1932 * Default for the root view. The gravity determines the text alignment, ALIGN_NORMAL,
1933 * ALIGN_CENTER, or ALIGN_OPPOSITE, which are relative to each paragraph’s text direction.
1934 *
1935 * Use with {@link #setTextAlignment(int)}
1936 */
1937 public static final int TEXT_ALIGNMENT_GRAVITY = 1;
1938
1939 /**
1940 * Align to the start of the paragraph, e.g. ALIGN_NORMAL.
1941 *
1942 * Use with {@link #setTextAlignment(int)}
1943 */
1944 public static final int TEXT_ALIGNMENT_TEXT_START = 2;
1945
1946 /**
1947 * Align to the end of the paragraph, e.g. ALIGN_OPPOSITE.
1948 *
1949 * Use with {@link #setTextAlignment(int)}
1950 */
1951 public static final int TEXT_ALIGNMENT_TEXT_END = 3;
1952
1953 /**
1954 * Center the paragraph, e.g. ALIGN_CENTER.
1955 *
1956 * Use with {@link #setTextAlignment(int)}
1957 */
1958 public static final int TEXT_ALIGNMENT_CENTER = 4;
1959
1960 /**
1961 * Align to the start of the view, which is ALIGN_LEFT if the view’s resolved
1962 * layoutDirection is LTR, and ALIGN_RIGHT otherwise.
1963 *
1964 * Use with {@link #setTextAlignment(int)}
1965 */
1966 public static final int TEXT_ALIGNMENT_VIEW_START = 5;
1967
1968 /**
1969 * Align to the end of the view, which is ALIGN_RIGHT if the view’s resolved
1970 * layoutDirection is LTR, and ALIGN_LEFT otherwise.
1971 *
1972 * Use with {@link #setTextAlignment(int)}
1973 */
1974 public static final int TEXT_ALIGNMENT_VIEW_END = 6;
1975
1976 /**
1977 * Default text alignment is inherited
1978 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001979 public static int TEXT_ALIGNMENT_DEFAULT = TEXT_ALIGNMENT_GRAVITY;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001980
1981 /**
1982 * Bit shift to get the horizontal layout direction. (bits after DRAG_HOVERED)
1983 * @hide
1984 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001985 static final int PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT = 13;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001986
1987 /**
1988 * Mask for use with private flags indicating bits used for text alignment.
1989 * @hide
1990 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001991 static final int PFLAG2_TEXT_ALIGNMENT_MASK = 0x00000007 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07001992
1993 /**
1994 * Array of text direction flags for mapping attribute "textAlignment" to correct
1995 * flag value.
1996 * @hide
1997 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07001998 private static final int[] PFLAG2_TEXT_ALIGNMENT_FLAGS = {
1999 TEXT_ALIGNMENT_INHERIT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2000 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2001 TEXT_ALIGNMENT_TEXT_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2002 TEXT_ALIGNMENT_TEXT_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2003 TEXT_ALIGNMENT_CENTER << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2004 TEXT_ALIGNMENT_VIEW_START << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT,
2005 TEXT_ALIGNMENT_VIEW_END << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002006 };
2007
2008 /**
2009 * Indicates whether the view text alignment has been resolved.
2010 * @hide
2011 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002012 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED = 0x00000008 << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002013
2014 /**
2015 * Bit shift to get the resolved text alignment.
2016 * @hide
2017 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002018 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT = 17;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002019
2020 /**
2021 * Mask for use with private flags indicating bits used for text alignment.
2022 * @hide
2023 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002024 static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK = 0x00000007
2025 << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002026
2027 /**
2028 * Indicates whether if the view text alignment has been resolved to gravity
2029 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002030 private static final int PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT =
2031 TEXT_ALIGNMENT_GRAVITY << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07002032
Svetoslav Ganov42138042012-03-20 11:51:39 -07002033 // Accessiblity constants for mPrivateFlags2
2034
2035 /**
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07002036 * Shift for the bits in {@link #mPrivateFlags2} related to the
2037 * "importantForAccessibility" attribute.
Svetoslav Ganov42138042012-03-20 11:51:39 -07002038 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002039 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT = 20;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002040
2041 /**
2042 * Automatically determine whether a view is important for accessibility.
2043 */
2044 public static final int IMPORTANT_FOR_ACCESSIBILITY_AUTO = 0x00000000;
2045
2046 /**
2047 * The view is important for accessibility.
2048 */
2049 public static final int IMPORTANT_FOR_ACCESSIBILITY_YES = 0x00000001;
2050
2051 /**
2052 * The view is not important for accessibility.
2053 */
2054 public static final int IMPORTANT_FOR_ACCESSIBILITY_NO = 0x00000002;
2055
2056 /**
2057 * The default whether the view is important for accessiblity.
2058 */
2059 static final int IMPORTANT_FOR_ACCESSIBILITY_DEFAULT = IMPORTANT_FOR_ACCESSIBILITY_AUTO;
2060
2061 /**
2062 * Mask for obtainig the bits which specify how to determine
2063 * whether a view is important for accessibility.
2064 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002065 static final int PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK = (IMPORTANT_FOR_ACCESSIBILITY_AUTO
Svetoslav Ganov42138042012-03-20 11:51:39 -07002066 | IMPORTANT_FOR_ACCESSIBILITY_YES | IMPORTANT_FOR_ACCESSIBILITY_NO)
Dianne Hackborn4702a852012-08-17 15:18:29 -07002067 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002068
2069 /**
2070 * Flag indicating whether a view has accessibility focus.
2071 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002072 static final int PFLAG2_ACCESSIBILITY_FOCUSED = 0x00000040 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07002073
2074 /**
2075 * Flag indicating whether a view state for accessibility has changed.
2076 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002077 static final int PFLAG2_ACCESSIBILITY_STATE_CHANGED = 0x00000080
2078 << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07002079
Chet Haaseafd5c3e2012-05-10 13:21:10 -07002080 /**
Chet Haase1a3ab172012-05-11 08:41:20 -07002081 * Flag indicating whether a view failed the quickReject() check in draw(). This condition
2082 * is used to check whether later changes to the view's transform should invalidate the
2083 * view to force the quickReject test to run again.
2084 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002085 static final int PFLAG2_VIEW_QUICK_REJECTED = 0x10000000;
Chet Haase1a3ab172012-05-11 08:41:20 -07002086
Adam Powell0090f202012-08-07 17:15:30 -07002087 /**
2088 * Flag indicating that start/end padding has been resolved into left/right padding
2089 * for use in measurement, layout, drawing, etc. This is set by {@link #resolvePadding()}
2090 * and checked by {@link #measure(int, int)} to determine if padding needs to be resolved
2091 * during measurement. In some special cases this is required such as when an adapter-based
2092 * view measures prospective children without attaching them to a window.
2093 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002094 static final int PFLAG2_PADDING_RESOLVED = 0x20000000;
Adam Powell0090f202012-08-07 17:15:30 -07002095
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07002096 // There are a couple of flags left in mPrivateFlags2
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07002097
Christopher Tate3d4bf172011-03-28 16:16:46 -07002098 /* End of masks for mPrivateFlags2 */
2099
Chet Haase21433372012-06-05 07:54:09 -07002100 /* Masks for mPrivateFlags3 */
2101
2102 /**
2103 * Flag indicating that view has a transform animation set on it. This is used to track whether
2104 * an animation is cleared between successive frames, in order to tell the associated
2105 * DisplayList to clear its animation matrix.
2106 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002107 static final int PFLAG3_VIEW_IS_ANIMATING_TRANSFORM = 0x1;
Chet Haase21433372012-06-05 07:54:09 -07002108
2109 /**
2110 * Flag indicating that view has an alpha animation set on it. This is used to track whether an
2111 * animation is cleared between successive frames, in order to tell the associated
2112 * DisplayList to restore its alpha value.
2113 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07002114 static final int PFLAG3_VIEW_IS_ANIMATING_ALPHA = 0x2;
Chet Haase21433372012-06-05 07:54:09 -07002115
2116
2117 /* End of masks for mPrivateFlags3 */
2118
Dianne Hackborn4702a852012-08-17 15:18:29 -07002119 static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
Christopher Tate3d4bf172011-03-28 16:16:46 -07002120
Chet Haasedaf98e92011-01-10 14:10:36 -08002121 /**
Adam Powell637d3372010-08-25 14:37:03 -07002122 * Always allow a user to over-scroll this view, provided it is a
2123 * view that can scroll.
2124 *
2125 * @see #getOverScrollMode()
2126 * @see #setOverScrollMode(int)
2127 */
2128 public static final int OVER_SCROLL_ALWAYS = 0;
2129
2130 /**
2131 * Allow a user to over-scroll this view only if the content is large
2132 * enough to meaningfully scroll, provided it is a view that can scroll.
2133 *
2134 * @see #getOverScrollMode()
2135 * @see #setOverScrollMode(int)
2136 */
2137 public static final int OVER_SCROLL_IF_CONTENT_SCROLLS = 1;
2138
2139 /**
2140 * Never allow a user to over-scroll this view.
2141 *
2142 * @see #getOverScrollMode()
2143 * @see #setOverScrollMode(int)
2144 */
2145 public static final int OVER_SCROLL_NEVER = 2;
2146
2147 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002148 * Special constant for {@link #setSystemUiVisibility(int)}: View has
2149 * requested the system UI (status bar) to be visible (the default).
Joe Onorato664644d2011-01-23 17:53:23 -08002150 *
Joe Malin32736f02011-01-19 16:14:20 -08002151 * @see #setSystemUiVisibility(int)
Joe Onorato664644d2011-01-23 17:53:23 -08002152 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002153 public static final int SYSTEM_UI_FLAG_VISIBLE = 0;
Joe Onorato664644d2011-01-23 17:53:23 -08002154
2155 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002156 * Flag for {@link #setSystemUiVisibility(int)}: View has requested the
2157 * system UI to enter an unobtrusive "low profile" mode.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002158 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002159 * <p>This is for use in games, book readers, video players, or any other
Philip Milne6c8ea062012-04-03 17:38:43 -07002160 * "immersive" application where the usual system chrome is deemed too distracting.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002161 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002162 * <p>In low profile mode, the status bar and/or navigation icons may dim.
Joe Onorato664644d2011-01-23 17:53:23 -08002163 *
Joe Malin32736f02011-01-19 16:14:20 -08002164 * @see #setSystemUiVisibility(int)
Joe Onorato664644d2011-01-23 17:53:23 -08002165 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002166 public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 0x00000001;
2167
2168 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002169 * Flag for {@link #setSystemUiVisibility(int)}: View has requested that the
2170 * system navigation be temporarily hidden.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002171 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002172 * <p>This is an even less obtrusive state than that called for by
Daniel Sandler60ee2562011-07-22 12:34:33 -04002173 * {@link #SYSTEM_UI_FLAG_LOW_PROFILE}; on devices that draw essential navigation controls
2174 * (Home, Back, and the like) on screen, <code>SYSTEM_UI_FLAG_HIDE_NAVIGATION</code> will cause
2175 * those to disappear. This is useful (in conjunction with the
Philip Milne6c8ea062012-04-03 17:38:43 -07002176 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN FLAG_FULLSCREEN} and
Daniel Sandler60ee2562011-07-22 12:34:33 -04002177 * {@link android.view.WindowManager.LayoutParams#FLAG_LAYOUT_IN_SCREEN FLAG_LAYOUT_IN_SCREEN}
2178 * window flags) for displaying content using every last pixel on the display.
2179 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002180 * <p>There is a limitation: because navigation controls are so important, the least user
2181 * interaction will cause them to reappear immediately. When this happens, both
2182 * this flag and {@link #SYSTEM_UI_FLAG_FULLSCREEN} will be cleared automatically,
2183 * so that both elements reappear at the same time.
Daniel Sandler60ee2562011-07-22 12:34:33 -04002184 *
2185 * @see #setSystemUiVisibility(int)
2186 */
2187 public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 0x00000002;
2188
2189 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002190 * Flag for {@link #setSystemUiVisibility(int)}: View has requested to go
2191 * into the normal fullscreen mode so that its content can take over the screen
2192 * while still allowing the user to interact with the application.
2193 *
2194 * <p>This has the same visual effect as
2195 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN
2196 * WindowManager.LayoutParams.FLAG_FULLSCREEN},
2197 * meaning that non-critical screen decorations (such as the status bar) will be
2198 * hidden while the user is in the View's window, focusing the experience on
2199 * that content. Unlike the window flag, if you are using ActionBar in
2200 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2201 * Window.FEATURE_ACTION_BAR_OVERLAY}, then enabling this flag will also
2202 * hide the action bar.
2203 *
2204 * <p>This approach to going fullscreen is best used over the window flag when
2205 * it is a transient state -- that is, the application does this at certain
2206 * points in its user interaction where it wants to allow the user to focus
2207 * on content, but not as a continuous state. For situations where the application
2208 * would like to simply stay full screen the entire time (such as a game that
2209 * wants to take over the screen), the
2210 * {@link android.view.WindowManager.LayoutParams#FLAG_FULLSCREEN window flag}
2211 * is usually a better approach. The state set here will be removed by the system
2212 * in various situations (such as the user moving to another application) like
2213 * the other system UI states.
2214 *
2215 * <p>When using this flag, the application should provide some easy facility
2216 * for the user to go out of it. A common example would be in an e-book
2217 * reader, where tapping on the screen brings back whatever screen and UI
2218 * decorations that had been hidden while the user was immersed in reading
2219 * the book.
2220 *
2221 * @see #setSystemUiVisibility(int)
2222 */
2223 public static final int SYSTEM_UI_FLAG_FULLSCREEN = 0x00000004;
2224
2225 /**
2226 * Flag for {@link #setSystemUiVisibility(int)}: When using other layout
2227 * flags, we would like a stable view of the content insets given to
2228 * {@link #fitSystemWindows(Rect)}. This means that the insets seen there
2229 * will always represent the worst case that the application can expect
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002230 * as a continuous state. In the stock Android UI this is the space for
2231 * the system bar, nav bar, and status bar, but not more transient elements
2232 * such as an input method.
2233 *
2234 * The stable layout your UI sees is based on the system UI modes you can
2235 * switch to. That is, if you specify {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
2236 * then you will get a stable layout for changes of the
2237 * {@link #SYSTEM_UI_FLAG_FULLSCREEN} mode; if you specify
2238 * {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} and
2239 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}, then you can transition
2240 * to {@link #SYSTEM_UI_FLAG_FULLSCREEN} and {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}
2241 * with a stable layout. (Note that you should avoid using
2242 * {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} by itself.)
2243 *
Jeff Smitha45746e2012-07-19 14:19:24 -05002244 * If you have set the window flag {@link WindowManager.LayoutParams#FLAG_FULLSCREEN}
Dianne Hackborn5b5cc4d2012-05-16 13:15:00 -07002245 * to hide the status bar (instead of using {@link #SYSTEM_UI_FLAG_FULLSCREEN}),
2246 * then a hidden status bar will be considered a "stable" state for purposes
2247 * here. This allows your UI to continually hide the status bar, while still
2248 * using the system UI flags to hide the action bar while still retaining
2249 * a stable layout. Note that changing the window fullscreen flag will never
2250 * provide a stable layout for a clean transition.
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002251 *
2252 * <p>If you are using ActionBar in
2253 * overlay mode with {@link Window#FEATURE_ACTION_BAR_OVERLAY
2254 * Window.FEATURE_ACTION_BAR_OVERLAY}, this flag will also impact the
2255 * insets it adds to those given to the application.
2256 */
2257 public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 0x00000100;
2258
2259 /**
2260 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2261 * to be layed out as if it has requested
2262 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, even if it currently hasn't. This
2263 * allows it to avoid artifacts when switching in and out of that mode, at
2264 * the expense that some of its user interface may be covered by screen
2265 * decorations when they are shown. You can perform layout of your inner
2266 * UI elements to account for the navagation system UI through the
2267 * {@link #fitSystemWindows(Rect)} method.
2268 */
2269 public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 0x00000200;
2270
2271 /**
2272 * Flag for {@link #setSystemUiVisibility(int)}: View would like its window
2273 * to be layed out as if it has requested
2274 * {@link #SYSTEM_UI_FLAG_FULLSCREEN}, even if it currently hasn't. This
2275 * allows it to avoid artifacts when switching in and out of that mode, at
2276 * the expense that some of its user interface may be covered by screen
2277 * decorations when they are shown. You can perform layout of your inner
2278 * UI elements to account for non-fullscreen system UI through the
2279 * {@link #fitSystemWindows(Rect)} method.
2280 */
2281 public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 0x00000400;
2282
2283 /**
Daniel Sandler60ee2562011-07-22 12:34:33 -04002284 * @deprecated Use {@link #SYSTEM_UI_FLAG_LOW_PROFILE} instead.
2285 */
2286 public static final int STATUS_BAR_HIDDEN = SYSTEM_UI_FLAG_LOW_PROFILE;
2287
2288 /**
2289 * @deprecated Use {@link #SYSTEM_UI_FLAG_VISIBLE} instead.
2290 */
2291 public static final int STATUS_BAR_VISIBLE = SYSTEM_UI_FLAG_VISIBLE;
Joe Onorato664644d2011-01-23 17:53:23 -08002292
2293 /**
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002294 * @hide
2295 *
2296 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2297 * out of the public fields to keep the undefined bits out of the developer's way.
2298 *
2299 * Flag to make the status bar not expandable. Unless you also
2300 * set {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS}, new notifications will continue to show.
2301 */
2302 public static final int STATUS_BAR_DISABLE_EXPAND = 0x00010000;
2303
2304 /**
2305 * @hide
2306 *
2307 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2308 * out of the public fields to keep the undefined bits out of the developer's way.
2309 *
2310 * Flag to hide notification icons and scrolling ticker text.
2311 */
2312 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ICONS = 0x00020000;
2313
2314 /**
2315 * @hide
2316 *
2317 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2318 * out of the public fields to keep the undefined bits out of the developer's way.
2319 *
2320 * Flag to disable incoming notification alerts. This will not block
2321 * icons, but it will block sound, vibrating and other visual or aural notifications.
2322 */
2323 public static final int STATUS_BAR_DISABLE_NOTIFICATION_ALERTS = 0x00040000;
2324
2325 /**
2326 * @hide
2327 *
2328 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2329 * out of the public fields to keep the undefined bits out of the developer's way.
2330 *
2331 * Flag to hide only the scrolling ticker. Note that
2332 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_ICONS} implies
2333 * {@link #STATUS_BAR_DISABLE_NOTIFICATION_TICKER}.
2334 */
2335 public static final int STATUS_BAR_DISABLE_NOTIFICATION_TICKER = 0x00080000;
2336
2337 /**
2338 * @hide
2339 *
2340 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2341 * out of the public fields to keep the undefined bits out of the developer's way.
2342 *
2343 * Flag to hide the center system info area.
2344 */
2345 public static final int STATUS_BAR_DISABLE_SYSTEM_INFO = 0x00100000;
2346
2347 /**
2348 * @hide
2349 *
2350 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2351 * out of the public fields to keep the undefined bits out of the developer's way.
2352 *
Daniel Sandlerdba93562011-10-06 16:39:58 -04002353 * Flag to hide only the home button. Don't use this
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002354 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2355 */
Daniel Sandlerdba93562011-10-06 16:39:58 -04002356 public static final int STATUS_BAR_DISABLE_HOME = 0x00200000;
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002357
2358 /**
2359 * @hide
2360 *
2361 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2362 * out of the public fields to keep the undefined bits out of the developer's way.
2363 *
Daniel Sandlerdba93562011-10-06 16:39:58 -04002364 * Flag to hide only the back button. Don't use this
Joe Onorato6478adc2011-01-27 21:15:01 -08002365 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2366 */
2367 public static final int STATUS_BAR_DISABLE_BACK = 0x00400000;
2368
2369 /**
2370 * @hide
2371 *
2372 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2373 * out of the public fields to keep the undefined bits out of the developer's way.
2374 *
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002375 * Flag to hide only the clock. You might use this if your activity has
2376 * its own clock making the status bar's clock redundant.
2377 */
Joe Onorato6478adc2011-01-27 21:15:01 -08002378 public static final int STATUS_BAR_DISABLE_CLOCK = 0x00800000;
2379
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002380 /**
2381 * @hide
Daniel Sandlerdba93562011-10-06 16:39:58 -04002382 *
2383 * NOTE: This flag may only be used in subtreeSystemUiVisibility. It is masked
2384 * out of the public fields to keep the undefined bits out of the developer's way.
2385 *
2386 * Flag to hide only the recent apps button. Don't use this
2387 * unless you're a special part of the system UI (i.e., setup wizard, keyguard).
2388 */
2389 public static final int STATUS_BAR_DISABLE_RECENT = 0x01000000;
2390
2391 /**
2392 * @hide
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002393 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002394 public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
Joe Onorato7bb8eeb2011-01-27 16:00:58 -08002395
2396 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -07002397 * These are the system UI flags that can be cleared by events outside
2398 * of an application. Currently this is just the ability to tap on the
2399 * screen while hiding the navigation bar to have it return.
2400 * @hide
2401 */
2402 public static final int SYSTEM_UI_CLEARABLE_FLAGS =
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07002403 SYSTEM_UI_FLAG_LOW_PROFILE | SYSTEM_UI_FLAG_HIDE_NAVIGATION
2404 | SYSTEM_UI_FLAG_FULLSCREEN;
2405
2406 /**
2407 * Flags that can impact the layout in relation to system UI.
2408 */
2409 public static final int SYSTEM_UI_LAYOUT_FLAGS =
2410 SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
2411 | SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
Dianne Hackborn9a230e02011-10-06 11:51:27 -07002412
2413 /**
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07002414 * Find views that render the specified text.
2415 *
2416 * @see #findViewsWithText(ArrayList, CharSequence, int)
2417 */
2418 public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
2419
2420 /**
2421 * Find find views that contain the specified content description.
2422 *
2423 * @see #findViewsWithText(ArrayList, CharSequence, int)
2424 */
2425 public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
2426
2427 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07002428 * Find views that contain {@link AccessibilityNodeProvider}. Such
2429 * a View is a root of virtual view hierarchy and may contain the searched
2430 * text. If this flag is set Views with providers are automatically
2431 * added and it is a responsibility of the client to call the APIs of
2432 * the provider to determine whether the virtual tree rooted at this View
2433 * contains the text, i.e. getting the list of {@link AccessibilityNodeInfo}s
2434 * represeting the virtual views with this text.
2435 *
2436 * @see #findViewsWithText(ArrayList, CharSequence, int)
2437 *
2438 * @hide
2439 */
2440 public static final int FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS = 0x00000004;
2441
2442 /**
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07002443 * The undefined cursor position.
2444 */
2445 private static final int ACCESSIBILITY_CURSOR_POSITION_UNDEFINED = -1;
2446
2447 /**
Romain Guybb9908b2012-03-08 11:14:07 -08002448 * Indicates that the screen has changed state and is now off.
2449 *
2450 * @see #onScreenStateChanged(int)
2451 */
2452 public static final int SCREEN_STATE_OFF = 0x0;
2453
2454 /**
2455 * Indicates that the screen has changed state and is now on.
2456 *
Romain Guy1e3d3132012-03-08 15:55:56 -08002457 * @see #onScreenStateChanged(int)
Romain Guybb9908b2012-03-08 11:14:07 -08002458 */
2459 public static final int SCREEN_STATE_ON = 0x1;
2460
2461 /**
Adam Powell637d3372010-08-25 14:37:03 -07002462 * Controls the over-scroll mode for this view.
2463 * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
2464 * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
2465 * and {@link #OVER_SCROLL_NEVER}.
2466 */
2467 private int mOverScrollMode;
2468
2469 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002470 * The parent this view is attached to.
2471 * {@hide}
2472 *
2473 * @see #getParent()
2474 */
2475 protected ViewParent mParent;
2476
2477 /**
2478 * {@hide}
2479 */
2480 AttachInfo mAttachInfo;
2481
2482 /**
2483 * {@hide}
2484 */
Romain Guy809a7f62009-05-14 15:44:42 -07002485 @ViewDebug.ExportedProperty(flagMapping = {
Dianne Hackborn4702a852012-08-17 15:18:29 -07002486 @ViewDebug.FlagToString(mask = PFLAG_FORCE_LAYOUT, equals = PFLAG_FORCE_LAYOUT,
Romain Guy809a7f62009-05-14 15:44:42 -07002487 name = "FORCE_LAYOUT"),
Dianne Hackborn4702a852012-08-17 15:18:29 -07002488 @ViewDebug.FlagToString(mask = PFLAG_LAYOUT_REQUIRED, equals = PFLAG_LAYOUT_REQUIRED,
Romain Guy809a7f62009-05-14 15:44:42 -07002489 name = "LAYOUT_REQUIRED"),
Dianne Hackborn4702a852012-08-17 15:18:29 -07002490 @ViewDebug.FlagToString(mask = PFLAG_DRAWING_CACHE_VALID, equals = PFLAG_DRAWING_CACHE_VALID,
Romain Guy5bcdff42009-05-14 21:27:18 -07002491 name = "DRAWING_CACHE_INVALID", outputIf = false),
Dianne Hackborn4702a852012-08-17 15:18:29 -07002492 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "DRAWN", outputIf = true),
2493 @ViewDebug.FlagToString(mask = PFLAG_DRAWN, equals = PFLAG_DRAWN, name = "NOT_DRAWN", outputIf = false),
2494 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY_OPAQUE, name = "DIRTY_OPAQUE"),
2495 @ViewDebug.FlagToString(mask = PFLAG_DIRTY_MASK, equals = PFLAG_DIRTY, name = "DIRTY")
Romain Guy809a7f62009-05-14 15:44:42 -07002496 })
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002497 int mPrivateFlags;
Christopher Tate3d4bf172011-03-28 16:16:46 -07002498 int mPrivateFlags2;
Chet Haase21433372012-06-05 07:54:09 -07002499 int mPrivateFlags3;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002500
2501 /**
Joe Onorato664644d2011-01-23 17:53:23 -08002502 * This view's request for the visibility of the status bar.
2503 * @hide
2504 */
Daniel Sandler60ee2562011-07-22 12:34:33 -04002505 @ViewDebug.ExportedProperty(flagMapping = {
2506 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_LOW_PROFILE,
2507 equals = SYSTEM_UI_FLAG_LOW_PROFILE,
2508 name = "SYSTEM_UI_FLAG_LOW_PROFILE", outputIf = true),
2509 @ViewDebug.FlagToString(mask = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2510 equals = SYSTEM_UI_FLAG_HIDE_NAVIGATION,
2511 name = "SYSTEM_UI_FLAG_HIDE_NAVIGATION", outputIf = true),
2512 @ViewDebug.FlagToString(mask = PUBLIC_STATUS_BAR_VISIBILITY_MASK,
2513 equals = SYSTEM_UI_FLAG_VISIBLE,
2514 name = "SYSTEM_UI_FLAG_VISIBLE", outputIf = true)
2515 })
Joe Onorato664644d2011-01-23 17:53:23 -08002516 int mSystemUiVisibility;
2517
2518 /**
Chet Haase563d4f22012-04-18 16:20:08 -07002519 * Reference count for transient state.
2520 * @see #setHasTransientState(boolean)
2521 */
2522 int mTransientStateCount = 0;
2523
2524 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002525 * Count of how many windows this view has been attached to.
2526 */
2527 int mWindowAttachCount;
2528
2529 /**
2530 * The layout parameters associated with this view and used by the parent
2531 * {@link android.view.ViewGroup} to determine how this view should be
2532 * laid out.
2533 * {@hide}
2534 */
2535 protected ViewGroup.LayoutParams mLayoutParams;
2536
2537 /**
2538 * The view flags hold various views states.
2539 * {@hide}
2540 */
2541 @ViewDebug.ExportedProperty
2542 int mViewFlags;
2543
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002544 static class TransformationInfo {
2545 /**
2546 * The transform matrix for the View. This transform is calculated internally
2547 * based on the rotation, scaleX, and scaleY properties. The identity matrix
2548 * is used by default. Do *not* use this variable directly; instead call
2549 * getMatrix(), which will automatically recalculate the matrix if necessary
2550 * to get the correct matrix based on the latest rotation and scale properties.
2551 */
2552 private final Matrix mMatrix = new Matrix();
Chet Haasec3aa3612010-06-17 08:50:37 -07002553
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002554 /**
2555 * The transform matrix for the View. This transform is calculated internally
2556 * based on the rotation, scaleX, and scaleY properties. The identity matrix
2557 * is used by default. Do *not* use this variable directly; instead call
2558 * getInverseMatrix(), which will automatically recalculate the matrix if necessary
2559 * to get the correct matrix based on the latest rotation and scale properties.
2560 */
2561 private Matrix mInverseMatrix;
Chet Haasec3aa3612010-06-17 08:50:37 -07002562
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002563 /**
2564 * An internal variable that tracks whether we need to recalculate the
2565 * transform matrix, based on whether the rotation or scaleX/Y properties
2566 * have changed since the matrix was last calculated.
2567 */
2568 boolean mMatrixDirty = false;
Chet Haasec3aa3612010-06-17 08:50:37 -07002569
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002570 /**
2571 * An internal variable that tracks whether we need to recalculate the
2572 * transform matrix, based on whether the rotation or scaleX/Y properties
2573 * have changed since the matrix was last calculated.
2574 */
2575 private boolean mInverseMatrixDirty = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07002576
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002577 /**
2578 * A variable that tracks whether we need to recalculate the
2579 * transform matrix, based on whether the rotation or scaleX/Y properties
2580 * have changed since the matrix was last calculated. This variable
2581 * is only valid after a call to updateMatrix() or to a function that
2582 * calls it such as getMatrix(), hasIdentityMatrix() and getInverseMatrix().
2583 */
2584 private boolean mMatrixIsIdentity = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07002585
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002586 /**
2587 * The Camera object is used to compute a 3D matrix when rotationX or rotationY are set.
2588 */
2589 private Camera mCamera = null;
Chet Haasefd2b0022010-08-06 13:08:56 -07002590
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002591 /**
2592 * This matrix is used when computing the matrix for 3D rotations.
2593 */
2594 private Matrix matrix3D = null;
Chet Haasefd2b0022010-08-06 13:08:56 -07002595
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002596 /**
2597 * These prev values are used to recalculate a centered pivot point when necessary. The
2598 * pivot point is only used in matrix operations (when rotation, scale, or translation are
2599 * set), so thes values are only used then as well.
2600 */
2601 private int mPrevWidth = -1;
2602 private int mPrevHeight = -1;
Philip Milne6c8ea062012-04-03 17:38:43 -07002603
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002604 /**
2605 * The degrees rotation around the vertical axis through the pivot point.
2606 */
2607 @ViewDebug.ExportedProperty
2608 float mRotationY = 0f;
2609
2610 /**
2611 * The degrees rotation around the horizontal axis through the pivot point.
2612 */
2613 @ViewDebug.ExportedProperty
2614 float mRotationX = 0f;
2615
2616 /**
2617 * The degrees rotation around the pivot point.
2618 */
2619 @ViewDebug.ExportedProperty
2620 float mRotation = 0f;
2621
2622 /**
2623 * The amount of translation of the object away from its left property (post-layout).
2624 */
2625 @ViewDebug.ExportedProperty
2626 float mTranslationX = 0f;
2627
2628 /**
2629 * The amount of translation of the object away from its top property (post-layout).
2630 */
2631 @ViewDebug.ExportedProperty
2632 float mTranslationY = 0f;
2633
2634 /**
2635 * The amount of scale in the x direction around the pivot point. A
2636 * value of 1 means no scaling is applied.
2637 */
2638 @ViewDebug.ExportedProperty
2639 float mScaleX = 1f;
2640
2641 /**
2642 * The amount of scale in the y direction around the pivot point. A
2643 * value of 1 means no scaling is applied.
2644 */
2645 @ViewDebug.ExportedProperty
2646 float mScaleY = 1f;
2647
2648 /**
Chet Haasea33de552012-02-03 16:28:24 -08002649 * The x location of the point around which the view is rotated and scaled.
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002650 */
2651 @ViewDebug.ExportedProperty
2652 float mPivotX = 0f;
2653
2654 /**
Chet Haasea33de552012-02-03 16:28:24 -08002655 * The y location of the point around which the view is rotated and scaled.
Dianne Hackbornddb715b2011-09-09 14:43:39 -07002656 */
2657 @ViewDebug.ExportedProperty
2658 float mPivotY = 0f;
2659
2660 /**
2661 * The opacity of the View. This is a value from 0 to 1, where 0 means
2662 * completely transparent and 1 means completely opaque.
2663 */
2664 @ViewDebug.ExportedProperty
2665 float mAlpha = 1f;
2666 }
2667
2668 TransformationInfo mTransformationInfo;
Chet Haasefd2b0022010-08-06 13:08:56 -07002669
Joe Malin32736f02011-01-19 16:14:20 -08002670 private boolean mLastIsOpaque;
2671
Chet Haasefd2b0022010-08-06 13:08:56 -07002672 /**
2673 * Convenience value to check for float values that are close enough to zero to be considered
2674 * zero.
2675 */
Romain Guy2542d192010-08-18 11:47:12 -07002676 private static final float NONZERO_EPSILON = .001f;
Chet Haasefd2b0022010-08-06 13:08:56 -07002677
2678 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002679 * The distance in pixels from the left edge of this view's parent
2680 * to the left edge of this view.
2681 * {@hide}
2682 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002683 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002684 protected int mLeft;
2685 /**
2686 * The distance in pixels from the left edge of this view's parent
2687 * to the right edge of this view.
2688 * {@hide}
2689 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002690 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002691 protected int mRight;
2692 /**
2693 * The distance in pixels from the top edge of this view's parent
2694 * to the top edge of this view.
2695 * {@hide}
2696 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002697 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002698 protected int mTop;
2699 /**
2700 * The distance in pixels from the top edge of this view's parent
2701 * to the bottom edge of this view.
2702 * {@hide}
2703 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002704 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002705 protected int mBottom;
2706
2707 /**
2708 * The offset, in pixels, by which the content of this view is scrolled
2709 * horizontally.
2710 * {@hide}
2711 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002712 @ViewDebug.ExportedProperty(category = "scrolling")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002713 protected int mScrollX;
2714 /**
2715 * The offset, in pixels, by which the content of this view is scrolled
2716 * vertically.
2717 * {@hide}
2718 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002719 @ViewDebug.ExportedProperty(category = "scrolling")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002720 protected int mScrollY;
2721
2722 /**
2723 * The left padding in pixels, that is the distance in pixels between the
2724 * left edge of this view and the left edge of its content.
2725 * {@hide}
2726 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002727 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002728 protected int mPaddingLeft;
2729 /**
2730 * The right padding in pixels, that is the distance in pixels between the
2731 * right edge of this view and the right edge of its content.
2732 * {@hide}
2733 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002734 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002735 protected int mPaddingRight;
2736 /**
2737 * The top padding in pixels, that is the distance in pixels between the
2738 * top edge of this view and the top edge of its content.
2739 * {@hide}
2740 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002741 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002742 protected int mPaddingTop;
2743 /**
2744 * The bottom padding in pixels, that is the distance in pixels between the
2745 * bottom edge of this view and the bottom edge of its content.
2746 * {@hide}
2747 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002748 @ViewDebug.ExportedProperty(category = "padding")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002749 protected int mPaddingBottom;
2750
2751 /**
Philip Milne1557fd72012-04-04 23:41:34 -07002752 * The layout insets in pixels, that is the distance in pixels between the
2753 * visible edges of this view its bounds.
2754 */
2755 private Insets mLayoutInsets;
2756
2757 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07002758 * Briefly describes the view and is primarily used for accessibility support.
2759 */
2760 private CharSequence mContentDescription;
2761
2762 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002763 * Cache the paddingRight set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002764 *
2765 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002766 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002767 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002768 protected int mUserPaddingRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002769
2770 /**
2771 * Cache the paddingBottom set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002772 *
2773 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002774 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002775 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002776 protected int mUserPaddingBottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002777
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002778 /**
Adam Powell20232d02010-12-08 21:08:53 -08002779 * Cache the paddingLeft set by the user to append to the scrollbar's size.
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002780 *
2781 * @hide
Adam Powell20232d02010-12-08 21:08:53 -08002782 */
2783 @ViewDebug.ExportedProperty(category = "padding")
Fabrice Di Meglio54d69622011-07-15 16:46:44 -07002784 protected int mUserPaddingLeft;
Adam Powell20232d02010-12-08 21:08:53 -08002785
2786 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07002787 * Cache the paddingStart set by the user to append to the scrollbar's size.
2788 *
2789 */
2790 @ViewDebug.ExportedProperty(category = "padding")
2791 int mUserPaddingStart;
2792
2793 /**
2794 * Cache the paddingEnd set by the user to append to the scrollbar's size.
2795 *
2796 */
2797 @ViewDebug.ExportedProperty(category = "padding")
2798 int mUserPaddingEnd;
2799
2800 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07002801 * Whether a left padding has been defined during layout inflation.
2802 *
2803 * @hide
2804 */
2805 boolean mUserPaddingLeftDefined = false;
2806
2807 /**
2808 * Whether a right padding has been defined during layout inflation.
2809 *
2810 * @hide
2811 */
2812 boolean mUserPaddingRightDefined = false;
2813
2814 /**
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07002815 * Default undefined padding
2816 */
2817 private static final int UNDEFINED_PADDING = Integer.MIN_VALUE;
2818
2819 /**
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07002820 * @hide
2821 */
2822 int mOldWidthMeasureSpec = Integer.MIN_VALUE;
2823 /**
2824 * @hide
2825 */
2826 int mOldHeightMeasureSpec = Integer.MIN_VALUE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002827
Philip Milne6c8ea062012-04-03 17:38:43 -07002828 private Drawable mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002829
2830 private int mBackgroundResource;
2831 private boolean mBackgroundSizeChanged;
2832
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002833 static class ListenerInfo {
2834 /**
2835 * Listener used to dispatch focus change events.
2836 * This field should be made private, so it is hidden from the SDK.
2837 * {@hide}
2838 */
2839 protected OnFocusChangeListener mOnFocusChangeListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002840
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002841 /**
2842 * Listeners for layout change events.
2843 */
2844 private ArrayList<OnLayoutChangeListener> mOnLayoutChangeListeners;
Chet Haase21cd1382010-09-01 17:42:29 -07002845
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002846 /**
2847 * Listeners for attach events.
2848 */
2849 private CopyOnWriteArrayList<OnAttachStateChangeListener> mOnAttachStateChangeListeners;
Adam Powell4afd62b2011-02-18 15:02:18 -08002850
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002851 /**
2852 * Listener used to dispatch click events.
2853 * This field should be made private, so it is hidden from the SDK.
2854 * {@hide}
2855 */
2856 public OnClickListener mOnClickListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002857
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002858 /**
2859 * Listener used to dispatch long click events.
2860 * This field should be made private, so it is hidden from the SDK.
2861 * {@hide}
2862 */
2863 protected OnLongClickListener mOnLongClickListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002864
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002865 /**
2866 * Listener used to build the context menu.
2867 * This field should be made private, so it is hidden from the SDK.
2868 * {@hide}
2869 */
2870 protected OnCreateContextMenuListener mOnCreateContextMenuListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002871
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002872 private OnKeyListener mOnKeyListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002873
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002874 private OnTouchListener mOnTouchListener;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002875
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002876 private OnHoverListener mOnHoverListener;
Jeff Brown10b62902011-06-20 16:40:37 -07002877
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002878 private OnGenericMotionListener mOnGenericMotionListener;
Jeff Brown33bbfd22011-02-24 20:55:35 -08002879
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002880 private OnDragListener mOnDragListener;
Chris Tate32affef2010-10-18 15:29:21 -07002881
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07002882 private OnSystemUiVisibilityChangeListener mOnSystemUiVisibilityChangeListener;
2883 }
2884
2885 ListenerInfo mListenerInfo;
Joe Onorato664644d2011-01-23 17:53:23 -08002886
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002887 /**
2888 * The application environment this view lives in.
2889 * This field should be made private, so it is hidden from the SDK.
2890 * {@hide}
2891 */
2892 protected Context mContext;
2893
Dianne Hackbornab0f4852011-09-12 16:59:06 -07002894 private final Resources mResources;
2895
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002896 private ScrollabilityCache mScrollCache;
2897
2898 private int[] mDrawableState = null;
2899
Romain Guy0211a0a2011-02-14 16:34:59 -08002900 /**
2901 * Set to true when drawing cache is enabled and cannot be created.
Philip Milne6c8ea062012-04-03 17:38:43 -07002902 *
Romain Guy0211a0a2011-02-14 16:34:59 -08002903 * @hide
2904 */
2905 public boolean mCachingFailed;
2906
Romain Guy02890fd2010-08-06 17:58:44 -07002907 private Bitmap mDrawingCache;
2908 private Bitmap mUnscaledDrawingCache;
Romain Guy6c319ca2011-01-11 14:29:25 -08002909 private HardwareLayer mHardwareLayer;
Romain Guy65b345f2011-07-27 18:51:50 -07002910 DisplayList mDisplayList;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002911
2912 /**
2913 * When this view has focus and the next focus is {@link #FOCUS_LEFT},
2914 * the user may specify which view to go to next.
2915 */
2916 private int mNextFocusLeftId = View.NO_ID;
2917
2918 /**
2919 * When this view has focus and the next focus is {@link #FOCUS_RIGHT},
2920 * the user may specify which view to go to next.
2921 */
2922 private int mNextFocusRightId = View.NO_ID;
2923
2924 /**
2925 * When this view has focus and the next focus is {@link #FOCUS_UP},
2926 * the user may specify which view to go to next.
2927 */
2928 private int mNextFocusUpId = View.NO_ID;
2929
2930 /**
2931 * When this view has focus and the next focus is {@link #FOCUS_DOWN},
2932 * the user may specify which view to go to next.
2933 */
2934 private int mNextFocusDownId = View.NO_ID;
2935
Jeff Brown4e6319b2010-12-13 10:36:51 -08002936 /**
2937 * When this view has focus and the next focus is {@link #FOCUS_FORWARD},
2938 * the user may specify which view to go to next.
2939 */
2940 int mNextFocusForwardId = View.NO_ID;
2941
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002942 private CheckForLongPress mPendingCheckForLongPress;
Adam Powelle14579b2009-12-16 18:39:52 -08002943 private CheckForTap mPendingCheckForTap = null;
Adam Powella35d7682010-03-12 14:48:13 -08002944 private PerformClick mPerformClick;
Svetoslav Ganova0156172011-06-26 17:55:44 -07002945 private SendViewScrolledAccessibilityEvent mSendViewScrolledAccessibilityEvent;
Joe Malin32736f02011-01-19 16:14:20 -08002946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002947 private UnsetPressedState mUnsetPressedState;
2948
2949 /**
2950 * Whether the long press's action has been invoked. The tap's action is invoked on the
2951 * up event while a long press is invoked as soon as the long press duration is reached, so
2952 * a long press could be performed before the tap is checked, in which case the tap's action
2953 * should not be invoked.
2954 */
2955 private boolean mHasPerformedLongPress;
2956
2957 /**
2958 * The minimum height of the view. We'll try our best to have the height
2959 * of this view to at least this amount.
2960 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002961 @ViewDebug.ExportedProperty(category = "measurement")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002962 private int mMinHeight;
2963
2964 /**
2965 * The minimum width of the view. We'll try our best to have the width
2966 * of this view to at least this amount.
2967 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07002968 @ViewDebug.ExportedProperty(category = "measurement")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002969 private int mMinWidth;
2970
2971 /**
2972 * The delegate to handle touch events that are physically in this view
2973 * but should be handled by another view.
2974 */
2975 private TouchDelegate mTouchDelegate = null;
2976
2977 /**
2978 * Solid color to use as a background when creating the drawing cache. Enables
2979 * the cache to use 16 bit bitmaps instead of 32 bit.
2980 */
2981 private int mDrawingCacheBackgroundColor = 0;
2982
2983 /**
2984 * Special tree observer used when mAttachInfo is null.
2985 */
2986 private ViewTreeObserver mFloatingTreeObserver;
Joe Malin32736f02011-01-19 16:14:20 -08002987
Adam Powelle14579b2009-12-16 18:39:52 -08002988 /**
2989 * Cache the touch slop from the context that created the view.
2990 */
2991 private int mTouchSlop;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002992
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08002993 /**
Chet Haasea00f3862011-02-22 06:34:40 -08002994 * Object that handles automatic animation of view properties.
2995 */
2996 private ViewPropertyAnimator mAnimator = null;
2997
2998 /**
Christopher Tate251602f2011-01-28 17:54:12 -08002999 * Flag indicating that a drag can cross window boundaries. When
3000 * {@link #startDrag(ClipData, DragShadowBuilder, Object, int)} is called
3001 * with this flag set, all visible applications will be able to participate
3002 * in the drag operation and receive the dragged content.
Christopher Tate7f9ff9d2011-02-14 17:31:13 -08003003 *
3004 * @hide
Christopher Tate02d2b3b2011-01-10 20:43:53 -08003005 */
3006 public static final int DRAG_FLAG_GLOBAL = 1;
3007
3008 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08003009 * Vertical scroll factor cached by {@link #getVerticalScrollFactor}.
3010 */
3011 private float mVerticalScrollFactor;
3012
3013 /**
Adam Powell20232d02010-12-08 21:08:53 -08003014 * Position of the vertical scroll bar.
3015 */
3016 private int mVerticalScrollbarPosition;
3017
3018 /**
3019 * Position the scroll bar at the default position as determined by the system.
3020 */
3021 public static final int SCROLLBAR_POSITION_DEFAULT = 0;
3022
3023 /**
3024 * Position the scroll bar along the left edge.
3025 */
3026 public static final int SCROLLBAR_POSITION_LEFT = 1;
3027
3028 /**
3029 * Position the scroll bar along the right edge.
3030 */
3031 public static final int SCROLLBAR_POSITION_RIGHT = 2;
3032
3033 /**
Romain Guy171c5922011-01-06 10:04:23 -08003034 * Indicates that the view does not have a layer.
Joe Malin32736f02011-01-19 16:14:20 -08003035 *
3036 * @see #getLayerType()
3037 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy171c5922011-01-06 10:04:23 -08003038 * @see #LAYER_TYPE_SOFTWARE
Joe Malin32736f02011-01-19 16:14:20 -08003039 * @see #LAYER_TYPE_HARDWARE
Romain Guy171c5922011-01-06 10:04:23 -08003040 */
3041 public static final int LAYER_TYPE_NONE = 0;
3042
3043 /**
3044 * <p>Indicates that the view has a software layer. A software layer is backed
3045 * by a bitmap and causes the view to be rendered using Android's software
3046 * rendering pipeline, even if hardware acceleration is enabled.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003047 *
Romain Guy171c5922011-01-06 10:04:23 -08003048 * <p>Software layers have various usages:</p>
3049 * <p>When the application is not using hardware acceleration, a software layer
3050 * is useful to apply a specific color filter and/or blending mode and/or
3051 * translucency to a view and all its children.</p>
3052 * <p>When the application is using hardware acceleration, a software layer
3053 * is useful to render drawing primitives not supported by the hardware
3054 * accelerated pipeline. It can also be used to cache a complex view tree
3055 * into a texture and reduce the complexity of drawing operations. For instance,
3056 * when animating a complex view tree with a translation, a software layer can
3057 * be used to render the view tree only once.</p>
3058 * <p>Software layers should be avoided when the affected view tree updates
3059 * often. Every update will require to re-render the software layer, which can
3060 * potentially be slow (particularly when hardware acceleration is turned on
3061 * since the layer will have to be uploaded into a hardware texture after every
3062 * update.)</p>
Joe Malin32736f02011-01-19 16:14:20 -08003063 *
3064 * @see #getLayerType()
3065 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy171c5922011-01-06 10:04:23 -08003066 * @see #LAYER_TYPE_NONE
Joe Malin32736f02011-01-19 16:14:20 -08003067 * @see #LAYER_TYPE_HARDWARE
Romain Guy171c5922011-01-06 10:04:23 -08003068 */
3069 public static final int LAYER_TYPE_SOFTWARE = 1;
3070
3071 /**
3072 * <p>Indicates that the view has a hardware layer. A hardware layer is backed
3073 * by a hardware specific texture (generally Frame Buffer Objects or FBO on
3074 * OpenGL hardware) and causes the view to be rendered using Android's hardware
3075 * rendering pipeline, but only if hardware acceleration is turned on for the
3076 * view hierarchy. When hardware acceleration is turned off, hardware layers
3077 * behave exactly as {@link #LAYER_TYPE_SOFTWARE software layers}.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003078 *
Romain Guy171c5922011-01-06 10:04:23 -08003079 * <p>A hardware layer is useful to apply a specific color filter and/or
3080 * blending mode and/or translucency to a view and all its children.</p>
Romain Guy6c319ca2011-01-11 14:29:25 -08003081 * <p>A hardware layer can be used to cache a complex view tree into a
3082 * texture and reduce the complexity of drawing operations. For instance,
3083 * when animating a complex view tree with a translation, a hardware layer can
3084 * be used to render the view tree only once.</p>
Romain Guy171c5922011-01-06 10:04:23 -08003085 * <p>A hardware layer can also be used to increase the rendering quality when
3086 * rotation transformations are applied on a view. It can also be used to
3087 * prevent potential clipping issues when applying 3D transforms on a view.</p>
Joe Malin32736f02011-01-19 16:14:20 -08003088 *
3089 * @see #getLayerType()
Romain Guy171c5922011-01-06 10:04:23 -08003090 * @see #setLayerType(int, android.graphics.Paint)
3091 * @see #LAYER_TYPE_NONE
3092 * @see #LAYER_TYPE_SOFTWARE
3093 */
3094 public static final int LAYER_TYPE_HARDWARE = 2;
Joe Malin32736f02011-01-19 16:14:20 -08003095
Romain Guy3aaff3a2011-01-12 14:18:47 -08003096 @ViewDebug.ExportedProperty(category = "drawing", mapping = {
3097 @ViewDebug.IntToString(from = LAYER_TYPE_NONE, to = "NONE"),
3098 @ViewDebug.IntToString(from = LAYER_TYPE_SOFTWARE, to = "SOFTWARE"),
3099 @ViewDebug.IntToString(from = LAYER_TYPE_HARDWARE, to = "HARDWARE")
3100 })
Romain Guy171c5922011-01-06 10:04:23 -08003101 int mLayerType = LAYER_TYPE_NONE;
3102 Paint mLayerPaint;
Romain Guy3a3133d2011-02-01 22:59:58 -08003103 Rect mLocalDirtyRect;
Romain Guy171c5922011-01-06 10:04:23 -08003104
3105 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07003106 * Set to true when the view is sending hover accessibility events because it
3107 * is the innermost hovered view.
3108 */
3109 private boolean mSendingHoverAccessibilityEvents;
3110
Dianne Hackborn4702a852012-08-17 15:18:29 -07003111 /**
3112 * Delegate for injecting accessiblity functionality.
3113 */
3114 AccessibilityDelegate mAccessibilityDelegate;
3115
3116 /**
3117 * Consistency verifier for debugging purposes.
3118 * @hide
3119 */
3120 protected final InputEventConsistencyVerifier mInputEventConsistencyVerifier =
3121 InputEventConsistencyVerifier.isInstrumentationEnabled() ?
3122 new InputEventConsistencyVerifier(this, 0) : null;
3123
Adam Powella9108a22012-07-18 11:18:09 -07003124 private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);
3125
Jeff Brown87b7f802011-06-21 18:35:45 -07003126 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003127 * Simple constructor to use when creating a view from code.
3128 *
3129 * @param context The Context the view is running in, through which it can
3130 * access the current theme, resources, etc.
3131 */
3132 public View(Context context) {
3133 mContext = context;
3134 mResources = context != null ? context.getResources() : null;
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003135 mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003136 // Set layout and text direction defaults
Dianne Hackborn4702a852012-08-17 15:18:29 -07003137 mPrivateFlags2 = (LAYOUT_DIRECTION_DEFAULT << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) |
3138 (TEXT_DIRECTION_DEFAULT << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) |
3139 (TEXT_ALIGNMENT_DEFAULT << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) |
3140 (IMPORTANT_FOR_ACCESSIBILITY_DEFAULT << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT);
Adam Powelle14579b2009-12-16 18:39:52 -08003141 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
Adam Powell637d3372010-08-25 14:37:03 -07003142 setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003143 mUserPaddingStart = UNDEFINED_PADDING;
3144 mUserPaddingEnd = UNDEFINED_PADDING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003145 }
3146
3147 /**
3148 * Constructor that is called when inflating a view from XML. This is called
3149 * when a view is being constructed from an XML file, supplying attributes
3150 * that were specified in the XML file. This version uses a default style of
3151 * 0, so the only attribute values applied are those in the Context's Theme
3152 * and the given AttributeSet.
3153 *
3154 * <p>
3155 * The method onFinishInflate() will be called after all children have been
3156 * added.
3157 *
3158 * @param context The Context the view is running in, through which it can
3159 * access the current theme, resources, etc.
3160 * @param attrs The attributes of the XML tag that is inflating the view.
3161 * @see #View(Context, AttributeSet, int)
3162 */
3163 public View(Context context, AttributeSet attrs) {
3164 this(context, attrs, 0);
3165 }
3166
3167 /**
3168 * Perform inflation from XML and apply a class-specific base style. This
3169 * constructor of View allows subclasses to use their own base style when
3170 * they are inflating. For example, a Button class's constructor would call
3171 * this version of the super class constructor and supply
3172 * <code>R.attr.buttonStyle</code> for <var>defStyle</var>; this allows
3173 * the theme's button style to modify all of the base view attributes (in
3174 * particular its background) as well as the Button class's attributes.
3175 *
3176 * @param context The Context the view is running in, through which it can
3177 * access the current theme, resources, etc.
3178 * @param attrs The attributes of the XML tag that is inflating the view.
3179 * @param defStyle The default style to apply to this view. If 0, no style
3180 * will be applied (beyond what is included in the theme). This may
3181 * either be an attribute resource, whose value will be retrieved
3182 * from the current theme, or an explicit style resource.
3183 * @see #View(Context, AttributeSet)
3184 */
3185 public View(Context context, AttributeSet attrs, int defStyle) {
3186 this(context);
3187
3188 TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.View,
3189 defStyle, 0);
3190
3191 Drawable background = null;
3192
3193 int leftPadding = -1;
3194 int topPadding = -1;
3195 int rightPadding = -1;
3196 int bottomPadding = -1;
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003197 int startPadding = UNDEFINED_PADDING;
3198 int endPadding = UNDEFINED_PADDING;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003199
3200 int padding = -1;
3201
3202 int viewFlagValues = 0;
3203 int viewFlagMasks = 0;
3204
3205 boolean setScrollContainer = false;
Romain Guy8506ab42009-06-11 17:35:47 -07003206
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003207 int x = 0;
3208 int y = 0;
3209
Chet Haase73066682010-11-29 15:55:32 -08003210 float tx = 0;
3211 float ty = 0;
3212 float rotation = 0;
3213 float rotationX = 0;
3214 float rotationY = 0;
3215 float sx = 1f;
3216 float sy = 1f;
3217 boolean transformSet = false;
3218
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003219 int scrollbarStyle = SCROLLBARS_INSIDE_OVERLAY;
Adam Powell637d3372010-08-25 14:37:03 -07003220 int overScrollMode = mOverScrollMode;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003221 boolean initializeScrollbars = false;
3222
3223 final int targetSdkVersion = context.getApplicationInfo().targetSdkVersion;
3224
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003225 final int N = a.getIndexCount();
3226 for (int i = 0; i < N; i++) {
3227 int attr = a.getIndex(i);
3228 switch (attr) {
3229 case com.android.internal.R.styleable.View_background:
3230 background = a.getDrawable(attr);
3231 break;
3232 case com.android.internal.R.styleable.View_padding:
3233 padding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003234 mUserPaddingLeftDefined = true;
3235 mUserPaddingRightDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003236 break;
3237 case com.android.internal.R.styleable.View_paddingLeft:
3238 leftPadding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003239 mUserPaddingLeftDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003240 break;
3241 case com.android.internal.R.styleable.View_paddingTop:
3242 topPadding = a.getDimensionPixelSize(attr, -1);
3243 break;
3244 case com.android.internal.R.styleable.View_paddingRight:
3245 rightPadding = a.getDimensionPixelSize(attr, -1);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003246 mUserPaddingRightDefined = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003247 break;
3248 case com.android.internal.R.styleable.View_paddingBottom:
3249 bottomPadding = a.getDimensionPixelSize(attr, -1);
3250 break;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003251 case com.android.internal.R.styleable.View_paddingStart:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003252 startPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003253 break;
3254 case com.android.internal.R.styleable.View_paddingEnd:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003255 endPadding = a.getDimensionPixelSize(attr, UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003256 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003257 case com.android.internal.R.styleable.View_scrollX:
3258 x = a.getDimensionPixelOffset(attr, 0);
3259 break;
3260 case com.android.internal.R.styleable.View_scrollY:
3261 y = a.getDimensionPixelOffset(attr, 0);
3262 break;
Chet Haase73066682010-11-29 15:55:32 -08003263 case com.android.internal.R.styleable.View_alpha:
3264 setAlpha(a.getFloat(attr, 1f));
3265 break;
3266 case com.android.internal.R.styleable.View_transformPivotX:
3267 setPivotX(a.getDimensionPixelOffset(attr, 0));
3268 break;
3269 case com.android.internal.R.styleable.View_transformPivotY:
3270 setPivotY(a.getDimensionPixelOffset(attr, 0));
3271 break;
3272 case com.android.internal.R.styleable.View_translationX:
3273 tx = a.getDimensionPixelOffset(attr, 0);
3274 transformSet = true;
3275 break;
3276 case com.android.internal.R.styleable.View_translationY:
3277 ty = a.getDimensionPixelOffset(attr, 0);
3278 transformSet = true;
3279 break;
3280 case com.android.internal.R.styleable.View_rotation:
3281 rotation = a.getFloat(attr, 0);
3282 transformSet = true;
3283 break;
3284 case com.android.internal.R.styleable.View_rotationX:
3285 rotationX = a.getFloat(attr, 0);
3286 transformSet = true;
3287 break;
3288 case com.android.internal.R.styleable.View_rotationY:
3289 rotationY = a.getFloat(attr, 0);
3290 transformSet = true;
3291 break;
3292 case com.android.internal.R.styleable.View_scaleX:
3293 sx = a.getFloat(attr, 1f);
3294 transformSet = true;
3295 break;
3296 case com.android.internal.R.styleable.View_scaleY:
3297 sy = a.getFloat(attr, 1f);
3298 transformSet = true;
3299 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003300 case com.android.internal.R.styleable.View_id:
3301 mID = a.getResourceId(attr, NO_ID);
3302 break;
3303 case com.android.internal.R.styleable.View_tag:
3304 mTag = a.getText(attr);
3305 break;
3306 case com.android.internal.R.styleable.View_fitsSystemWindows:
3307 if (a.getBoolean(attr, false)) {
3308 viewFlagValues |= FITS_SYSTEM_WINDOWS;
3309 viewFlagMasks |= FITS_SYSTEM_WINDOWS;
3310 }
3311 break;
3312 case com.android.internal.R.styleable.View_focusable:
3313 if (a.getBoolean(attr, false)) {
3314 viewFlagValues |= FOCUSABLE;
3315 viewFlagMasks |= FOCUSABLE_MASK;
3316 }
3317 break;
3318 case com.android.internal.R.styleable.View_focusableInTouchMode:
3319 if (a.getBoolean(attr, false)) {
3320 viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;
3321 viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;
3322 }
3323 break;
3324 case com.android.internal.R.styleable.View_clickable:
3325 if (a.getBoolean(attr, false)) {
3326 viewFlagValues |= CLICKABLE;
3327 viewFlagMasks |= CLICKABLE;
3328 }
3329 break;
3330 case com.android.internal.R.styleable.View_longClickable:
3331 if (a.getBoolean(attr, false)) {
3332 viewFlagValues |= LONG_CLICKABLE;
3333 viewFlagMasks |= LONG_CLICKABLE;
3334 }
3335 break;
3336 case com.android.internal.R.styleable.View_saveEnabled:
3337 if (!a.getBoolean(attr, true)) {
3338 viewFlagValues |= SAVE_DISABLED;
3339 viewFlagMasks |= SAVE_DISABLED_MASK;
3340 }
3341 break;
3342 case com.android.internal.R.styleable.View_duplicateParentState:
3343 if (a.getBoolean(attr, false)) {
3344 viewFlagValues |= DUPLICATE_PARENT_STATE;
3345 viewFlagMasks |= DUPLICATE_PARENT_STATE;
3346 }
3347 break;
3348 case com.android.internal.R.styleable.View_visibility:
3349 final int visibility = a.getInt(attr, 0);
3350 if (visibility != 0) {
3351 viewFlagValues |= VISIBILITY_FLAGS[visibility];
3352 viewFlagMasks |= VISIBILITY_MASK;
3353 }
3354 break;
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07003355 case com.android.internal.R.styleable.View_layoutDirection:
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003356 // Clear any layout direction flags (included resolved bits) already set
Dianne Hackborn4702a852012-08-17 15:18:29 -07003357 mPrivateFlags2 &= ~(PFLAG2_LAYOUT_DIRECTION_MASK | PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK);
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003358 // Set the layout direction flags depending on the value of the attribute
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07003359 final int layoutDirection = a.getInt(attr, -1);
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07003360 final int value = (layoutDirection != -1) ?
3361 LAYOUT_DIRECTION_FLAGS[layoutDirection] : LAYOUT_DIRECTION_DEFAULT;
Dianne Hackborn4702a852012-08-17 15:18:29 -07003362 mPrivateFlags2 |= (value << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT);
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -07003363 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003364 case com.android.internal.R.styleable.View_drawingCacheQuality:
3365 final int cacheQuality = a.getInt(attr, 0);
3366 if (cacheQuality != 0) {
3367 viewFlagValues |= DRAWING_CACHE_QUALITY_FLAGS[cacheQuality];
3368 viewFlagMasks |= DRAWING_CACHE_QUALITY_MASK;
3369 }
3370 break;
svetoslavganov75986cf2009-05-14 22:28:01 -07003371 case com.android.internal.R.styleable.View_contentDescription:
Svetoslav Ganove47957a2012-06-05 14:46:50 -07003372 setContentDescription(a.getString(attr));
svetoslavganov75986cf2009-05-14 22:28:01 -07003373 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003374 case com.android.internal.R.styleable.View_soundEffectsEnabled:
3375 if (!a.getBoolean(attr, true)) {
3376 viewFlagValues &= ~SOUND_EFFECTS_ENABLED;
3377 viewFlagMasks |= SOUND_EFFECTS_ENABLED;
3378 }
Karl Rosaen61ab2702009-06-23 11:10:25 -07003379 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003380 case com.android.internal.R.styleable.View_hapticFeedbackEnabled:
3381 if (!a.getBoolean(attr, true)) {
3382 viewFlagValues &= ~HAPTIC_FEEDBACK_ENABLED;
3383 viewFlagMasks |= HAPTIC_FEEDBACK_ENABLED;
3384 }
Karl Rosaen61ab2702009-06-23 11:10:25 -07003385 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003386 case R.styleable.View_scrollbars:
3387 final int scrollbars = a.getInt(attr, SCROLLBARS_NONE);
3388 if (scrollbars != SCROLLBARS_NONE) {
3389 viewFlagValues |= scrollbars;
3390 viewFlagMasks |= SCROLLBARS_MASK;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003391 initializeScrollbars = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003392 }
3393 break;
Romain Guy2a9fa892011-09-28 16:50:02 -07003394 //noinspection deprecation
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003395 case R.styleable.View_fadingEdge:
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003396 if (targetSdkVersion >= ICE_CREAM_SANDWICH) {
Romain Guy1ef3fdb2011-09-09 15:30:30 -07003397 // Ignore the attribute starting with ICS
3398 break;
3399 }
3400 // With builds < ICS, fall through and apply fading edges
3401 case R.styleable.View_requiresFadingEdge:
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003402 final int fadingEdge = a.getInt(attr, FADING_EDGE_NONE);
3403 if (fadingEdge != FADING_EDGE_NONE) {
3404 viewFlagValues |= fadingEdge;
3405 viewFlagMasks |= FADING_EDGE_MASK;
3406 initializeFadingEdge(a);
3407 }
3408 break;
3409 case R.styleable.View_scrollbarStyle:
3410 scrollbarStyle = a.getInt(attr, SCROLLBARS_INSIDE_OVERLAY);
3411 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3412 viewFlagValues |= scrollbarStyle & SCROLLBARS_STYLE_MASK;
3413 viewFlagMasks |= SCROLLBARS_STYLE_MASK;
3414 }
3415 break;
3416 case R.styleable.View_isScrollContainer:
3417 setScrollContainer = true;
3418 if (a.getBoolean(attr, false)) {
3419 setScrollContainer(true);
3420 }
3421 break;
3422 case com.android.internal.R.styleable.View_keepScreenOn:
3423 if (a.getBoolean(attr, false)) {
3424 viewFlagValues |= KEEP_SCREEN_ON;
3425 viewFlagMasks |= KEEP_SCREEN_ON;
3426 }
3427 break;
Jeff Brown85a31762010-09-01 17:01:00 -07003428 case R.styleable.View_filterTouchesWhenObscured:
3429 if (a.getBoolean(attr, false)) {
3430 viewFlagValues |= FILTER_TOUCHES_WHEN_OBSCURED;
3431 viewFlagMasks |= FILTER_TOUCHES_WHEN_OBSCURED;
3432 }
3433 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003434 case R.styleable.View_nextFocusLeft:
3435 mNextFocusLeftId = a.getResourceId(attr, View.NO_ID);
3436 break;
3437 case R.styleable.View_nextFocusRight:
3438 mNextFocusRightId = a.getResourceId(attr, View.NO_ID);
3439 break;
3440 case R.styleable.View_nextFocusUp:
3441 mNextFocusUpId = a.getResourceId(attr, View.NO_ID);
3442 break;
3443 case R.styleable.View_nextFocusDown:
3444 mNextFocusDownId = a.getResourceId(attr, View.NO_ID);
3445 break;
Jeff Brown4e6319b2010-12-13 10:36:51 -08003446 case R.styleable.View_nextFocusForward:
3447 mNextFocusForwardId = a.getResourceId(attr, View.NO_ID);
3448 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003449 case R.styleable.View_minWidth:
3450 mMinWidth = a.getDimensionPixelSize(attr, 0);
3451 break;
3452 case R.styleable.View_minHeight:
3453 mMinHeight = a.getDimensionPixelSize(attr, 0);
3454 break;
Romain Guy9a817362009-05-01 10:57:14 -07003455 case R.styleable.View_onClick:
Romain Guy870e09f2009-07-06 16:35:25 -07003456 if (context.isRestricted()) {
Joe Malin32736f02011-01-19 16:14:20 -08003457 throw new IllegalStateException("The android:onClick attribute cannot "
Romain Guy870e09f2009-07-06 16:35:25 -07003458 + "be used within a restricted context");
3459 }
3460
Romain Guy9a817362009-05-01 10:57:14 -07003461 final String handlerName = a.getString(attr);
3462 if (handlerName != null) {
3463 setOnClickListener(new OnClickListener() {
3464 private Method mHandler;
3465
3466 public void onClick(View v) {
3467 if (mHandler == null) {
3468 try {
3469 mHandler = getContext().getClass().getMethod(handlerName,
3470 View.class);
3471 } catch (NoSuchMethodException e) {
Joe Onorato42e14d72010-03-11 14:51:17 -08003472 int id = getId();
3473 String idText = id == NO_ID ? "" : " with id '"
3474 + getContext().getResources().getResourceEntryName(
3475 id) + "'";
Romain Guy9a817362009-05-01 10:57:14 -07003476 throw new IllegalStateException("Could not find a method " +
Joe Onorato42e14d72010-03-11 14:51:17 -08003477 handlerName + "(View) in the activity "
3478 + getContext().getClass() + " for onClick handler"
3479 + " on view " + View.this.getClass() + idText, e);
Romain Guy9a817362009-05-01 10:57:14 -07003480 }
3481 }
3482
3483 try {
3484 mHandler.invoke(getContext(), View.this);
3485 } catch (IllegalAccessException e) {
3486 throw new IllegalStateException("Could not execute non "
3487 + "public method of the activity", e);
3488 } catch (InvocationTargetException e) {
3489 throw new IllegalStateException("Could not execute "
3490 + "method of the activity", e);
3491 }
3492 }
3493 });
3494 }
3495 break;
Adam Powell637d3372010-08-25 14:37:03 -07003496 case R.styleable.View_overScrollMode:
3497 overScrollMode = a.getInt(attr, OVER_SCROLL_IF_CONTENT_SCROLLS);
3498 break;
Adam Powell20232d02010-12-08 21:08:53 -08003499 case R.styleable.View_verticalScrollbarPosition:
3500 mVerticalScrollbarPosition = a.getInt(attr, SCROLLBAR_POSITION_DEFAULT);
3501 break;
Romain Guy171c5922011-01-06 10:04:23 -08003502 case R.styleable.View_layerType:
3503 setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
3504 break;
Fabrice Di Meglio22268862011-06-27 18:13:18 -07003505 case R.styleable.View_textDirection:
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003506 // Clear any text direction flag already set
Dianne Hackborn4702a852012-08-17 15:18:29 -07003507 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003508 // Set the text direction flags depending on the value of the attribute
3509 final int textDirection = a.getInt(attr, -1);
3510 if (textDirection != -1) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07003511 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_FLAGS[textDirection];
Fabrice Di Megliob934db72012-03-20 14:33:01 -07003512 }
Fabrice Di Meglio22268862011-06-27 18:13:18 -07003513 break;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003514 case R.styleable.View_textAlignment:
3515 // Clear any text alignment flag already set
Dianne Hackborn4702a852012-08-17 15:18:29 -07003516 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003517 // Set the text alignment flag depending on the value of the attribute
3518 final int textAlignment = a.getInt(attr, TEXT_ALIGNMENT_DEFAULT);
Dianne Hackborn4702a852012-08-17 15:18:29 -07003519 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_FLAGS[textAlignment];
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -07003520 break;
Svetoslav Ganov42138042012-03-20 11:51:39 -07003521 case R.styleable.View_importantForAccessibility:
3522 setImportantForAccessibility(a.getInt(attr,
3523 IMPORTANT_FOR_ACCESSIBILITY_DEFAULT));
Svetoslav Ganov86783472012-06-06 21:12:20 -07003524 break;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003525 }
3526 }
3527
Adam Powell637d3372010-08-25 14:37:03 -07003528 setOverScrollMode(overScrollMode);
3529
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003530 // Cache start/end user padding as we cannot fully resolve padding here (we dont have yet
3531 // the resolved layout direction). Those cached values will be used later during padding
3532 // resolution.
Fabrice Di Megliof9e36502011-06-21 18:41:48 -07003533 mUserPaddingStart = startPadding;
3534 mUserPaddingEnd = endPadding;
3535
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003536 if (background != null) {
3537 setBackground(background);
3538 }
Fabrice Di Meglio509708d2012-03-06 15:41:11 -08003539
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003540 if (padding >= 0) {
3541 leftPadding = padding;
3542 topPadding = padding;
3543 rightPadding = padding;
3544 bottomPadding = padding;
3545 }
3546
3547 // If the user specified the padding (either with android:padding or
3548 // android:paddingLeft/Top/Right/Bottom), use this padding, otherwise
3549 // use the default padding or the padding from the background drawable
3550 // (stored at this point in mPadding*)
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07003551 internalSetPadding(leftPadding >= 0 ? leftPadding : mPaddingLeft,
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003552 topPadding >= 0 ? topPadding : mPaddingTop,
3553 rightPadding >= 0 ? rightPadding : mPaddingRight,
3554 bottomPadding >= 0 ? bottomPadding : mPaddingBottom);
3555
3556 if (viewFlagMasks != 0) {
3557 setFlags(viewFlagValues, viewFlagMasks);
3558 }
3559
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07003560 if (initializeScrollbars) {
3561 initializeScrollbars(a);
3562 }
3563
3564 a.recycle();
3565
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003566 // Needs to be called after mViewFlags is set
3567 if (scrollbarStyle != SCROLLBARS_INSIDE_OVERLAY) {
3568 recomputePadding();
3569 }
3570
3571 if (x != 0 || y != 0) {
3572 scrollTo(x, y);
3573 }
3574
Chet Haase73066682010-11-29 15:55:32 -08003575 if (transformSet) {
3576 setTranslationX(tx);
3577 setTranslationY(ty);
3578 setRotation(rotation);
3579 setRotationX(rotationX);
3580 setRotationY(rotationY);
3581 setScaleX(sx);
3582 setScaleY(sy);
3583 }
3584
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003585 if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
3586 setScrollContainer(true);
3587 }
Romain Guy8f1344f52009-05-15 16:03:59 -07003588
3589 computeOpaqueFlags();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003590 }
3591
3592 /**
3593 * Non-public constructor for use in testing
3594 */
3595 View() {
Dianne Hackbornab0f4852011-09-12 16:59:06 -07003596 mResources = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003597 }
3598
Dianne Hackborn4702a852012-08-17 15:18:29 -07003599 public String toString() {
3600 StringBuilder out = new StringBuilder(128);
3601 out.append(getClass().getName());
3602 out.append('{');
3603 out.append(Integer.toHexString(System.identityHashCode(this)));
3604 out.append(' ');
3605 switch (mViewFlags&VISIBILITY_MASK) {
3606 case VISIBLE: out.append('V'); break;
3607 case INVISIBLE: out.append('I'); break;
3608 case GONE: out.append('G'); break;
3609 default: out.append('.'); break;
3610 }
3611 out.append((mViewFlags&FOCUSABLE_MASK) == FOCUSABLE ? 'F' : '.');
3612 out.append((mViewFlags&ENABLED_MASK) == ENABLED ? 'E' : '.');
3613 out.append((mViewFlags&DRAW_MASK) == WILL_NOT_DRAW ? '.' : 'D');
3614 out.append((mViewFlags&SCROLLBARS_HORIZONTAL) != 0 ? 'H' : '.');
3615 out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
3616 out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
3617 out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
3618 out.append(' ');
3619 out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
3620 out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
3621 out.append((mPrivateFlags&PFLAG_SELECTED) != 0 ? 'S' : '.');
3622 if ((mPrivateFlags&PFLAG_PREPRESSED) != 0) {
3623 out.append('p');
3624 } else {
3625 out.append((mPrivateFlags&PFLAG_PRESSED) != 0 ? 'P' : '.');
3626 }
3627 out.append((mPrivateFlags&PFLAG_HOVERED) != 0 ? 'H' : '.');
3628 out.append((mPrivateFlags&PFLAG_ACTIVATED) != 0 ? 'A' : '.');
3629 out.append((mPrivateFlags&PFLAG_INVALIDATED) != 0 ? 'I' : '.');
3630 out.append((mPrivateFlags&PFLAG_DIRTY_MASK) != 0 ? 'D' : '.');
3631 out.append(' ');
3632 out.append(mLeft);
3633 out.append(',');
3634 out.append(mTop);
3635 out.append('-');
3636 out.append(mRight);
3637 out.append(',');
3638 out.append(mBottom);
3639 final int id = getId();
3640 if (id != NO_ID) {
3641 out.append(" #");
3642 out.append(Integer.toHexString(id));
3643 final Resources r = mResources;
3644 if (id != 0 && r != null) {
3645 try {
3646 String pkgname;
3647 switch (id&0xff000000) {
3648 case 0x7f000000:
3649 pkgname="app";
3650 break;
3651 case 0x01000000:
3652 pkgname="android";
3653 break;
3654 default:
3655 pkgname = r.getResourcePackageName(id);
3656 break;
3657 }
3658 String typename = r.getResourceTypeName(id);
3659 String entryname = r.getResourceEntryName(id);
3660 out.append(" ");
3661 out.append(pkgname);
3662 out.append(":");
3663 out.append(typename);
3664 out.append("/");
3665 out.append(entryname);
3666 } catch (Resources.NotFoundException e) {
3667 }
3668 }
3669 }
3670 out.append("}");
3671 return out.toString();
3672 }
3673
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003674 /**
3675 * <p>
3676 * Initializes the fading edges from a given set of styled attributes. This
3677 * method should be called by subclasses that need fading edges and when an
3678 * instance of these subclasses is created programmatically rather than
3679 * being inflated from XML. This method is automatically called when the XML
3680 * is inflated.
3681 * </p>
3682 *
3683 * @param a the styled attributes set to initialize the fading edges from
3684 */
3685 protected void initializeFadingEdge(TypedArray a) {
3686 initScrollCache();
3687
3688 mScrollCache.fadingEdgeLength = a.getDimensionPixelSize(
3689 R.styleable.View_fadingEdgeLength,
3690 ViewConfiguration.get(mContext).getScaledFadingEdgeLength());
3691 }
3692
3693 /**
3694 * Returns the size of the vertical faded edges used to indicate that more
3695 * content in this view is visible.
3696 *
3697 * @return The size in pixels of the vertical faded edge or 0 if vertical
3698 * faded edges are not enabled for this view.
3699 * @attr ref android.R.styleable#View_fadingEdgeLength
3700 */
3701 public int getVerticalFadingEdgeLength() {
3702 if (isVerticalFadingEdgeEnabled()) {
3703 ScrollabilityCache cache = mScrollCache;
3704 if (cache != null) {
3705 return cache.fadingEdgeLength;
3706 }
3707 }
3708 return 0;
3709 }
3710
3711 /**
3712 * Set the size of the faded edge used to indicate that more content in this
3713 * view is available. Will not change whether the fading edge is enabled; use
Romain Guy5c22a8c2011-05-13 11:48:45 -07003714 * {@link #setVerticalFadingEdgeEnabled(boolean)} or
3715 * {@link #setHorizontalFadingEdgeEnabled(boolean)} to enable the fading edge
3716 * for the vertical or horizontal fading edges.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003717 *
3718 * @param length The size in pixels of the faded edge used to indicate that more
3719 * content in this view is visible.
3720 */
3721 public void setFadingEdgeLength(int length) {
3722 initScrollCache();
3723 mScrollCache.fadingEdgeLength = length;
3724 }
3725
3726 /**
3727 * Returns the size of the horizontal faded edges used to indicate that more
3728 * content in this view is visible.
3729 *
3730 * @return The size in pixels of the horizontal faded edge or 0 if horizontal
3731 * faded edges are not enabled for this view.
3732 * @attr ref android.R.styleable#View_fadingEdgeLength
3733 */
3734 public int getHorizontalFadingEdgeLength() {
3735 if (isHorizontalFadingEdgeEnabled()) {
3736 ScrollabilityCache cache = mScrollCache;
3737 if (cache != null) {
3738 return cache.fadingEdgeLength;
3739 }
3740 }
3741 return 0;
3742 }
3743
3744 /**
3745 * Returns the width of the vertical scrollbar.
3746 *
3747 * @return The width in pixels of the vertical scrollbar or 0 if there
3748 * is no vertical scrollbar.
3749 */
3750 public int getVerticalScrollbarWidth() {
3751 ScrollabilityCache cache = mScrollCache;
3752 if (cache != null) {
3753 ScrollBarDrawable scrollBar = cache.scrollBar;
3754 if (scrollBar != null) {
3755 int size = scrollBar.getSize(true);
3756 if (size <= 0) {
3757 size = cache.scrollBarSize;
3758 }
3759 return size;
3760 }
3761 return 0;
3762 }
3763 return 0;
3764 }
3765
3766 /**
3767 * Returns the height of the horizontal scrollbar.
3768 *
3769 * @return The height in pixels of the horizontal scrollbar or 0 if
3770 * there is no horizontal scrollbar.
3771 */
3772 protected int getHorizontalScrollbarHeight() {
3773 ScrollabilityCache cache = mScrollCache;
3774 if (cache != null) {
3775 ScrollBarDrawable scrollBar = cache.scrollBar;
3776 if (scrollBar != null) {
3777 int size = scrollBar.getSize(false);
3778 if (size <= 0) {
3779 size = cache.scrollBarSize;
3780 }
3781 return size;
3782 }
3783 return 0;
3784 }
3785 return 0;
3786 }
3787
3788 /**
3789 * <p>
3790 * Initializes the scrollbars from a given set of styled attributes. This
3791 * method should be called by subclasses that need scrollbars and when an
3792 * instance of these subclasses is created programmatically rather than
3793 * being inflated from XML. This method is automatically called when the XML
3794 * is inflated.
3795 * </p>
3796 *
3797 * @param a the styled attributes set to initialize the scrollbars from
3798 */
3799 protected void initializeScrollbars(TypedArray a) {
3800 initScrollCache();
3801
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003802 final ScrollabilityCache scrollabilityCache = mScrollCache;
Joe Malin32736f02011-01-19 16:14:20 -08003803
Mike Cleronf116bf82009-09-27 19:14:12 -07003804 if (scrollabilityCache.scrollBar == null) {
3805 scrollabilityCache.scrollBar = new ScrollBarDrawable();
3806 }
Joe Malin32736f02011-01-19 16:14:20 -08003807
Romain Guy8bda2482010-03-02 11:42:11 -08003808 final boolean fadeScrollbars = a.getBoolean(R.styleable.View_fadeScrollbars, true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003809
Mike Cleronf116bf82009-09-27 19:14:12 -07003810 if (!fadeScrollbars) {
3811 scrollabilityCache.state = ScrollabilityCache.ON;
3812 }
3813 scrollabilityCache.fadeScrollBars = fadeScrollbars;
Joe Malin32736f02011-01-19 16:14:20 -08003814
3815
Mike Cleronf116bf82009-09-27 19:14:12 -07003816 scrollabilityCache.scrollBarFadeDuration = a.getInt(
3817 R.styleable.View_scrollbarFadeDuration, ViewConfiguration
3818 .getScrollBarFadeDuration());
3819 scrollabilityCache.scrollBarDefaultDelayBeforeFade = a.getInt(
3820 R.styleable.View_scrollbarDefaultDelayBeforeFade,
3821 ViewConfiguration.getScrollDefaultDelay());
3822
Joe Malin32736f02011-01-19 16:14:20 -08003823
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003824 scrollabilityCache.scrollBarSize = a.getDimensionPixelSize(
3825 com.android.internal.R.styleable.View_scrollbarSize,
3826 ViewConfiguration.get(mContext).getScaledScrollBarSize());
3827
3828 Drawable track = a.getDrawable(R.styleable.View_scrollbarTrackHorizontal);
3829 scrollabilityCache.scrollBar.setHorizontalTrackDrawable(track);
3830
3831 Drawable thumb = a.getDrawable(R.styleable.View_scrollbarThumbHorizontal);
3832 if (thumb != null) {
3833 scrollabilityCache.scrollBar.setHorizontalThumbDrawable(thumb);
3834 }
3835
3836 boolean alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawHorizontalTrack,
3837 false);
3838 if (alwaysDraw) {
3839 scrollabilityCache.scrollBar.setAlwaysDrawHorizontalTrack(true);
3840 }
3841
3842 track = a.getDrawable(R.styleable.View_scrollbarTrackVertical);
3843 scrollabilityCache.scrollBar.setVerticalTrackDrawable(track);
3844
3845 thumb = a.getDrawable(R.styleable.View_scrollbarThumbVertical);
3846 if (thumb != null) {
3847 scrollabilityCache.scrollBar.setVerticalThumbDrawable(thumb);
3848 }
3849
3850 alwaysDraw = a.getBoolean(R.styleable.View_scrollbarAlwaysDrawVerticalTrack,
3851 false);
3852 if (alwaysDraw) {
3853 scrollabilityCache.scrollBar.setAlwaysDrawVerticalTrack(true);
3854 }
3855
Fabrice Di Megliob03b4342012-06-04 12:55:30 -07003856 // Apply layout direction to the new Drawables if needed
3857 final int layoutDirection = getResolvedLayoutDirection();
3858 if (track != null) {
3859 track.setLayoutDirection(layoutDirection);
3860 }
3861 if (thumb != null) {
3862 thumb.setLayoutDirection(layoutDirection);
3863 }
3864
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003865 // Re-apply user/background padding so that scrollbar(s) get added
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003866 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003867 }
3868
3869 /**
3870 * <p>
3871 * Initalizes the scrollability cache if necessary.
3872 * </p>
3873 */
3874 private void initScrollCache() {
3875 if (mScrollCache == null) {
Mike Cleronf116bf82009-09-27 19:14:12 -07003876 mScrollCache = new ScrollabilityCache(ViewConfiguration.get(mContext), this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003877 }
3878 }
3879
Philip Milne6c8ea062012-04-03 17:38:43 -07003880 private ScrollabilityCache getScrollCache() {
3881 initScrollCache();
3882 return mScrollCache;
3883 }
3884
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003885 /**
Adam Powell20232d02010-12-08 21:08:53 -08003886 * Set the position of the vertical scroll bar. Should be one of
3887 * {@link #SCROLLBAR_POSITION_DEFAULT}, {@link #SCROLLBAR_POSITION_LEFT} or
3888 * {@link #SCROLLBAR_POSITION_RIGHT}.
3889 *
3890 * @param position Where the vertical scroll bar should be positioned.
3891 */
3892 public void setVerticalScrollbarPosition(int position) {
3893 if (mVerticalScrollbarPosition != position) {
3894 mVerticalScrollbarPosition = position;
3895 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -07003896 resolvePadding();
Adam Powell20232d02010-12-08 21:08:53 -08003897 }
3898 }
3899
3900 /**
3901 * @return The position where the vertical scroll bar will show, if applicable.
3902 * @see #setVerticalScrollbarPosition(int)
3903 */
3904 public int getVerticalScrollbarPosition() {
3905 return mVerticalScrollbarPosition;
3906 }
3907
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003908 ListenerInfo getListenerInfo() {
3909 if (mListenerInfo != null) {
3910 return mListenerInfo;
3911 }
3912 mListenerInfo = new ListenerInfo();
3913 return mListenerInfo;
3914 }
3915
Adam Powell20232d02010-12-08 21:08:53 -08003916 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003917 * Register a callback to be invoked when focus of this view changed.
3918 *
3919 * @param l The callback that will run.
3920 */
3921 public void setOnFocusChangeListener(OnFocusChangeListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003922 getListenerInfo().mOnFocusChangeListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003923 }
3924
3925 /**
Chet Haase21cd1382010-09-01 17:42:29 -07003926 * Add a listener that will be called when the bounds of the view change due to
3927 * layout processing.
3928 *
3929 * @param listener The listener that will be called when layout bounds change.
3930 */
3931 public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003932 ListenerInfo li = getListenerInfo();
3933 if (li.mOnLayoutChangeListeners == null) {
3934 li.mOnLayoutChangeListeners = new ArrayList<OnLayoutChangeListener>();
Chet Haase21cd1382010-09-01 17:42:29 -07003935 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003936 if (!li.mOnLayoutChangeListeners.contains(listener)) {
3937 li.mOnLayoutChangeListeners.add(listener);
Chet Haase1a76dcd2011-10-06 11:16:40 -07003938 }
Chet Haase21cd1382010-09-01 17:42:29 -07003939 }
3940
3941 /**
3942 * Remove a listener for layout changes.
3943 *
3944 * @param listener The listener for layout bounds change.
3945 */
3946 public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003947 ListenerInfo li = mListenerInfo;
3948 if (li == null || li.mOnLayoutChangeListeners == null) {
Chet Haase21cd1382010-09-01 17:42:29 -07003949 return;
3950 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003951 li.mOnLayoutChangeListeners.remove(listener);
Chet Haase21cd1382010-09-01 17:42:29 -07003952 }
3953
3954 /**
Adam Powell4afd62b2011-02-18 15:02:18 -08003955 * Add a listener for attach state changes.
3956 *
3957 * This listener will be called whenever this view is attached or detached
3958 * from a window. Remove the listener using
3959 * {@link #removeOnAttachStateChangeListener(OnAttachStateChangeListener)}.
3960 *
3961 * @param listener Listener to attach
3962 * @see #removeOnAttachStateChangeListener(OnAttachStateChangeListener)
3963 */
3964 public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003965 ListenerInfo li = getListenerInfo();
3966 if (li.mOnAttachStateChangeListeners == null) {
3967 li.mOnAttachStateChangeListeners
3968 = new CopyOnWriteArrayList<OnAttachStateChangeListener>();
Adam Powell4afd62b2011-02-18 15:02:18 -08003969 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003970 li.mOnAttachStateChangeListeners.add(listener);
Adam Powell4afd62b2011-02-18 15:02:18 -08003971 }
3972
3973 /**
3974 * Remove a listener for attach state changes. The listener will receive no further
3975 * notification of window attach/detach events.
3976 *
3977 * @param listener Listener to remove
3978 * @see #addOnAttachStateChangeListener(OnAttachStateChangeListener)
3979 */
3980 public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003981 ListenerInfo li = mListenerInfo;
3982 if (li == null || li.mOnAttachStateChangeListeners == null) {
Adam Powell4afd62b2011-02-18 15:02:18 -08003983 return;
3984 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003985 li.mOnAttachStateChangeListeners.remove(listener);
Adam Powell4afd62b2011-02-18 15:02:18 -08003986 }
3987
3988 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003989 * Returns the focus-change callback registered for this view.
3990 *
3991 * @return The callback, or null if one is not registered.
3992 */
3993 public OnFocusChangeListener getOnFocusChangeListener() {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07003994 ListenerInfo li = mListenerInfo;
3995 return li != null ? li.mOnFocusChangeListener : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08003996 }
3997
3998 /**
3999 * Register a callback to be invoked when this view is clicked. If this view is not
4000 * clickable, it becomes clickable.
4001 *
4002 * @param l The callback that will run
4003 *
4004 * @see #setClickable(boolean)
4005 */
4006 public void setOnClickListener(OnClickListener l) {
4007 if (!isClickable()) {
4008 setClickable(true);
4009 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004010 getListenerInfo().mOnClickListener = l;
4011 }
4012
4013 /**
4014 * Return whether this view has an attached OnClickListener. Returns
4015 * true if there is a listener, false if there is none.
4016 */
4017 public boolean hasOnClickListeners() {
4018 ListenerInfo li = mListenerInfo;
4019 return (li != null && li.mOnClickListener != null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004020 }
4021
4022 /**
4023 * Register a callback to be invoked when this view is clicked and held. If this view is not
4024 * long clickable, it becomes long clickable.
4025 *
4026 * @param l The callback that will run
4027 *
4028 * @see #setLongClickable(boolean)
4029 */
4030 public void setOnLongClickListener(OnLongClickListener l) {
4031 if (!isLongClickable()) {
4032 setLongClickable(true);
4033 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004034 getListenerInfo().mOnLongClickListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004035 }
4036
4037 /**
4038 * Register a callback to be invoked when the context menu for this view is
4039 * being built. If this view is not long clickable, it becomes long clickable.
4040 *
4041 * @param l The callback that will run
4042 *
4043 */
4044 public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
4045 if (!isLongClickable()) {
4046 setLongClickable(true);
4047 }
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004048 getListenerInfo().mOnCreateContextMenuListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004049 }
4050
4051 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004052 * Call this view's OnClickListener, if it is defined. Performs all normal
4053 * actions associated with clicking: reporting accessibility event, playing
4054 * a sound, etc.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004055 *
4056 * @return True there was an assigned OnClickListener that was called, false
4057 * otherwise is returned.
4058 */
4059 public boolean performClick() {
svetoslavganov75986cf2009-05-14 22:28:01 -07004060 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
4061
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004062 ListenerInfo li = mListenerInfo;
4063 if (li != null && li.mOnClickListener != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004064 playSoundEffect(SoundEffectConstants.CLICK);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004065 li.mOnClickListener.onClick(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004066 return true;
4067 }
4068
4069 return false;
4070 }
4071
4072 /**
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004073 * Directly call any attached OnClickListener. Unlike {@link #performClick()},
4074 * this only calls the listener, and does not do any associated clicking
4075 * actions like reporting an accessibility event.
4076 *
4077 * @return True there was an assigned OnClickListener that was called, false
4078 * otherwise is returned.
4079 */
4080 public boolean callOnClick() {
4081 ListenerInfo li = mListenerInfo;
4082 if (li != null && li.mOnClickListener != null) {
4083 li.mOnClickListener.onClick(this);
4084 return true;
4085 }
4086 return false;
4087 }
4088
4089 /**
Gilles Debunnef788a9f2010-07-22 10:17:23 -07004090 * Call this view's OnLongClickListener, if it is defined. Invokes the context menu if the
4091 * OnLongClickListener did not consume the event.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004092 *
Gilles Debunnef788a9f2010-07-22 10:17:23 -07004093 * @return True if one of the above receivers consumed the event, false otherwise.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004094 */
4095 public boolean performLongClick() {
svetoslavganov75986cf2009-05-14 22:28:01 -07004096 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
4097
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004098 boolean handled = false;
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004099 ListenerInfo li = mListenerInfo;
4100 if (li != null && li.mOnLongClickListener != null) {
4101 handled = li.mOnLongClickListener.onLongClick(View.this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004102 }
4103 if (!handled) {
4104 handled = showContextMenu();
4105 }
4106 if (handled) {
4107 performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
4108 }
4109 return handled;
4110 }
4111
4112 /**
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004113 * Performs button-related actions during a touch down event.
4114 *
4115 * @param event The event.
4116 * @return True if the down was consumed.
4117 *
4118 * @hide
4119 */
4120 protected boolean performButtonActionOnTouchDown(MotionEvent event) {
4121 if ((event.getButtonState() & MotionEvent.BUTTON_SECONDARY) != 0) {
4122 if (showContextMenu(event.getX(), event.getY(), event.getMetaState())) {
4123 return true;
4124 }
4125 }
4126 return false;
4127 }
4128
4129 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004130 * Bring up the context menu for this view.
4131 *
4132 * @return Whether a context menu was displayed.
4133 */
4134 public boolean showContextMenu() {
4135 return getParent().showContextMenuForChild(this);
4136 }
4137
4138 /**
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004139 * Bring up the context menu for this view, referring to the item under the specified point.
4140 *
4141 * @param x The referenced x coordinate.
4142 * @param y The referenced y coordinate.
4143 * @param metaState The keyboard modifiers that were pressed.
4144 * @return Whether a context menu was displayed.
4145 *
4146 * @hide
4147 */
4148 public boolean showContextMenu(float x, float y, int metaState) {
4149 return showContextMenu();
4150 }
4151
4152 /**
Adam Powell6e346362010-07-23 10:18:23 -07004153 * Start an action mode.
4154 *
4155 * @param callback Callback that will control the lifecycle of the action mode
4156 * @return The new action mode if it is started, null otherwise
4157 *
4158 * @see ActionMode
4159 */
4160 public ActionMode startActionMode(ActionMode.Callback callback) {
John Reck5160e2a2012-02-22 09:35:12 -08004161 ViewParent parent = getParent();
4162 if (parent == null) return null;
4163 return parent.startActionModeForChild(this, callback);
Adam Powell6e346362010-07-23 10:18:23 -07004164 }
4165
4166 /**
Jean Chalard405bc512012-05-29 19:12:34 +09004167 * Register a callback to be invoked when a hardware key is pressed in this view.
4168 * Key presses in software input methods will generally not trigger the methods of
4169 * this listener.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004170 * @param l the key listener to attach to this view
4171 */
4172 public void setOnKeyListener(OnKeyListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004173 getListenerInfo().mOnKeyListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004174 }
4175
4176 /**
4177 * Register a callback to be invoked when a touch event is sent to this view.
4178 * @param l the touch listener to attach to this view
4179 */
4180 public void setOnTouchListener(OnTouchListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004181 getListenerInfo().mOnTouchListener = l;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004182 }
4183
4184 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08004185 * Register a callback to be invoked when a generic motion event is sent to this view.
4186 * @param l the generic motion listener to attach to this view
4187 */
4188 public void setOnGenericMotionListener(OnGenericMotionListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004189 getListenerInfo().mOnGenericMotionListener = l;
Jeff Brown33bbfd22011-02-24 20:55:35 -08004190 }
4191
4192 /**
Jeff Brown53ca3f12011-06-27 18:36:00 -07004193 * Register a callback to be invoked when a hover event is sent to this view.
4194 * @param l the hover listener to attach to this view
4195 */
4196 public void setOnHoverListener(OnHoverListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004197 getListenerInfo().mOnHoverListener = l;
Jeff Brown53ca3f12011-06-27 18:36:00 -07004198 }
4199
4200 /**
Joe Malin32736f02011-01-19 16:14:20 -08004201 * Register a drag event listener callback object for this View. The parameter is
4202 * an implementation of {@link android.view.View.OnDragListener}. To send a drag event to a
4203 * View, the system calls the
4204 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent)} method.
4205 * @param l An implementation of {@link android.view.View.OnDragListener}.
Chris Tate32affef2010-10-18 15:29:21 -07004206 */
4207 public void setOnDragListener(OnDragListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004208 getListenerInfo().mOnDragListener = l;
Chris Tate32affef2010-10-18 15:29:21 -07004209 }
4210
4211 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -07004212 * Give this view focus. This will cause
4213 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} to be called.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004214 *
4215 * Note: this does not check whether this {@link View} should get focus, it just
4216 * gives it focus no matter what. It should only be called internally by framework
4217 * code that knows what it is doing, namely {@link #requestFocus(int, Rect)}.
4218 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08004219 * @param direction values are {@link View#FOCUS_UP}, {@link View#FOCUS_DOWN},
4220 * {@link View#FOCUS_LEFT} or {@link View#FOCUS_RIGHT}. This is the direction which
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004221 * focus moved when requestFocus() is called. It may not always
4222 * apply, in which case use the default View.FOCUS_DOWN.
4223 * @param previouslyFocusedRect The rectangle of the view that had focus
4224 * prior in this View's coordinate system.
4225 */
4226 void handleFocusGainInternal(int direction, Rect previouslyFocusedRect) {
4227 if (DBG) {
4228 System.out.println(this + " requestFocus()");
4229 }
4230
Dianne Hackborn4702a852012-08-17 15:18:29 -07004231 if ((mPrivateFlags & PFLAG_FOCUSED) == 0) {
4232 mPrivateFlags |= PFLAG_FOCUSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004233
4234 if (mParent != null) {
4235 mParent.requestChildFocus(this, this);
4236 }
4237
4238 onFocusChanged(true, direction, previouslyFocusedRect);
4239 refreshDrawableState();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004240
4241 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4242 notifyAccessibilityStateChanged();
4243 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004244 }
4245 }
4246
4247 /**
4248 * Request that a rectangle of this view be visible on the screen,
4249 * scrolling if necessary just enough.
4250 *
4251 * <p>A View should call this if it maintains some notion of which part
4252 * of its content is interesting. For example, a text editing view
4253 * should call this when its cursor moves.
4254 *
4255 * @param rectangle The rectangle.
4256 * @return Whether any parent scrolled.
4257 */
4258 public boolean requestRectangleOnScreen(Rect rectangle) {
4259 return requestRectangleOnScreen(rectangle, false);
4260 }
4261
4262 /**
4263 * Request that a rectangle of this view be visible on the screen,
4264 * scrolling if necessary just enough.
4265 *
4266 * <p>A View should call this if it maintains some notion of which part
4267 * of its content is interesting. For example, a text editing view
4268 * should call this when its cursor moves.
4269 *
4270 * <p>When <code>immediate</code> is set to true, scrolling will not be
4271 * animated.
4272 *
4273 * @param rectangle The rectangle.
4274 * @param immediate True to forbid animated scrolling, false otherwise
4275 * @return Whether any parent scrolled.
4276 */
4277 public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
4278 View child = this;
4279 ViewParent parent = mParent;
4280 boolean scrolled = false;
4281 while (parent != null) {
4282 scrolled |= parent.requestChildRectangleOnScreen(child,
4283 rectangle, immediate);
4284
4285 // offset rect so next call has the rectangle in the
4286 // coordinate system of its direct child.
4287 rectangle.offset(child.getLeft(), child.getTop());
4288 rectangle.offset(-child.getScrollX(), -child.getScrollY());
4289
4290 if (!(parent instanceof View)) {
4291 break;
4292 }
Romain Guy8506ab42009-06-11 17:35:47 -07004293
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004294 child = (View) parent;
4295 parent = child.getParent();
4296 }
4297 return scrolled;
4298 }
4299
4300 /**
Svetoslav Ganov13fd5612012-02-01 17:01:12 -08004301 * Called when this view wants to give up focus. If focus is cleared
4302 * {@link #onFocusChanged(boolean, int, android.graphics.Rect)} is called.
4303 * <p>
4304 * <strong>Note:</strong> When a View clears focus the framework is trying
4305 * to give focus to the first focusable View from the top. Hence, if this
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004306 * View is the first from the top that can take focus, then all callbacks
4307 * related to clearing focus will be invoked after wich the framework will
4308 * give focus to this view.
Svetoslav Ganov13fd5612012-02-01 17:01:12 -08004309 * </p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004310 */
4311 public void clearFocus() {
4312 if (DBG) {
4313 System.out.println(this + " clearFocus()");
4314 }
4315
Dianne Hackborn4702a852012-08-17 15:18:29 -07004316 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4317 mPrivateFlags &= ~PFLAG_FOCUSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004318
4319 if (mParent != null) {
4320 mParent.clearChildFocus(this);
4321 }
4322
4323 onFocusChanged(false, 0, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07004324
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004325 refreshDrawableState();
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004326
4327 ensureInputFocusOnFirstFocusable();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004328
4329 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4330 notifyAccessibilityStateChanged();
4331 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004332 }
4333 }
4334
Svetoslav Ganov57cadf22012-04-04 16:44:39 -07004335 void ensureInputFocusOnFirstFocusable() {
4336 View root = getRootView();
4337 if (root != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004338 root.requestFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004339 }
4340 }
4341
4342 /**
4343 * Called internally by the view system when a new view is getting focus.
4344 * This is what clears the old focus.
4345 */
4346 void unFocus() {
4347 if (DBG) {
4348 System.out.println(this + " unFocus()");
4349 }
4350
Dianne Hackborn4702a852012-08-17 15:18:29 -07004351 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
4352 mPrivateFlags &= ~PFLAG_FOCUSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004353
4354 onFocusChanged(false, 0, null);
4355 refreshDrawableState();
Svetoslav Ganov42138042012-03-20 11:51:39 -07004356
4357 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4358 notifyAccessibilityStateChanged();
4359 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004360 }
4361 }
4362
4363 /**
4364 * Returns true if this view has focus iteself, or is the ancestor of the
4365 * view that has focus.
4366 *
4367 * @return True if this view has or contains focus, false otherwise.
4368 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07004369 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004370 public boolean hasFocus() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07004371 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004372 }
4373
4374 /**
4375 * Returns true if this view is focusable or if it contains a reachable View
4376 * for which {@link #hasFocusable()} returns true. A "reachable hasFocusable()"
4377 * is a View whose parents do not block descendants focus.
4378 *
4379 * Only {@link #VISIBLE} views are considered focusable.
4380 *
4381 * @return True if the view is focusable or if the view contains a focusable
4382 * View, false otherwise.
4383 *
4384 * @see ViewGroup#FOCUS_BLOCK_DESCENDANTS
4385 */
4386 public boolean hasFocusable() {
4387 return (mViewFlags & VISIBILITY_MASK) == VISIBLE && isFocusable();
4388 }
4389
4390 /**
4391 * Called by the view system when the focus state of this view changes.
4392 * When the focus change event is caused by directional navigation, direction
4393 * and previouslyFocusedRect provide insight into where the focus is coming from.
4394 * When overriding, be sure to call up through to the super class so that
4395 * the standard focus handling will occur.
Romain Guy8506ab42009-06-11 17:35:47 -07004396 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004397 * @param gainFocus True if the View has focus; false otherwise.
4398 * @param direction The direction focus has moved when requestFocus()
4399 * is called to give this view focus. Values are
Jeff Brown4e6319b2010-12-13 10:36:51 -08004400 * {@link #FOCUS_UP}, {@link #FOCUS_DOWN}, {@link #FOCUS_LEFT},
4401 * {@link #FOCUS_RIGHT}, {@link #FOCUS_FORWARD}, or {@link #FOCUS_BACKWARD}.
4402 * It may not always apply, in which case use the default.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004403 * @param previouslyFocusedRect The rectangle, in this view's coordinate
4404 * system, of the previously focused view. If applicable, this will be
4405 * passed in as finer grained information about where the focus is coming
4406 * from (in addition to direction). Will be <code>null</code> otherwise.
4407 */
4408 protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
svetoslavganov75986cf2009-05-14 22:28:01 -07004409 if (gainFocus) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004410 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4411 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_FOCUSED);
Svetoslav Ganov42138042012-03-20 11:51:39 -07004412 }
svetoslavganov75986cf2009-05-14 22:28:01 -07004413 }
4414
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004415 InputMethodManager imm = InputMethodManager.peekInstance();
4416 if (!gainFocus) {
4417 if (isPressed()) {
4418 setPressed(false);
4419 }
4420 if (imm != null && mAttachInfo != null
4421 && mAttachInfo.mHasWindowFocus) {
4422 imm.focusOut(this);
4423 }
Romain Guya2431d02009-04-30 16:30:00 -07004424 onFocusLost();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004425 } else if (imm != null && mAttachInfo != null
4426 && mAttachInfo.mHasWindowFocus) {
4427 imm.focusIn(this);
4428 }
Romain Guy8506ab42009-06-11 17:35:47 -07004429
Romain Guy0fd89bf2011-01-26 15:41:30 -08004430 invalidate(true);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07004431 ListenerInfo li = mListenerInfo;
4432 if (li != null && li.mOnFocusChangeListener != null) {
4433 li.mOnFocusChangeListener.onFocusChange(this, gainFocus);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004434 }
Joe Malin32736f02011-01-19 16:14:20 -08004435
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07004436 if (mAttachInfo != null) {
4437 mAttachInfo.mKeyDispatchState.reset(this);
4438 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08004439 }
4440
4441 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004442 * Sends an accessibility event of the given type. If accessiiblity is
4443 * not enabled this method has no effect. The default implementation calls
4444 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)} first
4445 * to populate information about the event source (this View), then calls
4446 * {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)} to
4447 * populate the text content of the event source including its descendants,
4448 * and last calls
4449 * {@link ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)}
4450 * on its parent to resuest sending of the event to interested parties.
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004451 * <p>
4452 * If an {@link AccessibilityDelegate} has been specified via calling
4453 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4454 * {@link AccessibilityDelegate#sendAccessibilityEvent(View, int)} is
4455 * responsible for handling this call.
4456 * </p>
Svetoslav Ganov30401322011-05-12 18:53:45 -07004457 *
Scott Mainb303d832011-10-12 16:45:18 -07004458 * @param eventType The type of the event to send, as defined by several types from
4459 * {@link android.view.accessibility.AccessibilityEvent}, such as
4460 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_CLICKED} or
4461 * {@link android.view.accessibility.AccessibilityEvent#TYPE_VIEW_HOVER_ENTER}.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004462 *
4463 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4464 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4465 * @see ViewParent#requestSendAccessibilityEvent(View, AccessibilityEvent)
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004466 * @see AccessibilityDelegate
svetoslavganov75986cf2009-05-14 22:28:01 -07004467 */
4468 public void sendAccessibilityEvent(int eventType) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004469 if (mAccessibilityDelegate != null) {
4470 mAccessibilityDelegate.sendAccessibilityEvent(this, eventType);
4471 } else {
4472 sendAccessibilityEventInternal(eventType);
4473 }
4474 }
4475
4476 /**
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004477 * Convenience method for sending a {@link AccessibilityEvent#TYPE_ANNOUNCEMENT}
4478 * {@link AccessibilityEvent} to make an announcement which is related to some
4479 * sort of a context change for which none of the events representing UI transitions
4480 * is a good fit. For example, announcing a new page in a book. If accessibility
4481 * is not enabled this method does nothing.
4482 *
4483 * @param text The announcement text.
4484 */
4485 public void announceForAccessibility(CharSequence text) {
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004486 if (AccessibilityManager.getInstance(mContext).isEnabled() && mParent != null) {
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004487 AccessibilityEvent event = AccessibilityEvent.obtain(
4488 AccessibilityEvent.TYPE_ANNOUNCEMENT);
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004489 onInitializeAccessibilityEvent(event);
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004490 event.getText().add(text);
Svetoslav Ganov7a82b2b2012-07-02 18:33:23 -07004491 event.setContentDescription(null);
4492 mParent.requestSendAccessibilityEvent(this, event);
Svetoslav Ganov51ab90c2012-03-09 10:54:49 -08004493 }
4494 }
4495
4496 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004497 * @see #sendAccessibilityEvent(int)
4498 *
4499 * Note: Called from the default {@link AccessibilityDelegate}.
4500 */
4501 void sendAccessibilityEventInternal(int eventType) {
svetoslavganov75986cf2009-05-14 22:28:01 -07004502 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
4503 sendAccessibilityEventUnchecked(AccessibilityEvent.obtain(eventType));
4504 }
4505 }
4506
4507 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004508 * This method behaves exactly as {@link #sendAccessibilityEvent(int)} but
4509 * takes as an argument an empty {@link AccessibilityEvent} and does not
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004510 * perform a check whether accessibility is enabled.
4511 * <p>
4512 * If an {@link AccessibilityDelegate} has been specified via calling
4513 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4514 * {@link AccessibilityDelegate#sendAccessibilityEventUnchecked(View, AccessibilityEvent)}
4515 * is responsible for handling this call.
4516 * </p>
Svetoslav Ganov30401322011-05-12 18:53:45 -07004517 *
4518 * @param event The event to send.
4519 *
4520 * @see #sendAccessibilityEvent(int)
svetoslavganov75986cf2009-05-14 22:28:01 -07004521 */
4522 public void sendAccessibilityEventUnchecked(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004523 if (mAccessibilityDelegate != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004524 mAccessibilityDelegate.sendAccessibilityEventUnchecked(this, event);
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004525 } else {
4526 sendAccessibilityEventUncheckedInternal(event);
4527 }
4528 }
4529
4530 /**
4531 * @see #sendAccessibilityEventUnchecked(AccessibilityEvent)
4532 *
4533 * Note: Called from the default {@link AccessibilityDelegate}.
4534 */
4535 void sendAccessibilityEventUncheckedInternal(AccessibilityEvent event) {
Svetoslav Ganov9cd1eca2011-01-13 14:24:02 -08004536 if (!isShown()) {
4537 return;
4538 }
Svetoslav Ganov30401322011-05-12 18:53:45 -07004539 onInitializeAccessibilityEvent(event);
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07004540 // Only a subset of accessibility events populates text content.
4541 if ((event.getEventType() & POPULATING_ACCESSIBILITY_EVENT_TYPES) != 0) {
4542 dispatchPopulateAccessibilityEvent(event);
4543 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004544 // In the beginning we called #isShown(), so we know that getParent() is not null.
4545 getParent().requestSendAccessibilityEvent(this, event);
svetoslavganov75986cf2009-05-14 22:28:01 -07004546 }
4547
4548 /**
Svetoslav Ganov30401322011-05-12 18:53:45 -07004549 * Dispatches an {@link AccessibilityEvent} to the {@link View} first and then
4550 * to its children for adding their text content to the event. Note that the
4551 * event text is populated in a separate dispatch path since we add to the
4552 * event not only the text of the source but also the text of all its descendants.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004553 * A typical implementation will call
4554 * {@link #onPopulateAccessibilityEvent(AccessibilityEvent)} on the this view
4555 * and then call the {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
4556 * on each child. Override this method if custom population of the event text
4557 * content is required.
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004558 * <p>
4559 * If an {@link AccessibilityDelegate} has been specified via calling
4560 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4561 * {@link AccessibilityDelegate#dispatchPopulateAccessibilityEvent(View, AccessibilityEvent)}
4562 * is responsible for handling this call.
4563 * </p>
Svetoslav Ganov82e236d2011-09-29 19:31:06 -07004564 * <p>
4565 * <em>Note:</em> Accessibility events of certain types are not dispatched for
4566 * populating the event text via this method. For details refer to {@link AccessibilityEvent}.
4567 * </p>
svetoslavganov75986cf2009-05-14 22:28:01 -07004568 *
4569 * @param event The event.
4570 *
4571 * @return True if the event population was completed.
4572 */
4573 public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004574 if (mAccessibilityDelegate != null) {
4575 return mAccessibilityDelegate.dispatchPopulateAccessibilityEvent(this, event);
4576 } else {
4577 return dispatchPopulateAccessibilityEventInternal(event);
4578 }
4579 }
4580
4581 /**
4582 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4583 *
4584 * Note: Called from the default {@link AccessibilityDelegate}.
4585 */
4586 boolean dispatchPopulateAccessibilityEventInternal(AccessibilityEvent event) {
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004587 onPopulateAccessibilityEvent(event);
svetoslavganov75986cf2009-05-14 22:28:01 -07004588 return false;
4589 }
4590
4591 /**
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004592 * Called from {@link #dispatchPopulateAccessibilityEvent(AccessibilityEvent)}
Svetoslav Ganov30401322011-05-12 18:53:45 -07004593 * giving a chance to this View to populate the accessibility event with its
Scott Mainb303d832011-10-12 16:45:18 -07004594 * text content. While this method is free to modify event
4595 * attributes other than text content, doing so should normally be performed in
Svetoslav Ganov30401322011-05-12 18:53:45 -07004596 * {@link #onInitializeAccessibilityEvent(AccessibilityEvent)}.
4597 * <p>
4598 * Example: Adding formatted date string to an accessibility event in addition
Scott Mainb303d832011-10-12 16:45:18 -07004599 * to the text added by the super implementation:
4600 * <pre> public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov30401322011-05-12 18:53:45 -07004601 * super.onPopulateAccessibilityEvent(event);
4602 * final int flags = DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_WEEKDAY;
4603 * String selectedDateUtterance = DateUtils.formatDateTime(mContext,
4604 * mCurrentDate.getTimeInMillis(), flags);
4605 * event.getText().add(selectedDateUtterance);
Scott Mainb303d832011-10-12 16:45:18 -07004606 * }</pre>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004607 * <p>
4608 * If an {@link AccessibilityDelegate} has been specified via calling
4609 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4610 * {@link AccessibilityDelegate#onPopulateAccessibilityEvent(View, AccessibilityEvent)}
4611 * is responsible for handling this call.
4612 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07004613 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4614 * information to the event, in case the default implementation has basic information to add.
4615 * </p>
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004616 *
4617 * @param event The accessibility event which to populate.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004618 *
4619 * @see #sendAccessibilityEvent(int)
4620 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004621 */
4622 public void onPopulateAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004623 if (mAccessibilityDelegate != null) {
4624 mAccessibilityDelegate.onPopulateAccessibilityEvent(this, event);
4625 } else {
4626 onPopulateAccessibilityEventInternal(event);
4627 }
Svetoslav Ganov736c2752011-04-22 18:30:36 -07004628 }
4629
4630 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004631 * @see #onPopulateAccessibilityEvent(AccessibilityEvent)
4632 *
4633 * Note: Called from the default {@link AccessibilityDelegate}.
4634 */
4635 void onPopulateAccessibilityEventInternal(AccessibilityEvent event) {
4636
4637 }
4638
4639 /**
4640 * Initializes an {@link AccessibilityEvent} with information about
4641 * this View which is the event source. In other words, the source of
4642 * an accessibility event is the view whose state change triggered firing
4643 * the event.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004644 * <p>
4645 * Example: Setting the password property of an event in addition
Scott Mainb303d832011-10-12 16:45:18 -07004646 * to properties set by the super implementation:
4647 * <pre> public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
4648 * super.onInitializeAccessibilityEvent(event);
4649 * event.setPassword(true);
4650 * }</pre>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004651 * <p>
4652 * If an {@link AccessibilityDelegate} has been specified via calling
4653 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4654 * {@link AccessibilityDelegate#onInitializeAccessibilityEvent(View, AccessibilityEvent)}
4655 * is responsible for handling this call.
4656 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07004657 * <p class="note"><strong>Note:</strong> Always call the super implementation before adding
4658 * information to the event, in case the default implementation has basic information to add.
4659 * </p>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004660 * @param event The event to initialize.
Svetoslav Ganov30401322011-05-12 18:53:45 -07004661 *
4662 * @see #sendAccessibilityEvent(int)
4663 * @see #dispatchPopulateAccessibilityEvent(AccessibilityEvent)
4664 */
4665 public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004666 if (mAccessibilityDelegate != null) {
4667 mAccessibilityDelegate.onInitializeAccessibilityEvent(this, event);
4668 } else {
4669 onInitializeAccessibilityEventInternal(event);
4670 }
4671 }
4672
4673 /**
4674 * @see #onInitializeAccessibilityEvent(AccessibilityEvent)
4675 *
4676 * Note: Called from the default {@link AccessibilityDelegate}.
4677 */
4678 void onInitializeAccessibilityEventInternal(AccessibilityEvent event) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004679 event.setSource(this);
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08004680 event.setClassName(View.class.getName());
Svetoslav Ganov30401322011-05-12 18:53:45 -07004681 event.setPackageName(getContext().getPackageName());
4682 event.setEnabled(isEnabled());
4683 event.setContentDescription(mContentDescription);
4684
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -07004685 if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED && mAttachInfo != null) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07004686 ArrayList<View> focusablesTempList = mAttachInfo.mTempArrayList;
Svetoslav Ganovd9ee72f2011-10-05 22:26:05 -07004687 getRootView().addFocusables(focusablesTempList, View.FOCUS_FORWARD,
4688 FOCUSABLES_ALL);
4689 event.setItemCount(focusablesTempList.size());
4690 event.setCurrentItemIndex(focusablesTempList.indexOf(this));
4691 focusablesTempList.clear();
Svetoslav Ganov30401322011-05-12 18:53:45 -07004692 }
4693 }
4694
4695 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004696 * Returns an {@link AccessibilityNodeInfo} representing this view from the
4697 * point of view of an {@link android.accessibilityservice.AccessibilityService}.
4698 * This method is responsible for obtaining an accessibility node info from a
4699 * pool of reusable instances and calling
4700 * {@link #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} on this view to
4701 * initialize the former.
4702 * <p>
4703 * Note: The client is responsible for recycling the obtained instance by calling
4704 * {@link AccessibilityNodeInfo#recycle()} to minimize object creation.
4705 * </p>
Svetoslav Ganov02107852011-10-03 17:06:56 -07004706 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004707 * @return A populated {@link AccessibilityNodeInfo}.
4708 *
4709 * @see AccessibilityNodeInfo
4710 */
4711 public AccessibilityNodeInfo createAccessibilityNodeInfo() {
Svetoslav Ganov02107852011-10-03 17:06:56 -07004712 AccessibilityNodeProvider provider = getAccessibilityNodeProvider();
4713 if (provider != null) {
4714 return provider.createAccessibilityNodeInfo(View.NO_ID);
4715 } else {
4716 AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain(this);
4717 onInitializeAccessibilityNodeInfo(info);
4718 return info;
4719 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004720 }
4721
4722 /**
4723 * Initializes an {@link AccessibilityNodeInfo} with information about this view.
4724 * The base implementation sets:
4725 * <ul>
4726 * <li>{@link AccessibilityNodeInfo#setParent(View)},</li>
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004727 * <li>{@link AccessibilityNodeInfo#setBoundsInParent(Rect)},</li>
4728 * <li>{@link AccessibilityNodeInfo#setBoundsInScreen(Rect)},</li>
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004729 * <li>{@link AccessibilityNodeInfo#setPackageName(CharSequence)},</li>
4730 * <li>{@link AccessibilityNodeInfo#setClassName(CharSequence)},</li>
4731 * <li>{@link AccessibilityNodeInfo#setContentDescription(CharSequence)},</li>
4732 * <li>{@link AccessibilityNodeInfo#setEnabled(boolean)},</li>
4733 * <li>{@link AccessibilityNodeInfo#setClickable(boolean)},</li>
4734 * <li>{@link AccessibilityNodeInfo#setFocusable(boolean)},</li>
4735 * <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
4736 * <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
4737 * <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
4738 * </ul>
4739 * <p>
4740 * Subclasses should override this method, call the super implementation,
4741 * and set additional attributes.
4742 * </p>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004743 * <p>
4744 * If an {@link AccessibilityDelegate} has been specified via calling
4745 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4746 * {@link AccessibilityDelegate#onInitializeAccessibilityNodeInfo(View, AccessibilityNodeInfo)}
4747 * is responsible for handling this call.
4748 * </p>
4749 *
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004750 * @param info The instance to initialize.
4751 */
4752 public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004753 if (mAccessibilityDelegate != null) {
4754 mAccessibilityDelegate.onInitializeAccessibilityNodeInfo(this, info);
4755 } else {
4756 onInitializeAccessibilityNodeInfoInternal(info);
4757 }
4758 }
4759
4760 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004761 * Gets the location of this view in screen coordintates.
4762 *
4763 * @param outRect The output location
4764 */
4765 private void getBoundsOnScreen(Rect outRect) {
4766 if (mAttachInfo == null) {
4767 return;
4768 }
4769
4770 RectF position = mAttachInfo.mTmpTransformRect;
Svetoslav Ganov14b2b742012-05-08 16:36:34 -07004771 position.set(0, 0, mRight - mLeft, mBottom - mTop);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004772
4773 if (!hasIdentityMatrix()) {
4774 getMatrix().mapRect(position);
4775 }
4776
Svetoslav Ganov14b2b742012-05-08 16:36:34 -07004777 position.offset(mLeft, mTop);
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004778
4779 ViewParent parent = mParent;
4780 while (parent instanceof View) {
4781 View parentView = (View) parent;
4782
4783 position.offset(-parentView.mScrollX, -parentView.mScrollY);
4784
4785 if (!parentView.hasIdentityMatrix()) {
4786 parentView.getMatrix().mapRect(position);
4787 }
4788
4789 position.offset(parentView.mLeft, parentView.mTop);
4790
4791 parent = parentView.mParent;
4792 }
4793
4794 if (parent instanceof ViewRootImpl) {
4795 ViewRootImpl viewRootImpl = (ViewRootImpl) parent;
4796 position.offset(0, -viewRootImpl.mCurScrollY);
4797 }
4798
4799 position.offset(mAttachInfo.mWindowLeft, mAttachInfo.mWindowTop);
4800
4801 outRect.set((int) (position.left + 0.5f), (int) (position.top + 0.5f),
4802 (int) (position.right + 0.5f), (int) (position.bottom + 0.5f));
4803 }
4804
4805 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004806 * @see #onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
4807 *
4808 * Note: Called from the default {@link AccessibilityDelegate}.
4809 */
4810 void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004811 Rect bounds = mAttachInfo.mTmpInvalRect;
Svetoslav Ganov983119a2012-07-03 21:04:10 -07004812
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004813 getDrawingRect(bounds);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004814 info.setBoundsInParent(bounds);
4815
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004816 getBoundsOnScreen(bounds);
Svetoslav Ganoveeee4d22011-06-10 20:51:30 -07004817 info.setBoundsInScreen(bounds);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004818
Svetoslav Ganovc406be92012-05-11 16:12:32 -07004819 ViewParent parent = getParentForAccessibility();
4820 if (parent instanceof View) {
4821 info.setParent((View) parent);
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004822 }
4823
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004824 info.setVisibleToUser(isVisibleToUser());
4825
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004826 info.setPackageName(mContext.getPackageName());
Svetoslav Ganov8a78fd42012-01-17 14:36:46 -08004827 info.setClassName(View.class.getName());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004828 info.setContentDescription(getContentDescription());
4829
4830 info.setEnabled(isEnabled());
4831 info.setClickable(isClickable());
4832 info.setFocusable(isFocusable());
4833 info.setFocused(isFocused());
Svetoslav Ganov42138042012-03-20 11:51:39 -07004834 info.setAccessibilityFocused(isAccessibilityFocused());
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004835 info.setSelected(isSelected());
4836 info.setLongClickable(isLongClickable());
4837
4838 // TODO: These make sense only if we are in an AdapterView but all
4839 // views can be selected. Maybe from accessiiblity perspective
4840 // we should report as selectable view in an AdapterView.
4841 info.addAction(AccessibilityNodeInfo.ACTION_SELECT);
4842 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_SELECTION);
4843
4844 if (isFocusable()) {
4845 if (isFocused()) {
4846 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_FOCUS);
4847 } else {
4848 info.addAction(AccessibilityNodeInfo.ACTION_FOCUS);
4849 }
4850 }
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004851
Svetoslav Ganov02afe2c2012-05-07 17:51:59 -07004852 if (!isAccessibilityFocused()) {
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07004853 info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
Svetoslav Ganov02afe2c2012-05-07 17:51:59 -07004854 } else {
4855 info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
4856 }
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004857
Svetoslav Ganovfb1e80a2012-05-16 17:33:19 -07004858 if (isClickable() && isEnabled()) {
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004859 info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
4860 }
4861
Svetoslav Ganovfb1e80a2012-05-16 17:33:19 -07004862 if (isLongClickable() && isEnabled()) {
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004863 info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
4864 }
4865
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07004866 if (mContentDescription != null && mContentDescription.length() > 0) {
Svetoslav Ganov2b435aa2012-05-04 17:16:37 -07004867 info.addAction(AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY);
4868 info.addAction(AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY);
4869 info.setMovementGranularities(AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07004870 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD
4871 | AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH);
Svetoslav Ganovcfcff982012-04-28 15:31:09 -07004872 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004873 }
4874
4875 /**
Svetoslav Ganov0a1bb6d2012-05-07 11:54:39 -07004876 * Computes whether this view is visible to the user. Such a view is
4877 * attached, visible, all its predecessors are visible, it is not clipped
4878 * entirely by its predecessors, and has an alpha greater than zero.
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004879 *
4880 * @return Whether the view is visible on the screen.
Guang Zhu0d607fb2012-05-11 19:34:56 -07004881 *
4882 * @hide
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004883 */
Guang Zhu0d607fb2012-05-11 19:34:56 -07004884 protected boolean isVisibleToUser() {
4885 return isVisibleToUser(null);
4886 }
4887
4888 /**
Romain Guyf0af1d52012-07-11 18:31:21 -07004889 * Computes whether the given portion of this view is visible to the user.
4890 * Such a view is attached, visible, all its predecessors are visible,
4891 * has an alpha greater than zero, and the specified portion is not
4892 * clipped entirely by its predecessors.
Guang Zhu0d607fb2012-05-11 19:34:56 -07004893 *
4894 * @param boundInView the portion of the view to test; coordinates should be relative; may be
4895 * <code>null</code>, and the entire view will be tested in this case.
4896 * When <code>true</code> is returned by the function, the actual visible
4897 * region will be stored in this parameter; that is, if boundInView is fully
4898 * contained within the view, no modification will be made, otherwise regions
4899 * outside of the visible area of the view will be clipped.
4900 *
4901 * @return Whether the specified portion of the view is visible on the screen.
4902 *
4903 * @hide
4904 */
4905 protected boolean isVisibleToUser(Rect boundInView) {
Romain Guyf0af1d52012-07-11 18:31:21 -07004906 if (mAttachInfo != null) {
4907 Rect visibleRect = mAttachInfo.mTmpInvalRect;
4908 Point offset = mAttachInfo.mPoint;
4909 // The first two checks are made also made by isShown() which
4910 // however traverses the tree up to the parent to catch that.
4911 // Therefore, we do some fail fast check to minimize the up
4912 // tree traversal.
4913 boolean isVisible = mAttachInfo.mWindowVisibility == View.VISIBLE
4914 && getAlpha() > 0
4915 && isShown()
4916 && getGlobalVisibleRect(visibleRect, offset);
Guang Zhu0d607fb2012-05-11 19:34:56 -07004917 if (isVisible && boundInView != null) {
4918 visibleRect.offset(-offset.x, -offset.y);
Romain Guyf0af1d52012-07-11 18:31:21 -07004919 // isVisible is always true here, use a simple assignment
4920 isVisible = boundInView.intersect(visibleRect);
Guang Zhu0d607fb2012-05-11 19:34:56 -07004921 }
4922 return isVisible;
Romain Guyf0af1d52012-07-11 18:31:21 -07004923 }
4924
4925 return false;
Svetoslav Ganov749e7962012-04-19 17:13:46 -07004926 }
4927
4928 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -07004929 * Sets a delegate for implementing accessibility support via compositon as
4930 * opposed to inheritance. The delegate's primary use is for implementing
4931 * backwards compatible widgets. For more details see {@link AccessibilityDelegate}.
4932 *
4933 * @param delegate The delegate instance.
4934 *
4935 * @see AccessibilityDelegate
4936 */
4937 public void setAccessibilityDelegate(AccessibilityDelegate delegate) {
4938 mAccessibilityDelegate = delegate;
4939 }
4940
4941 /**
Svetoslav Ganov02107852011-10-03 17:06:56 -07004942 * Gets the provider for managing a virtual view hierarchy rooted at this View
4943 * and reported to {@link android.accessibilityservice.AccessibilityService}s
4944 * that explore the window content.
4945 * <p>
4946 * If this method returns an instance, this instance is responsible for managing
4947 * {@link AccessibilityNodeInfo}s describing the virtual sub-tree rooted at this
4948 * View including the one representing the View itself. Similarly the returned
4949 * instance is responsible for performing accessibility actions on any virtual
4950 * view or the root view itself.
4951 * </p>
4952 * <p>
4953 * If an {@link AccessibilityDelegate} has been specified via calling
4954 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
4955 * {@link AccessibilityDelegate#getAccessibilityNodeProvider(View)}
4956 * is responsible for handling this call.
4957 * </p>
4958 *
4959 * @return The provider.
4960 *
4961 * @see AccessibilityNodeProvider
4962 */
4963 public AccessibilityNodeProvider getAccessibilityNodeProvider() {
4964 if (mAccessibilityDelegate != null) {
4965 return mAccessibilityDelegate.getAccessibilityNodeProvider(this);
4966 } else {
4967 return null;
4968 }
4969 }
4970
4971 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07004972 * Gets the unique identifier of this view on the screen for accessibility purposes.
4973 * If this {@link View} is not attached to any window, {@value #NO_ID} is returned.
4974 *
4975 * @return The view accessibility id.
4976 *
4977 * @hide
4978 */
4979 public int getAccessibilityViewId() {
4980 if (mAccessibilityViewId == NO_ID) {
4981 mAccessibilityViewId = sNextAccessibilityViewId++;
4982 }
4983 return mAccessibilityViewId;
4984 }
4985
4986 /**
4987 * Gets the unique identifier of the window in which this View reseides.
4988 *
4989 * @return The window accessibility id.
4990 *
4991 * @hide
4992 */
4993 public int getAccessibilityWindowId() {
4994 return mAttachInfo != null ? mAttachInfo.mAccessibilityWindowId : NO_ID;
4995 }
4996
4997 /**
svetoslavganov75986cf2009-05-14 22:28:01 -07004998 * Gets the {@link View} description. It briefly describes the view and is
4999 * primarily used for accessibility support. Set this property to enable
5000 * better accessibility support for your application. This is especially
5001 * true for views that do not have textual representation (For example,
5002 * ImageButton).
5003 *
Svetoslav Ganov42138042012-03-20 11:51:39 -07005004 * @return The content description.
svetoslavganov75986cf2009-05-14 22:28:01 -07005005 *
5006 * @attr ref android.R.styleable#View_contentDescription
5007 */
Svetoslav Ganov42138042012-03-20 11:51:39 -07005008 @ViewDebug.ExportedProperty(category = "accessibility")
svetoslavganov75986cf2009-05-14 22:28:01 -07005009 public CharSequence getContentDescription() {
5010 return mContentDescription;
5011 }
5012
5013 /**
5014 * Sets the {@link View} description. It briefly describes the view and is
5015 * primarily used for accessibility support. Set this property to enable
5016 * better accessibility support for your application. This is especially
5017 * true for views that do not have textual representation (For example,
5018 * ImageButton).
5019 *
5020 * @param contentDescription The content description.
5021 *
5022 * @attr ref android.R.styleable#View_contentDescription
5023 */
Svetoslav Ganove261e282011-10-18 17:47:04 -07005024 @RemotableViewMethod
svetoslavganov75986cf2009-05-14 22:28:01 -07005025 public void setContentDescription(CharSequence contentDescription) {
5026 mContentDescription = contentDescription;
Svetoslav Ganove47957a2012-06-05 14:46:50 -07005027 final boolean nonEmptyDesc = contentDescription != null && contentDescription.length() > 0;
5028 if (nonEmptyDesc && getImportantForAccessibility() == IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
5029 setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
5030 }
svetoslavganov75986cf2009-05-14 22:28:01 -07005031 }
5032
5033 /**
Romain Guya2431d02009-04-30 16:30:00 -07005034 * Invoked whenever this view loses focus, either by losing window focus or by losing
5035 * focus within its window. This method can be used to clear any state tied to the
5036 * focus. For instance, if a button is held pressed with the trackball and the window
5037 * loses focus, this method can be used to cancel the press.
5038 *
5039 * Subclasses of View overriding this method should always call super.onFocusLost().
5040 *
5041 * @see #onFocusChanged(boolean, int, android.graphics.Rect)
Romain Guy8506ab42009-06-11 17:35:47 -07005042 * @see #onWindowFocusChanged(boolean)
Romain Guya2431d02009-04-30 16:30:00 -07005043 *
5044 * @hide pending API council approval
5045 */
5046 protected void onFocusLost() {
5047 resetPressedState();
5048 }
5049
5050 private void resetPressedState() {
5051 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
5052 return;
5053 }
5054
5055 if (isPressed()) {
5056 setPressed(false);
5057
5058 if (!mHasPerformedLongPress) {
Maryam Garrett1549dd12009-12-15 16:06:36 -05005059 removeLongPressCallback();
Romain Guya2431d02009-04-30 16:30:00 -07005060 }
5061 }
5062 }
5063
5064 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005065 * Returns true if this view has focus
5066 *
5067 * @return True if this view has focus, false otherwise.
5068 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005069 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005070 public boolean isFocused() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005071 return (mPrivateFlags & PFLAG_FOCUSED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005072 }
5073
5074 /**
5075 * Find the view in the hierarchy rooted at this view that currently has
5076 * focus.
5077 *
5078 * @return The view that currently has focus, or null if no focused view can
5079 * be found.
5080 */
5081 public View findFocus() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005082 return (mPrivateFlags & PFLAG_FOCUSED) != 0 ? this : null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005083 }
5084
5085 /**
Philip Milne6c8ea062012-04-03 17:38:43 -07005086 * Indicates whether this view is one of the set of scrollable containers in
5087 * its window.
5088 *
5089 * @return whether this view is one of the set of scrollable containers in
5090 * its window
5091 *
5092 * @attr ref android.R.styleable#View_isScrollContainer
5093 */
5094 public boolean isScrollContainer() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005095 return (mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0;
Philip Milne6c8ea062012-04-03 17:38:43 -07005096 }
5097
5098 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005099 * Change whether this view is one of the set of scrollable containers in
5100 * its window. This will be used to determine whether the window can
5101 * resize or must pan when a soft input area is open -- scrollable
5102 * containers allow the window to use resize mode since the container
5103 * will appropriately shrink.
Philip Milne6c8ea062012-04-03 17:38:43 -07005104 *
5105 * @attr ref android.R.styleable#View_isScrollContainer
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005106 */
5107 public void setScrollContainer(boolean isScrollContainer) {
5108 if (isScrollContainer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005109 if (mAttachInfo != null && (mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005110 mAttachInfo.mScrollContainers.add(this);
Dianne Hackborn4702a852012-08-17 15:18:29 -07005111 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005112 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07005113 mPrivateFlags |= PFLAG_SCROLL_CONTAINER;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005114 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005115 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005116 mAttachInfo.mScrollContainers.remove(this);
5117 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07005118 mPrivateFlags &= ~(PFLAG_SCROLL_CONTAINER|PFLAG_SCROLL_CONTAINER_ADDED);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005119 }
5120 }
5121
5122 /**
5123 * Returns the quality of the drawing cache.
5124 *
5125 * @return One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5126 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5127 *
5128 * @see #setDrawingCacheQuality(int)
5129 * @see #setDrawingCacheEnabled(boolean)
5130 * @see #isDrawingCacheEnabled()
5131 *
5132 * @attr ref android.R.styleable#View_drawingCacheQuality
5133 */
5134 public int getDrawingCacheQuality() {
5135 return mViewFlags & DRAWING_CACHE_QUALITY_MASK;
5136 }
5137
5138 /**
5139 * Set the drawing cache quality of this view. This value is used only when the
5140 * drawing cache is enabled
5141 *
5142 * @param quality One of {@link #DRAWING_CACHE_QUALITY_AUTO},
5143 * {@link #DRAWING_CACHE_QUALITY_LOW}, or {@link #DRAWING_CACHE_QUALITY_HIGH}
5144 *
5145 * @see #getDrawingCacheQuality()
5146 * @see #setDrawingCacheEnabled(boolean)
5147 * @see #isDrawingCacheEnabled()
5148 *
5149 * @attr ref android.R.styleable#View_drawingCacheQuality
5150 */
5151 public void setDrawingCacheQuality(int quality) {
5152 setFlags(quality, DRAWING_CACHE_QUALITY_MASK);
5153 }
5154
5155 /**
5156 * Returns whether the screen should remain on, corresponding to the current
5157 * value of {@link #KEEP_SCREEN_ON}.
5158 *
5159 * @return Returns true if {@link #KEEP_SCREEN_ON} is set.
5160 *
5161 * @see #setKeepScreenOn(boolean)
5162 *
5163 * @attr ref android.R.styleable#View_keepScreenOn
5164 */
5165 public boolean getKeepScreenOn() {
5166 return (mViewFlags & KEEP_SCREEN_ON) != 0;
5167 }
5168
5169 /**
5170 * Controls whether the screen should remain on, modifying the
5171 * value of {@link #KEEP_SCREEN_ON}.
5172 *
5173 * @param keepScreenOn Supply true to set {@link #KEEP_SCREEN_ON}.
5174 *
5175 * @see #getKeepScreenOn()
5176 *
5177 * @attr ref android.R.styleable#View_keepScreenOn
5178 */
5179 public void setKeepScreenOn(boolean keepScreenOn) {
5180 setFlags(keepScreenOn ? KEEP_SCREEN_ON : 0, KEEP_SCREEN_ON);
5181 }
5182
5183 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005184 * Gets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5185 * @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 -08005186 *
5187 * @attr ref android.R.styleable#View_nextFocusLeft
5188 */
5189 public int getNextFocusLeftId() {
5190 return mNextFocusLeftId;
5191 }
5192
5193 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005194 * Sets the id of the view to use when the next focus is {@link #FOCUS_LEFT}.
5195 * @param nextFocusLeftId The next focus ID, or {@link #NO_ID} if the framework should
5196 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005197 *
5198 * @attr ref android.R.styleable#View_nextFocusLeft
5199 */
5200 public void setNextFocusLeftId(int nextFocusLeftId) {
5201 mNextFocusLeftId = nextFocusLeftId;
5202 }
5203
5204 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005205 * Gets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5206 * @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 -08005207 *
5208 * @attr ref android.R.styleable#View_nextFocusRight
5209 */
5210 public int getNextFocusRightId() {
5211 return mNextFocusRightId;
5212 }
5213
5214 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005215 * Sets the id of the view to use when the next focus is {@link #FOCUS_RIGHT}.
5216 * @param nextFocusRightId The next focus ID, or {@link #NO_ID} if the framework should
5217 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005218 *
5219 * @attr ref android.R.styleable#View_nextFocusRight
5220 */
5221 public void setNextFocusRightId(int nextFocusRightId) {
5222 mNextFocusRightId = nextFocusRightId;
5223 }
5224
5225 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005226 * Gets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5227 * @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 -08005228 *
5229 * @attr ref android.R.styleable#View_nextFocusUp
5230 */
5231 public int getNextFocusUpId() {
5232 return mNextFocusUpId;
5233 }
5234
5235 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005236 * Sets the id of the view to use when the next focus is {@link #FOCUS_UP}.
5237 * @param nextFocusUpId The next focus ID, or {@link #NO_ID} if the framework should
5238 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005239 *
5240 * @attr ref android.R.styleable#View_nextFocusUp
5241 */
5242 public void setNextFocusUpId(int nextFocusUpId) {
5243 mNextFocusUpId = nextFocusUpId;
5244 }
5245
5246 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005247 * Gets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5248 * @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 -08005249 *
5250 * @attr ref android.R.styleable#View_nextFocusDown
5251 */
5252 public int getNextFocusDownId() {
5253 return mNextFocusDownId;
5254 }
5255
5256 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005257 * Sets the id of the view to use when the next focus is {@link #FOCUS_DOWN}.
5258 * @param nextFocusDownId The next focus ID, or {@link #NO_ID} if the framework should
5259 * decide automatically.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005260 *
5261 * @attr ref android.R.styleable#View_nextFocusDown
5262 */
5263 public void setNextFocusDownId(int nextFocusDownId) {
5264 mNextFocusDownId = nextFocusDownId;
5265 }
5266
5267 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -08005268 * Gets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5269 * @return The next focus ID, or {@link #NO_ID} if the framework should decide automatically.
5270 *
5271 * @attr ref android.R.styleable#View_nextFocusForward
5272 */
5273 public int getNextFocusForwardId() {
5274 return mNextFocusForwardId;
5275 }
5276
5277 /**
5278 * Sets the id of the view to use when the next focus is {@link #FOCUS_FORWARD}.
5279 * @param nextFocusForwardId The next focus ID, or {@link #NO_ID} if the framework should
5280 * decide automatically.
5281 *
5282 * @attr ref android.R.styleable#View_nextFocusForward
5283 */
5284 public void setNextFocusForwardId(int nextFocusForwardId) {
5285 mNextFocusForwardId = nextFocusForwardId;
5286 }
5287
5288 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005289 * Returns the visibility of this view and all of its ancestors
5290 *
5291 * @return True if this view and all of its ancestors are {@link #VISIBLE}
5292 */
5293 public boolean isShown() {
5294 View current = this;
5295 //noinspection ConstantConditions
5296 do {
5297 if ((current.mViewFlags & VISIBILITY_MASK) != VISIBLE) {
5298 return false;
5299 }
5300 ViewParent parent = current.mParent;
5301 if (parent == null) {
5302 return false; // We are not attached to the view root
5303 }
5304 if (!(parent instanceof View)) {
5305 return true;
5306 }
5307 current = (View) parent;
5308 } while (current != null);
5309
5310 return false;
5311 }
5312
5313 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005314 * Called by the view hierarchy when the content insets for a window have
5315 * changed, to allow it to adjust its content to fit within those windows.
5316 * The content insets tell you the space that the status bar, input method,
5317 * and other system windows infringe on the application's window.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005318 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005319 * <p>You do not normally need to deal with this function, since the default
5320 * window decoration given to applications takes care of applying it to the
5321 * content of the window. If you use {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}
5322 * or {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION} this will not be the case,
5323 * and your content can be placed under those system elements. You can then
5324 * use this method within your view hierarchy if you have parts of your UI
5325 * which you would like to ensure are not being covered.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005326 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005327 * <p>The default implementation of this method simply applies the content
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005328 * inset's to the view's padding, consuming that content (modifying the
5329 * insets to be 0), and returning true. This behavior is off by default, but can
5330 * be enabled through {@link #setFitsSystemWindows(boolean)}.
5331 *
5332 * <p>This function's traversal down the hierarchy is depth-first. The same content
5333 * insets object is propagated down the hierarchy, so any changes made to it will
5334 * be seen by all following views (including potentially ones above in
5335 * the hierarchy since this is a depth-first traversal). The first view
5336 * that returns true will abort the entire traversal.
5337 *
5338 * <p>The default implementation works well for a situation where it is
5339 * used with a container that covers the entire window, allowing it to
5340 * apply the appropriate insets to its content on all edges. If you need
5341 * a more complicated layout (such as two different views fitting system
5342 * windows, one on the top of the window, and one on the bottom),
5343 * you can override the method and handle the insets however you would like.
5344 * Note that the insets provided by the framework are always relative to the
5345 * far edges of the window, not accounting for the location of the called view
5346 * within that window. (In fact when this method is called you do not yet know
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005347 * where the layout will place the view, as it is done before layout happens.)
5348 *
5349 * <p>Note: unlike many View methods, there is no dispatch phase to this
5350 * call. If you are overriding it in a ViewGroup and want to allow the
5351 * call to continue to your children, you must be sure to call the super
5352 * implementation.
5353 *
Dianne Hackborncf675782012-05-10 15:07:24 -07005354 * <p>Here is a sample layout that makes use of fitting system windows
5355 * to have controls for a video view placed inside of the window decorations
5356 * that it hides and shows. This can be used with code like the second
5357 * sample (video player) shown in {@link #setSystemUiVisibility(int)}.
5358 *
5359 * {@sample development/samples/ApiDemos/res/layout/video_player.xml complete}
5360 *
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005361 * @param insets Current content insets of the window. Prior to
5362 * {@link android.os.Build.VERSION_CODES#JELLY_BEAN} you must not modify
5363 * the insets or else you and Android will be unhappy.
5364 *
5365 * @return Return true if this view applied the insets and it should not
5366 * continue propagating further down the hierarchy, false otherwise.
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005367 * @see #getFitsSystemWindows()
Romain Guyf0af1d52012-07-11 18:31:21 -07005368 * @see #setFitsSystemWindows(boolean)
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005369 * @see #setSystemUiVisibility(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005370 */
5371 protected boolean fitSystemWindows(Rect insets) {
5372 if ((mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS) {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -07005373 mUserPaddingStart = UNDEFINED_PADDING;
5374 mUserPaddingEnd = UNDEFINED_PADDING;
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005375 if ((mViewFlags & OPTIONAL_FITS_SYSTEM_WINDOWS) == 0
5376 || mAttachInfo == null
5377 || (mAttachInfo.mSystemUiVisibility & SYSTEM_UI_LAYOUT_FLAGS) == 0) {
5378 internalSetPadding(insets.left, insets.top, insets.right, insets.bottom);
5379 return true;
5380 } else {
5381 internalSetPadding(0, 0, 0, 0);
5382 return false;
5383 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005384 }
5385 return false;
5386 }
5387
5388 /**
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005389 * Sets whether or not this view should account for system screen decorations
5390 * such as the status bar and inset its content; that is, controlling whether
5391 * the default implementation of {@link #fitSystemWindows(Rect)} will be
5392 * executed. See that method for more details.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005393 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005394 * <p>Note that if you are providing your own implementation of
5395 * {@link #fitSystemWindows(Rect)}, then there is no need to set this
5396 * flag to true -- your implementation will be overriding the default
5397 * implementation that checks this flag.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005398 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005399 * @param fitSystemWindows If true, then the default implementation of
5400 * {@link #fitSystemWindows(Rect)} will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005401 *
5402 * @attr ref android.R.styleable#View_fitsSystemWindows
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005403 * @see #getFitsSystemWindows()
5404 * @see #fitSystemWindows(Rect)
5405 * @see #setSystemUiVisibility(int)
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005406 */
5407 public void setFitsSystemWindows(boolean fitSystemWindows) {
5408 setFlags(fitSystemWindows ? FITS_SYSTEM_WINDOWS : 0, FITS_SYSTEM_WINDOWS);
5409 }
5410
5411 /**
Dianne Hackborncf675782012-05-10 15:07:24 -07005412 * Check for state of {@link #setFitsSystemWindows(boolean). If this method
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005413 * returns true, the default implementation of {@link #fitSystemWindows(Rect)}
5414 * will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005415 *
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005416 * @return Returns true if the default implementation of
5417 * {@link #fitSystemWindows(Rect)} will be executed.
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005418 *
5419 * @attr ref android.R.styleable#View_fitsSystemWindows
Dianne Hackbornd5333f92012-05-18 10:51:35 -07005420 * @see #setFitsSystemWindows()
5421 * @see #fitSystemWindows(Rect)
5422 * @see #setSystemUiVisibility(int)
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005423 */
Dianne Hackborncf675782012-05-10 15:07:24 -07005424 public boolean getFitsSystemWindows() {
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005425 return (mViewFlags & FITS_SYSTEM_WINDOWS) == FITS_SYSTEM_WINDOWS;
5426 }
5427
Dianne Hackbornb1b55e62012-05-10 16:25:54 -07005428 /** @hide */
5429 public boolean fitsSystemWindows() {
5430 return getFitsSystemWindows();
5431 }
5432
Adam Powell0bd1d0a2011-07-22 19:35:06 -07005433 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07005434 * Ask that a new dispatch of {@link #fitSystemWindows(Rect)} be performed.
5435 */
5436 public void requestFitSystemWindows() {
5437 if (mParent != null) {
5438 mParent.requestFitSystemWindows();
5439 }
5440 }
5441
5442 /**
5443 * For use by PhoneWindow to make its own system window fitting optional.
5444 * @hide
5445 */
5446 public void makeOptionalFitsSystemWindows() {
5447 setFlags(OPTIONAL_FITS_SYSTEM_WINDOWS, OPTIONAL_FITS_SYSTEM_WINDOWS);
5448 }
5449
5450 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005451 * Returns the visibility status for this view.
5452 *
5453 * @return One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5454 * @attr ref android.R.styleable#View_visibility
5455 */
5456 @ViewDebug.ExportedProperty(mapping = {
The Android Open Source Projectc39a6e02009-03-11 12:11:56 -07005457 @ViewDebug.IntToString(from = VISIBLE, to = "VISIBLE"),
5458 @ViewDebug.IntToString(from = INVISIBLE, to = "INVISIBLE"),
5459 @ViewDebug.IntToString(from = GONE, to = "GONE")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005460 })
5461 public int getVisibility() {
5462 return mViewFlags & VISIBILITY_MASK;
5463 }
5464
5465 /**
5466 * Set the enabled state of this view.
5467 *
5468 * @param visibility One of {@link #VISIBLE}, {@link #INVISIBLE}, or {@link #GONE}.
5469 * @attr ref android.R.styleable#View_visibility
5470 */
5471 @RemotableViewMethod
5472 public void setVisibility(int visibility) {
5473 setFlags(visibility, VISIBILITY_MASK);
Philip Milne6c8ea062012-04-03 17:38:43 -07005474 if (mBackground != null) mBackground.setVisible(visibility == VISIBLE, false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005475 }
5476
5477 /**
5478 * Returns the enabled status for this view. The interpretation of the
5479 * enabled state varies by subclass.
5480 *
5481 * @return True if this view is enabled, false otherwise.
5482 */
5483 @ViewDebug.ExportedProperty
5484 public boolean isEnabled() {
5485 return (mViewFlags & ENABLED_MASK) == ENABLED;
5486 }
5487
5488 /**
5489 * Set the enabled state of this view. The interpretation of the enabled
5490 * state varies by subclass.
5491 *
5492 * @param enabled True if this view is enabled, false otherwise.
5493 */
Jeff Sharkey2b95c242010-02-08 17:40:30 -08005494 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005495 public void setEnabled(boolean enabled) {
Amith Yamasania2ef00b2009-07-30 16:14:34 -07005496 if (enabled == isEnabled()) return;
5497
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005498 setFlags(enabled ? ENABLED : DISABLED, ENABLED_MASK);
5499
5500 /*
5501 * The View most likely has to change its appearance, so refresh
5502 * the drawable state.
5503 */
5504 refreshDrawableState();
5505
5506 // Invalidate too, since the default behavior for views is to be
5507 // be drawn at 50% alpha rather than to change the drawable.
Romain Guy0fd89bf2011-01-26 15:41:30 -08005508 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005509 }
5510
5511 /**
5512 * Set whether this view can receive the focus.
5513 *
5514 * Setting this to false will also ensure that this view is not focusable
5515 * in touch mode.
5516 *
5517 * @param focusable If true, this view can receive the focus.
5518 *
5519 * @see #setFocusableInTouchMode(boolean)
5520 * @attr ref android.R.styleable#View_focusable
5521 */
5522 public void setFocusable(boolean focusable) {
5523 if (!focusable) {
5524 setFlags(0, FOCUSABLE_IN_TOUCH_MODE);
5525 }
5526 setFlags(focusable ? FOCUSABLE : NOT_FOCUSABLE, FOCUSABLE_MASK);
5527 }
5528
5529 /**
5530 * Set whether this view can receive focus while in touch mode.
5531 *
5532 * Setting this to true will also ensure that this view is focusable.
5533 *
5534 * @param focusableInTouchMode If true, this view can receive the focus while
5535 * in touch mode.
5536 *
5537 * @see #setFocusable(boolean)
5538 * @attr ref android.R.styleable#View_focusableInTouchMode
5539 */
5540 public void setFocusableInTouchMode(boolean focusableInTouchMode) {
5541 // Focusable in touch mode should always be set before the focusable flag
5542 // otherwise, setting the focusable flag will trigger a focusableViewAvailable()
5543 // which, in touch mode, will not successfully request focus on this view
5544 // because the focusable in touch mode flag is not set
5545 setFlags(focusableInTouchMode ? FOCUSABLE_IN_TOUCH_MODE : 0, FOCUSABLE_IN_TOUCH_MODE);
5546 if (focusableInTouchMode) {
5547 setFlags(FOCUSABLE, FOCUSABLE_MASK);
5548 }
5549 }
5550
5551 /**
5552 * Set whether this view should have sound effects enabled for events such as
5553 * clicking and touching.
5554 *
5555 * <p>You may wish to disable sound effects for a view if you already play sounds,
5556 * for instance, a dial key that plays dtmf tones.
5557 *
5558 * @param soundEffectsEnabled whether sound effects are enabled for this view.
5559 * @see #isSoundEffectsEnabled()
5560 * @see #playSoundEffect(int)
5561 * @attr ref android.R.styleable#View_soundEffectsEnabled
5562 */
5563 public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {
5564 setFlags(soundEffectsEnabled ? SOUND_EFFECTS_ENABLED: 0, SOUND_EFFECTS_ENABLED);
5565 }
5566
5567 /**
5568 * @return whether this view should have sound effects enabled for events such as
5569 * clicking and touching.
5570 *
5571 * @see #setSoundEffectsEnabled(boolean)
5572 * @see #playSoundEffect(int)
5573 * @attr ref android.R.styleable#View_soundEffectsEnabled
5574 */
5575 @ViewDebug.ExportedProperty
5576 public boolean isSoundEffectsEnabled() {
5577 return SOUND_EFFECTS_ENABLED == (mViewFlags & SOUND_EFFECTS_ENABLED);
5578 }
5579
5580 /**
5581 * Set whether this view should have haptic feedback for events such as
5582 * long presses.
5583 *
5584 * <p>You may wish to disable haptic feedback if your view already controls
5585 * its own haptic feedback.
5586 *
5587 * @param hapticFeedbackEnabled whether haptic feedback enabled for this view.
5588 * @see #isHapticFeedbackEnabled()
5589 * @see #performHapticFeedback(int)
5590 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5591 */
5592 public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {
5593 setFlags(hapticFeedbackEnabled ? HAPTIC_FEEDBACK_ENABLED: 0, HAPTIC_FEEDBACK_ENABLED);
5594 }
5595
5596 /**
5597 * @return whether this view should have haptic feedback enabled for events
5598 * long presses.
5599 *
5600 * @see #setHapticFeedbackEnabled(boolean)
5601 * @see #performHapticFeedback(int)
5602 * @attr ref android.R.styleable#View_hapticFeedbackEnabled
5603 */
5604 @ViewDebug.ExportedProperty
5605 public boolean isHapticFeedbackEnabled() {
5606 return HAPTIC_FEEDBACK_ENABLED == (mViewFlags & HAPTIC_FEEDBACK_ENABLED);
5607 }
5608
5609 /**
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005610 * Returns the layout direction for this view.
Cibu Johny7632cb92010-02-22 13:01:02 -08005611 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005612 * @return One of {@link #LAYOUT_DIRECTION_LTR},
5613 * {@link #LAYOUT_DIRECTION_RTL},
5614 * {@link #LAYOUT_DIRECTION_INHERIT} or
5615 * {@link #LAYOUT_DIRECTION_LOCALE}.
5616 * @attr ref android.R.styleable#View_layoutDirection
Cibu Johny7632cb92010-02-22 13:01:02 -08005617 */
Fabrice Di Megliobce84d22011-06-02 15:57:01 -07005618 @ViewDebug.ExportedProperty(category = "layout", mapping = {
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005619 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "LTR"),
5620 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RTL"),
5621 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_INHERIT, to = "INHERIT"),
5622 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LOCALE, to = "LOCALE")
Cibu Johny7632cb92010-02-22 13:01:02 -08005623 })
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005624 public int getLayoutDirection() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005625 return (mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_MASK) >> PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT;
Cibu Johny7632cb92010-02-22 13:01:02 -08005626 }
5627
5628 /**
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005629 * Set the layout direction for this view. This will propagate a reset of layout direction
5630 * resolution to the view's children and resolve layout direction for this view.
Cibu Johny7632cb92010-02-22 13:01:02 -08005631 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005632 * @param layoutDirection One of {@link #LAYOUT_DIRECTION_LTR},
5633 * {@link #LAYOUT_DIRECTION_RTL},
5634 * {@link #LAYOUT_DIRECTION_INHERIT} or
5635 * {@link #LAYOUT_DIRECTION_LOCALE}.
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005636 *
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005637 * @attr ref android.R.styleable#View_layoutDirection
Cibu Johny7632cb92010-02-22 13:01:02 -08005638 */
5639 @RemotableViewMethod
Fabrice Di Meglioc46f7ff2011-06-06 18:23:10 -07005640 public void setLayoutDirection(int layoutDirection) {
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005641 if (getLayoutDirection() != layoutDirection) {
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -07005642 // Reset the current layout direction and the resolved one
Dianne Hackborn4702a852012-08-17 15:18:29 -07005643 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_MASK;
Fabrice Di Meglio7f86c802011-07-01 15:09:24 -07005644 resetResolvedLayoutDirection();
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005645 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -07005646 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005647 // Set the new layout direction (filtered)
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005648 mPrivateFlags2 |=
Dianne Hackborn4702a852012-08-17 15:18:29 -07005649 ((layoutDirection << PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT) & PFLAG2_LAYOUT_DIRECTION_MASK);
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005650 resolveRtlProperties();
5651 // ... and ask for a layout pass
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005652 requestLayout();
Fabrice Di Meglio80dc53d2011-06-21 18:36:33 -07005653 }
Cibu Johny7632cb92010-02-22 13:01:02 -08005654 }
5655
5656 /**
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005657 * Returns the resolved layout direction for this view.
5658 *
5659 * @return {@link #LAYOUT_DIRECTION_RTL} if the layout direction is RTL or returns
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005660 * {@link #LAYOUT_DIRECTION_LTR} if the layout direction is not RTL.
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005661 */
5662 @ViewDebug.ExportedProperty(category = "layout", mapping = {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005663 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
5664 @ViewDebug.IntToString(from = LAYOUT_DIRECTION_RTL, to = "RESOLVED_DIRECTION_RTL")
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005665 })
5666 public int getResolvedLayoutDirection() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005667 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
5668 if (targetSdkVersion < JELLY_BEAN_MR1) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005669 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07005670 return LAYOUT_DIRECTION_LTR;
5671 }
Fabrice Di Megliob93911f2012-06-26 19:43:15 -07005672 // The layout direction will be resolved only if needed
Dianne Hackborn4702a852012-08-17 15:18:29 -07005673 if ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED) != PFLAG2_LAYOUT_DIRECTION_RESOLVED) {
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -07005674 resolveLayoutDirection();
5675 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07005676 return ((mPrivateFlags2 & PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) == PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL) ?
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005677 LAYOUT_DIRECTION_RTL : LAYOUT_DIRECTION_LTR;
5678 }
5679
5680 /**
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -07005681 * Indicates whether or not this view's layout is right-to-left. This is resolved from
5682 * layout attribute and/or the inherited value from the parent
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005683 *
5684 * @return true if the layout is right-to-left.
Fabrice Di Meglioc0053222011-06-13 12:16:51 -07005685 */
5686 @ViewDebug.ExportedProperty(category = "layout")
5687 public boolean isLayoutRtl() {
5688 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL);
5689 }
5690
5691 /**
Adam Powell539ee872012-02-03 19:00:49 -08005692 * Indicates whether the view is currently tracking transient state that the
5693 * app should not need to concern itself with saving and restoring, but that
5694 * the framework should take special note to preserve when possible.
5695 *
Adam Powell785c4472012-05-02 21:25:39 -07005696 * <p>A view with transient state cannot be trivially rebound from an external
5697 * data source, such as an adapter binding item views in a list. This may be
5698 * because the view is performing an animation, tracking user selection
5699 * of content, or similar.</p>
5700 *
Adam Powell539ee872012-02-03 19:00:49 -08005701 * @return true if the view has transient state
Adam Powell539ee872012-02-03 19:00:49 -08005702 */
5703 @ViewDebug.ExportedProperty(category = "layout")
5704 public boolean hasTransientState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005705 return (mPrivateFlags2 & PFLAG2_HAS_TRANSIENT_STATE) == PFLAG2_HAS_TRANSIENT_STATE;
Adam Powell539ee872012-02-03 19:00:49 -08005706 }
5707
5708 /**
5709 * Set whether this view is currently tracking transient state that the
Chet Haase563d4f22012-04-18 16:20:08 -07005710 * framework should attempt to preserve when possible. This flag is reference counted,
5711 * so every call to setHasTransientState(true) should be paired with a later call
5712 * to setHasTransientState(false).
Adam Powell539ee872012-02-03 19:00:49 -08005713 *
Adam Powell785c4472012-05-02 21:25:39 -07005714 * <p>A view with transient state cannot be trivially rebound from an external
5715 * data source, such as an adapter binding item views in a list. This may be
5716 * because the view is performing an animation, tracking user selection
5717 * of content, or similar.</p>
5718 *
Adam Powell539ee872012-02-03 19:00:49 -08005719 * @param hasTransientState true if this view has transient state
Adam Powell539ee872012-02-03 19:00:49 -08005720 */
5721 public void setHasTransientState(boolean hasTransientState) {
Chet Haase563d4f22012-04-18 16:20:08 -07005722 mTransientStateCount = hasTransientState ? mTransientStateCount + 1 :
5723 mTransientStateCount - 1;
5724 if (mTransientStateCount < 0) {
5725 mTransientStateCount = 0;
5726 Log.e(VIEW_LOG_TAG, "hasTransientState decremented below 0: " +
5727 "unmatched pair of setHasTransientState calls");
5728 }
5729 if ((hasTransientState && mTransientStateCount == 1) ||
Adam Powell057a5852012-05-11 10:28:38 -07005730 (!hasTransientState && mTransientStateCount == 0)) {
Chet Haase563d4f22012-04-18 16:20:08 -07005731 // update flag if we've just incremented up from 0 or decremented down to 0
Dianne Hackborn4702a852012-08-17 15:18:29 -07005732 mPrivateFlags2 = (mPrivateFlags2 & ~PFLAG2_HAS_TRANSIENT_STATE) |
5733 (hasTransientState ? PFLAG2_HAS_TRANSIENT_STATE : 0);
Chet Haase563d4f22012-04-18 16:20:08 -07005734 if (mParent != null) {
5735 try {
5736 mParent.childHasTransientStateChanged(this, hasTransientState);
5737 } catch (AbstractMethodError e) {
5738 Log.e(VIEW_LOG_TAG, mParent.getClass().getSimpleName() +
5739 " does not fully implement ViewParent", e);
5740 }
Adam Powell539ee872012-02-03 19:00:49 -08005741 }
5742 }
5743 }
5744
5745 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005746 * If this view doesn't do any drawing on its own, set this flag to
5747 * allow further optimizations. By default, this flag is not set on
5748 * View, but could be set on some View subclasses such as ViewGroup.
5749 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07005750 * Typically, if you override {@link #onDraw(android.graphics.Canvas)}
5751 * you should clear this flag.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005752 *
5753 * @param willNotDraw whether or not this View draw on its own
5754 */
5755 public void setWillNotDraw(boolean willNotDraw) {
5756 setFlags(willNotDraw ? WILL_NOT_DRAW : 0, DRAW_MASK);
5757 }
5758
5759 /**
5760 * Returns whether or not this View draws on its own.
5761 *
5762 * @return true if this view has nothing to draw, false otherwise
5763 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005764 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005765 public boolean willNotDraw() {
5766 return (mViewFlags & DRAW_MASK) == WILL_NOT_DRAW;
5767 }
5768
5769 /**
5770 * When a View's drawing cache is enabled, drawing is redirected to an
5771 * offscreen bitmap. Some views, like an ImageView, must be able to
5772 * bypass this mechanism if they already draw a single bitmap, to avoid
5773 * unnecessary usage of the memory.
5774 *
5775 * @param willNotCacheDrawing true if this view does not cache its
5776 * drawing, false otherwise
5777 */
5778 public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {
5779 setFlags(willNotCacheDrawing ? WILL_NOT_CACHE_DRAWING : 0, WILL_NOT_CACHE_DRAWING);
5780 }
5781
5782 /**
5783 * Returns whether or not this View can cache its drawing or not.
5784 *
5785 * @return true if this view does not cache its drawing, false otherwise
5786 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005787 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005788 public boolean willNotCacheDrawing() {
5789 return (mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING;
5790 }
5791
5792 /**
5793 * Indicates whether this view reacts to click events or not.
5794 *
5795 * @return true if the view is clickable, false otherwise
5796 *
5797 * @see #setClickable(boolean)
5798 * @attr ref android.R.styleable#View_clickable
5799 */
5800 @ViewDebug.ExportedProperty
5801 public boolean isClickable() {
5802 return (mViewFlags & CLICKABLE) == CLICKABLE;
5803 }
5804
5805 /**
5806 * Enables or disables click events for this view. When a view
5807 * is clickable it will change its state to "pressed" on every click.
5808 * Subclasses should set the view clickable to visually react to
5809 * user's clicks.
5810 *
5811 * @param clickable true to make the view clickable, false otherwise
5812 *
5813 * @see #isClickable()
5814 * @attr ref android.R.styleable#View_clickable
5815 */
5816 public void setClickable(boolean clickable) {
5817 setFlags(clickable ? CLICKABLE : 0, CLICKABLE);
5818 }
5819
5820 /**
5821 * Indicates whether this view reacts to long click events or not.
5822 *
5823 * @return true if the view is long clickable, false otherwise
5824 *
5825 * @see #setLongClickable(boolean)
5826 * @attr ref android.R.styleable#View_longClickable
5827 */
5828 public boolean isLongClickable() {
5829 return (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
5830 }
5831
5832 /**
5833 * Enables or disables long click events for this view. When a view is long
5834 * clickable it reacts to the user holding down the button for a longer
5835 * duration than a tap. This event can either launch the listener or a
5836 * context menu.
5837 *
5838 * @param longClickable true to make the view long clickable, false otherwise
5839 * @see #isLongClickable()
5840 * @attr ref android.R.styleable#View_longClickable
5841 */
5842 public void setLongClickable(boolean longClickable) {
5843 setFlags(longClickable ? LONG_CLICKABLE : 0, LONG_CLICKABLE);
5844 }
5845
5846 /**
Chet Haase49afa5b2010-08-23 11:39:53 -07005847 * Sets the pressed state for this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005848 *
5849 * @see #isClickable()
5850 * @see #setClickable(boolean)
5851 *
5852 * @param pressed Pass true to set the View's internal state to "pressed", or false to reverts
5853 * the View's internal state from a previously set "pressed" state.
5854 */
5855 public void setPressed(boolean pressed) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005856 final boolean needsRefresh = pressed != ((mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED);
Adam Powell4d6f0662012-02-21 15:11:11 -08005857
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005858 if (pressed) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005859 mPrivateFlags |= PFLAG_PRESSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005860 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005861 mPrivateFlags &= ~PFLAG_PRESSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005862 }
Adam Powell035a1fc2012-02-27 15:23:50 -08005863
5864 if (needsRefresh) {
5865 refreshDrawableState();
5866 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005867 dispatchSetPressed(pressed);
5868 }
5869
5870 /**
5871 * Dispatch setPressed to all of this View's children.
5872 *
5873 * @see #setPressed(boolean)
5874 *
5875 * @param pressed The new pressed state
5876 */
5877 protected void dispatchSetPressed(boolean pressed) {
5878 }
5879
5880 /**
5881 * Indicates whether the view is currently in pressed state. Unless
5882 * {@link #setPressed(boolean)} is explicitly called, only clickable views can enter
5883 * the pressed state.
5884 *
Philip Milne6c8ea062012-04-03 17:38:43 -07005885 * @see #setPressed(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005886 * @see #isClickable()
5887 * @see #setClickable(boolean)
5888 *
5889 * @return true if the view is currently pressed, false otherwise
5890 */
5891 public boolean isPressed() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07005892 return (mPrivateFlags & PFLAG_PRESSED) == PFLAG_PRESSED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005893 }
5894
5895 /**
5896 * Indicates whether this view will save its state (that is,
5897 * whether its {@link #onSaveInstanceState} method will be called).
5898 *
5899 * @return Returns true if the view state saving is enabled, else false.
5900 *
5901 * @see #setSaveEnabled(boolean)
5902 * @attr ref android.R.styleable#View_saveEnabled
5903 */
5904 public boolean isSaveEnabled() {
5905 return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
5906 }
5907
5908 /**
5909 * Controls whether the saving of this view's state is
5910 * enabled (that is, whether its {@link #onSaveInstanceState} method
5911 * will be called). Note that even if freezing is enabled, the
Romain Guy5c22a8c2011-05-13 11:48:45 -07005912 * view still must have an id assigned to it (via {@link #setId(int)})
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005913 * for its state to be saved. This flag can only disable the
5914 * saving of this view; any child views may still have their state saved.
5915 *
5916 * @param enabled Set to false to <em>disable</em> state saving, or true
5917 * (the default) to allow it.
5918 *
5919 * @see #isSaveEnabled()
5920 * @see #setId(int)
5921 * @see #onSaveInstanceState()
5922 * @attr ref android.R.styleable#View_saveEnabled
5923 */
5924 public void setSaveEnabled(boolean enabled) {
5925 setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
5926 }
5927
Jeff Brown85a31762010-09-01 17:01:00 -07005928 /**
5929 * Gets whether the framework should discard touches when the view's
5930 * window is obscured by another visible window.
5931 * Refer to the {@link View} security documentation for more details.
5932 *
5933 * @return True if touch filtering is enabled.
5934 *
5935 * @see #setFilterTouchesWhenObscured(boolean)
5936 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5937 */
5938 @ViewDebug.ExportedProperty
5939 public boolean getFilterTouchesWhenObscured() {
5940 return (mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0;
5941 }
5942
5943 /**
5944 * Sets whether the framework should discard touches when the view's
5945 * window is obscured by another visible window.
5946 * Refer to the {@link View} security documentation for more details.
5947 *
5948 * @param enabled True if touch filtering should be enabled.
5949 *
5950 * @see #getFilterTouchesWhenObscured
5951 * @attr ref android.R.styleable#View_filterTouchesWhenObscured
5952 */
5953 public void setFilterTouchesWhenObscured(boolean enabled) {
5954 setFlags(enabled ? 0 : FILTER_TOUCHES_WHEN_OBSCURED,
5955 FILTER_TOUCHES_WHEN_OBSCURED);
5956 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005957
5958 /**
Dianne Hackbornb4bc78b2010-05-12 18:59:50 -07005959 * Indicates whether the entire hierarchy under this view will save its
5960 * state when a state saving traversal occurs from its parent. The default
5961 * is true; if false, these views will not be saved unless
5962 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5963 *
5964 * @return Returns true if the view state saving from parent is enabled, else false.
5965 *
5966 * @see #setSaveFromParentEnabled(boolean)
5967 */
5968 public boolean isSaveFromParentEnabled() {
5969 return (mViewFlags & PARENT_SAVE_DISABLED_MASK) != PARENT_SAVE_DISABLED;
5970 }
5971
5972 /**
5973 * Controls whether the entire hierarchy under this view will save its
5974 * state when a state saving traversal occurs from its parent. The default
5975 * is true; if false, these views will not be saved unless
5976 * {@link #saveHierarchyState(SparseArray)} is called directly on this view.
5977 *
5978 * @param enabled Set to false to <em>disable</em> state saving, or true
5979 * (the default) to allow it.
5980 *
5981 * @see #isSaveFromParentEnabled()
5982 * @see #setId(int)
5983 * @see #onSaveInstanceState()
5984 */
5985 public void setSaveFromParentEnabled(boolean enabled) {
5986 setFlags(enabled ? 0 : PARENT_SAVE_DISABLED, PARENT_SAVE_DISABLED_MASK);
5987 }
5988
5989
5990 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005991 * Returns whether this View is able to take focus.
5992 *
5993 * @return True if this view can take focus, or false otherwise.
5994 * @attr ref android.R.styleable#View_focusable
5995 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07005996 @ViewDebug.ExportedProperty(category = "focus")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08005997 public final boolean isFocusable() {
5998 return FOCUSABLE == (mViewFlags & FOCUSABLE_MASK);
5999 }
6000
6001 /**
6002 * When a view is focusable, it may not want to take focus when in touch mode.
6003 * For example, a button would like focus when the user is navigating via a D-pad
6004 * so that the user can click on it, but once the user starts touching the screen,
6005 * the button shouldn't take focus
6006 * @return Whether the view is focusable in touch mode.
6007 * @attr ref android.R.styleable#View_focusableInTouchMode
6008 */
6009 @ViewDebug.ExportedProperty
6010 public final boolean isFocusableInTouchMode() {
6011 return FOCUSABLE_IN_TOUCH_MODE == (mViewFlags & FOCUSABLE_IN_TOUCH_MODE);
6012 }
6013
6014 /**
6015 * Find the nearest view in the specified direction that can take focus.
6016 * This does not actually give focus to that view.
6017 *
6018 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6019 *
6020 * @return The nearest focusable in the specified direction, or null if none
6021 * can be found.
6022 */
6023 public View focusSearch(int direction) {
6024 if (mParent != null) {
6025 return mParent.focusSearch(this, direction);
6026 } else {
6027 return null;
6028 }
6029 }
6030
6031 /**
6032 * This method is the last chance for the focused view and its ancestors to
6033 * respond to an arrow key. This is called when the focused view did not
6034 * consume the key internally, nor could the view system find a new view in
6035 * the requested direction to give focus to.
6036 *
6037 * @param focused The currently focused view.
6038 * @param direction The direction focus wants to move. One of FOCUS_UP,
6039 * FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT.
6040 * @return True if the this view consumed this unhandled move.
6041 */
6042 public boolean dispatchUnhandledMove(View focused, int direction) {
6043 return false;
6044 }
6045
6046 /**
6047 * If a user manually specified the next view id for a particular direction,
Jeff Brown4e6319b2010-12-13 10:36:51 -08006048 * use the root to look up the view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006049 * @param root The root view of the hierarchy containing this view.
Jeff Brown4e6319b2010-12-13 10:36:51 -08006050 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, FOCUS_RIGHT, FOCUS_FORWARD,
6051 * or FOCUS_BACKWARD.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006052 * @return The user specified next view, or null if there is none.
6053 */
6054 View findUserSetNextFocus(View root, int direction) {
6055 switch (direction) {
6056 case FOCUS_LEFT:
6057 if (mNextFocusLeftId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006058 return findViewInsideOutShouldExist(root, mNextFocusLeftId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006059 case FOCUS_RIGHT:
6060 if (mNextFocusRightId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006061 return findViewInsideOutShouldExist(root, mNextFocusRightId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006062 case FOCUS_UP:
6063 if (mNextFocusUpId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006064 return findViewInsideOutShouldExist(root, mNextFocusUpId);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006065 case FOCUS_DOWN:
6066 if (mNextFocusDownId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006067 return findViewInsideOutShouldExist(root, mNextFocusDownId);
Jeff Brown4e6319b2010-12-13 10:36:51 -08006068 case FOCUS_FORWARD:
6069 if (mNextFocusForwardId == View.NO_ID) return null;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006070 return findViewInsideOutShouldExist(root, mNextFocusForwardId);
Jeff Brown4e6319b2010-12-13 10:36:51 -08006071 case FOCUS_BACKWARD: {
John Reck1ecebbb2012-03-06 16:08:54 -08006072 if (mID == View.NO_ID) return null;
Jeff Brown4e6319b2010-12-13 10:36:51 -08006073 final int id = mID;
Jeff Brown4dfbec22011-08-15 14:55:37 -07006074 return root.findViewByPredicateInsideOut(this, new Predicate<View>() {
Jeff Brown4e6319b2010-12-13 10:36:51 -08006075 @Override
6076 public boolean apply(View t) {
6077 return t.mNextFocusForwardId == id;
6078 }
6079 });
6080 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006081 }
6082 return null;
6083 }
6084
Jeff Brown4dfbec22011-08-15 14:55:37 -07006085 private View findViewInsideOutShouldExist(View root, final int childViewId) {
6086 View result = root.findViewByPredicateInsideOut(this, new Predicate<View>() {
6087 @Override
6088 public boolean apply(View t) {
6089 return t.mID == childViewId;
6090 }
6091 });
6092
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006093 if (result == null) {
6094 Log.w(VIEW_LOG_TAG, "couldn't find next focus view specified "
6095 + "by user for id " + childViewId);
6096 }
6097 return result;
6098 }
6099
6100 /**
6101 * Find and return all focusable views that are descendants of this view,
6102 * possibly including this view if it is focusable itself.
6103 *
6104 * @param direction The direction of the focus
6105 * @return A list of focusable views
6106 */
6107 public ArrayList<View> getFocusables(int direction) {
6108 ArrayList<View> result = new ArrayList<View>(24);
6109 addFocusables(result, direction);
6110 return result;
6111 }
6112
6113 /**
6114 * Add any focusable views that are descendants of this view (possibly
6115 * including this view if it is focusable itself) to views. If we are in touch mode,
6116 * only add views that are also focusable in touch mode.
6117 *
6118 * @param views Focusable views found so far
6119 * @param direction The direction of the focus
6120 */
6121 public void addFocusables(ArrayList<View> views, int direction) {
svetoslavganov75986cf2009-05-14 22:28:01 -07006122 addFocusables(views, direction, FOCUSABLES_TOUCH_MODE);
6123 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006124
svetoslavganov75986cf2009-05-14 22:28:01 -07006125 /**
6126 * Adds any focusable views that are descendants of this view (possibly
6127 * including this view if it is focusable itself) to views. This method
6128 * adds all focusable views regardless if we are in touch mode or
Svetoslav Ganov42138042012-03-20 11:51:39 -07006129 * only views focusable in touch mode if we are in touch mode or
6130 * only views that can take accessibility focus if accessibility is enabeld
6131 * depending on the focusable mode paramater.
svetoslavganov75986cf2009-05-14 22:28:01 -07006132 *
6133 * @param views Focusable views found so far or null if all we are interested is
6134 * the number of focusables.
6135 * @param direction The direction of the focus.
6136 * @param focusableMode The type of focusables to be added.
6137 *
6138 * @see #FOCUSABLES_ALL
6139 * @see #FOCUSABLES_TOUCH_MODE
6140 */
6141 public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006142 if (views == null) {
svetoslavganov75986cf2009-05-14 22:28:01 -07006143 return;
6144 }
Svetoslav Ganov3cb889c2012-04-16 19:10:30 -07006145 if (!isFocusable()) {
6146 return;
svetoslavganov75986cf2009-05-14 22:28:01 -07006147 }
Svetoslav Ganov3cb889c2012-04-16 19:10:30 -07006148 if ((focusableMode & FOCUSABLES_TOUCH_MODE) == FOCUSABLES_TOUCH_MODE
6149 && isInTouchMode() && !isFocusableInTouchMode()) {
6150 return;
6151 }
6152 views.add(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006153 }
6154
6155 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006156 * Finds the Views that contain given text. The containment is case insensitive.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006157 * The search is performed by either the text that the View renders or the content
6158 * description that describes the view for accessibility purposes and the view does
6159 * not render or both. Clients can specify how the search is to be performed via
6160 * passing the {@link #FIND_VIEWS_WITH_TEXT} and
6161 * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006162 *
6163 * @param outViews The output list of matching Views.
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006164 * @param searched The text to match against.
Svetoslav Ganov02107852011-10-03 17:06:56 -07006165 *
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006166 * @see #FIND_VIEWS_WITH_TEXT
6167 * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
6168 * @see #setContentDescription(CharSequence)
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006169 */
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006170 public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
Svetoslav Ganov02107852011-10-03 17:06:56 -07006171 if (getAccessibilityNodeProvider() != null) {
6172 if ((flags & FIND_VIEWS_WITH_ACCESSIBILITY_NODE_PROVIDERS) != 0) {
6173 outViews.add(this);
6174 }
6175 } else if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006176 && (searched != null && searched.length() > 0)
6177 && (mContentDescription != null && mContentDescription.length() > 0)) {
Svetoslav Ganovea515ae2011-09-14 18:15:32 -07006178 String searchedLowerCase = searched.toString().toLowerCase();
6179 String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
6180 if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
6181 outViews.add(this);
6182 }
6183 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006184 }
6185
6186 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006187 * Find and return all touchable views that are descendants of this view,
6188 * possibly including this view if it is touchable itself.
6189 *
6190 * @return A list of touchable views
6191 */
6192 public ArrayList<View> getTouchables() {
6193 ArrayList<View> result = new ArrayList<View>();
6194 addTouchables(result);
6195 return result;
6196 }
6197
6198 /**
6199 * Add any touchable views that are descendants of this view (possibly
6200 * including this view if it is touchable itself) to views.
6201 *
6202 * @param views Touchable views found so far
6203 */
6204 public void addTouchables(ArrayList<View> views) {
6205 final int viewFlags = mViewFlags;
6206
6207 if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
6208 && (viewFlags & ENABLED_MASK) == ENABLED) {
6209 views.add(this);
6210 }
6211 }
6212
6213 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07006214 * Returns whether this View is accessibility focused.
6215 *
6216 * @return True if this View is accessibility focused.
6217 */
6218 boolean isAccessibilityFocused() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006219 return (mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006220 }
6221
6222 /**
6223 * Call this to try to give accessibility focus to this view.
6224 *
6225 * A view will not actually take focus if {@link AccessibilityManager#isEnabled()}
6226 * returns false or the view is no visible or the view already has accessibility
6227 * focus.
6228 *
6229 * See also {@link #focusSearch(int)}, which is what you call to say that you
6230 * have focus, and you want your parent to look for the next one.
6231 *
6232 * @return Whether this view actually took accessibility focus.
6233 *
6234 * @hide
6235 */
6236 public boolean requestAccessibilityFocus() {
Svetoslav Ganov07b726c2012-04-30 12:24:57 -07006237 AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
6238 if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006239 return false;
6240 }
6241 if ((mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6242 return false;
6243 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07006244 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) == 0) {
6245 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006246 ViewRootImpl viewRootImpl = getViewRootImpl();
6247 if (viewRootImpl != null) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006248 viewRootImpl.setAccessibilityFocus(this, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07006249 }
6250 invalidate();
6251 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
6252 notifyAccessibilityStateChanged();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006253 return true;
6254 }
6255 return false;
6256 }
6257
6258 /**
6259 * Call this to try to clear accessibility focus of this view.
6260 *
6261 * See also {@link #focusSearch(int)}, which is what you call to say that you
6262 * have focus, and you want your parent to look for the next one.
6263 *
6264 * @hide
6265 */
6266 public void clearAccessibilityFocus() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006267 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6268 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006269 invalidate();
6270 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
6271 notifyAccessibilityStateChanged();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006272 }
Svetoslav Ganovc00d0082012-05-22 18:37:49 -07006273 // Clear the global reference of accessibility focus if this
6274 // view or any of its descendants had accessibility focus.
6275 ViewRootImpl viewRootImpl = getViewRootImpl();
6276 if (viewRootImpl != null) {
6277 View focusHost = viewRootImpl.getAccessibilityFocusedHost();
6278 if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07006279 viewRootImpl.setAccessibilityFocus(null, null);
Svetoslav Ganovc00d0082012-05-22 18:37:49 -07006280 }
6281 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006282 }
6283
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07006284 private void sendAccessibilityHoverEvent(int eventType) {
6285 // Since we are not delivering to a client accessibility events from not
6286 // important views (unless the clinet request that) we need to fire the
6287 // event from the deepest view exposed to the client. As a consequence if
6288 // the user crosses a not exposed view the client will see enter and exit
6289 // of the exposed predecessor followed by and enter and exit of that same
6290 // predecessor when entering and exiting the not exposed descendant. This
6291 // is fine since the client has a clear idea which view is hovered at the
6292 // price of a couple more events being sent. This is a simple and
6293 // working solution.
6294 View source = this;
6295 while (true) {
6296 if (source.includeForAccessibility()) {
6297 source.sendAccessibilityEvent(eventType);
6298 return;
6299 }
6300 ViewParent parent = source.getParent();
6301 if (parent instanceof View) {
6302 source = (View) parent;
6303 } else {
6304 return;
6305 }
6306 }
6307 }
6308
Svetoslav Ganov42138042012-03-20 11:51:39 -07006309 /**
6310 * Clears accessibility focus without calling any callback methods
6311 * normally invoked in {@link #clearAccessibilityFocus()}. This method
6312 * is used for clearing accessibility focus when giving this focus to
6313 * another view.
6314 */
6315 void clearAccessibilityFocusNoCallbacks() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006316 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_FOCUSED) != 0) {
6317 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_FOCUSED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006318 invalidate();
6319 }
6320 }
6321
6322 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006323 * Call this to try to give focus to a specific view or to one of its
6324 * descendants.
6325 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006326 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6327 * false), or if it is focusable and it is not focusable in touch mode
6328 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006329 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006330 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006331 * have focus, and you want your parent to look for the next one.
6332 *
6333 * This is equivalent to calling {@link #requestFocus(int, Rect)} with arguments
6334 * {@link #FOCUS_DOWN} and <code>null</code>.
6335 *
6336 * @return Whether this view or one of its descendants actually took focus.
6337 */
6338 public final boolean requestFocus() {
6339 return requestFocus(View.FOCUS_DOWN);
6340 }
6341
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006342 /**
6343 * Call this to try to give focus to a specific view or to one of its
6344 * descendants and give it a hint about what direction focus is heading.
6345 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006346 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6347 * false), or if it is focusable and it is not focusable in touch mode
6348 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006349 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006350 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006351 * have focus, and you want your parent to look for the next one.
6352 *
6353 * This is equivalent to calling {@link #requestFocus(int, Rect)} with
6354 * <code>null</code> set for the previously focused rectangle.
6355 *
6356 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6357 * @return Whether this view or one of its descendants actually took focus.
6358 */
6359 public final boolean requestFocus(int direction) {
6360 return requestFocus(direction, null);
6361 }
6362
6363 /**
6364 * Call this to try to give focus to a specific view or to one of its descendants
6365 * and give it hints about the direction and a specific rectangle that the focus
6366 * is coming from. The rectangle can help give larger views a finer grained hint
6367 * about where focus is coming from, and therefore, where to show selection, or
6368 * forward focus change internally.
6369 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006370 * A view will not actually take focus if it is not focusable ({@link #isFocusable} returns
6371 * false), or if it is focusable and it is not focusable in touch mode
6372 * ({@link #isFocusableInTouchMode}) while the device is in touch mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006373 *
6374 * A View will not take focus if it is not visible.
6375 *
Gilles Debunne2ed2eac2011-02-24 16:29:48 -08006376 * A View will not take focus if one of its parents has
6377 * {@link android.view.ViewGroup#getDescendantFocusability()} equal to
6378 * {@link ViewGroup#FOCUS_BLOCK_DESCENDANTS}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006379 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07006380 * See also {@link #focusSearch(int)}, which is what you call to say that you
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006381 * have focus, and you want your parent to look for the next one.
6382 *
6383 * You may wish to override this method if your custom {@link View} has an internal
6384 * {@link View} that it wishes to forward the request to.
6385 *
6386 * @param direction One of FOCUS_UP, FOCUS_DOWN, FOCUS_LEFT, and FOCUS_RIGHT
6387 * @param previouslyFocusedRect The rectangle (in this View's coordinate system)
6388 * to give a finer grained hint about where focus is coming from. May be null
6389 * if there is no hint.
6390 * @return Whether this view or one of its descendants actually took focus.
6391 */
6392 public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006393 return requestFocusNoSearch(direction, previouslyFocusedRect);
6394 }
6395
6396 private boolean requestFocusNoSearch(int direction, Rect previouslyFocusedRect) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006397 // need to be focusable
6398 if ((mViewFlags & FOCUSABLE_MASK) != FOCUSABLE ||
6399 (mViewFlags & VISIBILITY_MASK) != VISIBLE) {
6400 return false;
6401 }
6402
6403 // need to be focusable in touch mode if in touch mode
6404 if (isInTouchMode() &&
Svetoslav Ganov8643aa02011-04-20 12:12:33 -07006405 (FOCUSABLE_IN_TOUCH_MODE != (mViewFlags & FOCUSABLE_IN_TOUCH_MODE))) {
6406 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006407 }
6408
6409 // need to not have any parents blocking us
6410 if (hasAncestorThatBlocksDescendantFocus()) {
6411 return false;
6412 }
6413
6414 handleFocusGainInternal(direction, previouslyFocusedRect);
6415 return true;
6416 }
6417
6418 /**
6419 * Call this to try to give focus to a specific view or to one of its descendants. This is a
6420 * special variant of {@link #requestFocus() } that will allow views that are not focuable in
6421 * touch mode to request focus when they are touched.
6422 *
6423 * @return Whether this view or one of its descendants actually took focus.
6424 *
6425 * @see #isInTouchMode()
6426 *
6427 */
6428 public final boolean requestFocusFromTouch() {
6429 // Leave touch mode if we need to
6430 if (isInTouchMode()) {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07006431 ViewRootImpl viewRoot = getViewRootImpl();
Christopher Tate2c095f32010-10-04 14:13:40 -07006432 if (viewRoot != null) {
6433 viewRoot.ensureTouchMode(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006434 }
6435 }
6436 return requestFocus(View.FOCUS_DOWN);
6437 }
6438
6439 /**
6440 * @return Whether any ancestor of this view blocks descendant focus.
6441 */
6442 private boolean hasAncestorThatBlocksDescendantFocus() {
6443 ViewParent ancestor = mParent;
6444 while (ancestor instanceof ViewGroup) {
6445 final ViewGroup vgAncestor = (ViewGroup) ancestor;
6446 if (vgAncestor.getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) {
6447 return true;
6448 } else {
6449 ancestor = vgAncestor.getParent();
6450 }
6451 }
6452 return false;
6453 }
6454
6455 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -07006456 * Gets the mode for determining whether this View is important for accessibility
6457 * which is if it fires accessibility events and if it is reported to
6458 * accessibility services that query the screen.
6459 *
6460 * @return The mode for determining whether a View is important for accessibility.
6461 *
6462 * @attr ref android.R.styleable#View_importantForAccessibility
6463 *
6464 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6465 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6466 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6467 */
6468 @ViewDebug.ExportedProperty(category = "accessibility", mapping = {
Svetoslav Ganovf9817f72012-05-22 18:10:31 -07006469 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_AUTO, to = "auto"),
6470 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_YES, to = "yes"),
6471 @ViewDebug.IntToString(from = IMPORTANT_FOR_ACCESSIBILITY_NO, to = "no")
Svetoslav Ganov42138042012-03-20 11:51:39 -07006472 })
6473 public int getImportantForAccessibility() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006474 return (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6475 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006476 }
6477
6478 /**
6479 * Sets how to determine whether this view is important for accessibility
6480 * which is if it fires accessibility events and if it is reported to
6481 * accessibility services that query the screen.
6482 *
6483 * @param mode How to determine whether this view is important for accessibility.
6484 *
6485 * @attr ref android.R.styleable#View_importantForAccessibility
6486 *
6487 * @see #IMPORTANT_FOR_ACCESSIBILITY_YES
6488 * @see #IMPORTANT_FOR_ACCESSIBILITY_NO
6489 * @see #IMPORTANT_FOR_ACCESSIBILITY_AUTO
6490 */
6491 public void setImportantForAccessibility(int mode) {
6492 if (mode != getImportantForAccessibility()) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006493 mPrivateFlags2 &= ~PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
6494 mPrivateFlags2 |= (mode << PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT)
6495 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006496 notifyAccessibilityStateChanged();
6497 }
6498 }
6499
6500 /**
6501 * Gets whether this view should be exposed for accessibility.
6502 *
6503 * @return Whether the view is exposed for accessibility.
6504 *
6505 * @hide
6506 */
6507 public boolean isImportantForAccessibility() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006508 final int mode = (mPrivateFlags2 & PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_MASK)
6509 >> PFLAG2_IMPORTANT_FOR_ACCESSIBILITY_SHIFT;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006510 switch (mode) {
6511 case IMPORTANT_FOR_ACCESSIBILITY_YES:
6512 return true;
6513 case IMPORTANT_FOR_ACCESSIBILITY_NO:
6514 return false;
6515 case IMPORTANT_FOR_ACCESSIBILITY_AUTO:
Svetoslav Ganov34caec92012-07-19 18:07:58 -07006516 return isActionableForAccessibility() || hasListenersForAccessibility()
6517 || getAccessibilityNodeProvider() != null;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006518 default:
6519 throw new IllegalArgumentException("Unknow important for accessibility mode: "
6520 + mode);
6521 }
6522 }
6523
6524 /**
6525 * Gets the parent for accessibility purposes. Note that the parent for
6526 * accessibility is not necessary the immediate parent. It is the first
6527 * predecessor that is important for accessibility.
6528 *
6529 * @return The parent for accessibility purposes.
6530 */
6531 public ViewParent getParentForAccessibility() {
6532 if (mParent instanceof View) {
6533 View parentView = (View) mParent;
6534 if (parentView.includeForAccessibility()) {
6535 return mParent;
6536 } else {
6537 return mParent.getParentForAccessibility();
6538 }
6539 }
6540 return null;
6541 }
6542
6543 /**
6544 * Adds the children of a given View for accessibility. Since some Views are
6545 * not important for accessibility the children for accessibility are not
6546 * necessarily direct children of the riew, rather they are the first level of
6547 * descendants important for accessibility.
6548 *
6549 * @param children The list of children for accessibility.
6550 */
6551 public void addChildrenForAccessibility(ArrayList<View> children) {
6552 if (includeForAccessibility()) {
6553 children.add(this);
6554 }
6555 }
6556
6557 /**
6558 * Whether to regard this view for accessibility. A view is regarded for
6559 * accessibility if it is important for accessibility or the querying
6560 * accessibility service has explicitly requested that view not
6561 * important for accessibility are regarded.
6562 *
6563 * @return Whether to regard the view for accessibility.
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006564 *
6565 * @hide
Svetoslav Ganov42138042012-03-20 11:51:39 -07006566 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006567 public boolean includeForAccessibility() {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006568 if (mAttachInfo != null) {
Romain Guyf0af1d52012-07-11 18:31:21 -07006569 return mAttachInfo.mIncludeNotImportantViews || isImportantForAccessibility();
Svetoslav Ganov42138042012-03-20 11:51:39 -07006570 }
6571 return false;
6572 }
6573
6574 /**
6575 * Returns whether the View is considered actionable from
6576 * accessibility perspective. Such view are important for
6577 * accessiiblity.
6578 *
6579 * @return True if the view is actionable for accessibility.
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006580 *
6581 * @hide
Svetoslav Ganov42138042012-03-20 11:51:39 -07006582 */
Svetoslav Ganove5dfa47d2012-05-08 15:58:32 -07006583 public boolean isActionableForAccessibility() {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006584 return (isClickable() || isLongClickable() || isFocusable());
6585 }
6586
6587 /**
6588 * Returns whether the View has registered callbacks wich makes it
6589 * important for accessiiblity.
6590 *
6591 * @return True if the view is actionable for accessibility.
6592 */
6593 private boolean hasListenersForAccessibility() {
6594 ListenerInfo info = getListenerInfo();
6595 return mTouchDelegate != null || info.mOnKeyListener != null
6596 || info.mOnTouchListener != null || info.mOnGenericMotionListener != null
6597 || info.mOnHoverListener != null || info.mOnDragListener != null;
6598 }
6599
6600 /**
6601 * Notifies accessibility services that some view's important for
6602 * accessibility state has changed. Note that such notifications
6603 * are made at most once every
6604 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}
6605 * to avoid unnecessary load to the system. Also once a view has
6606 * made a notifucation this method is a NOP until the notification has
6607 * been sent to clients.
6608 *
6609 * @hide
6610 *
6611 * TODO: Makse sure this method is called for any view state change
6612 * that is interesting for accessilility purposes.
6613 */
6614 public void notifyAccessibilityStateChanged() {
Svetoslav Ganovc406be92012-05-11 16:12:32 -07006615 if (!AccessibilityManager.getInstance(mContext).isEnabled()) {
6616 return;
6617 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07006618 if ((mPrivateFlags2 & PFLAG2_ACCESSIBILITY_STATE_CHANGED) == 0) {
6619 mPrivateFlags2 |= PFLAG2_ACCESSIBILITY_STATE_CHANGED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006620 if (mParent != null) {
6621 mParent.childAccessibilityStateChanged(this);
6622 }
6623 }
6624 }
6625
6626 /**
6627 * Reset the state indicating the this view has requested clients
6628 * interested in its accessiblity state to be notified.
6629 *
6630 * @hide
6631 */
6632 public void resetAccessibilityStateChanged() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07006633 mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_STATE_CHANGED;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006634 }
6635
6636 /**
6637 * Performs the specified accessibility action on the view. For
6638 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
alanv8eeefef2012-05-07 16:57:53 -07006639 * <p>
6640 * If an {@link AccessibilityDelegate} has been specified via calling
6641 * {@link #setAccessibilityDelegate(AccessibilityDelegate)} its
6642 * {@link AccessibilityDelegate#performAccessibilityAction(View, int, Bundle)}
6643 * is responsible for handling this call.
6644 * </p>
Svetoslav Ganov42138042012-03-20 11:51:39 -07006645 *
6646 * @param action The action to perform.
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006647 * @param arguments Optional action arguments.
Svetoslav Ganov42138042012-03-20 11:51:39 -07006648 * @return Whether the action was performed.
6649 */
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006650 public boolean performAccessibilityAction(int action, Bundle arguments) {
alanv8eeefef2012-05-07 16:57:53 -07006651 if (mAccessibilityDelegate != null) {
6652 return mAccessibilityDelegate.performAccessibilityAction(this, action, arguments);
6653 } else {
6654 return performAccessibilityActionInternal(action, arguments);
6655 }
6656 }
6657
6658 /**
6659 * @see #performAccessibilityAction(int, Bundle)
6660 *
6661 * Note: Called from the default {@link AccessibilityDelegate}.
6662 */
6663 boolean performAccessibilityActionInternal(int action, Bundle arguments) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006664 switch (action) {
6665 case AccessibilityNodeInfo.ACTION_CLICK: {
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006666 if (isClickable()) {
Svetoslav Ganov773f2622012-05-05 19:59:42 -07006667 return performClick();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006668 }
6669 } break;
6670 case AccessibilityNodeInfo.ACTION_LONG_CLICK: {
6671 if (isLongClickable()) {
Svetoslav Ganov773f2622012-05-05 19:59:42 -07006672 return performLongClick();
Svetoslav Ganov005b83b2012-04-16 18:17:17 -07006673 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07006674 } break;
6675 case AccessibilityNodeInfo.ACTION_FOCUS: {
6676 if (!hasFocus()) {
6677 // Get out of touch mode since accessibility
6678 // wants to move focus around.
6679 getViewRootImpl().ensureTouchMode(false);
6680 return requestFocus();
6681 }
6682 } break;
6683 case AccessibilityNodeInfo.ACTION_CLEAR_FOCUS: {
6684 if (hasFocus()) {
6685 clearFocus();
6686 return !isFocused();
6687 }
6688 } break;
6689 case AccessibilityNodeInfo.ACTION_SELECT: {
6690 if (!isSelected()) {
6691 setSelected(true);
6692 return isSelected();
6693 }
6694 } break;
6695 case AccessibilityNodeInfo.ACTION_CLEAR_SELECTION: {
6696 if (isSelected()) {
6697 setSelected(false);
6698 return !isSelected();
6699 }
6700 } break;
6701 case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
Svetoslav Ganov27e2da72012-07-02 18:12:00 -07006702 if (!isAccessibilityFocused()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07006703 return requestAccessibilityFocus();
6704 }
6705 } break;
6706 case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
6707 if (isAccessibilityFocused()) {
6708 clearAccessibilityFocus();
6709 return true;
6710 }
6711 } break;
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006712 case AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY: {
6713 if (arguments != null) {
6714 final int granularity = arguments.getInt(
6715 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6716 return nextAtGranularity(granularity);
6717 }
6718 } break;
6719 case AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY: {
6720 if (arguments != null) {
6721 final int granularity = arguments.getInt(
6722 AccessibilityNodeInfo.ACTION_ARGUMENT_MOVEMENT_GRANULARITY_INT);
6723 return previousAtGranularity(granularity);
6724 }
6725 } break;
Svetoslav Ganov42138042012-03-20 11:51:39 -07006726 }
6727 return false;
6728 }
6729
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006730 private boolean nextAtGranularity(int granularity) {
6731 CharSequence text = getIterableTextForAccessibility();
Svetoslav Ganov64899e52012-05-15 21:09:30 -07006732 if (text == null || text.length() == 0) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006733 return false;
6734 }
6735 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6736 if (iterator == null) {
6737 return false;
6738 }
6739 final int current = getAccessibilityCursorPosition();
6740 final int[] range = iterator.following(current);
6741 if (range == null) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006742 return false;
6743 }
6744 final int start = range[0];
6745 final int end = range[1];
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006746 setAccessibilityCursorPosition(end);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006747 sendViewTextTraversedAtGranularityEvent(
6748 AccessibilityNodeInfo.ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
6749 granularity, start, end);
6750 return true;
6751 }
6752
6753 private boolean previousAtGranularity(int granularity) {
6754 CharSequence text = getIterableTextForAccessibility();
Svetoslav Ganov64899e52012-05-15 21:09:30 -07006755 if (text == null || text.length() == 0) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006756 return false;
6757 }
6758 TextSegmentIterator iterator = getIteratorForGranularity(granularity);
6759 if (iterator == null) {
6760 return false;
6761 }
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006762 int current = getAccessibilityCursorPosition();
6763 if (current == ACCESSIBILITY_CURSOR_POSITION_UNDEFINED) {
6764 current = text.length();
6765 } else if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6766 // When traversing by character we always put the cursor after the character
6767 // to ease edit and have to compensate before asking the for previous segment.
6768 current--;
6769 }
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006770 final int[] range = iterator.preceding(current);
6771 if (range == null) {
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006772 return false;
6773 }
6774 final int start = range[0];
6775 final int end = range[1];
Svetoslav Ganov39f2aee2012-05-29 09:15:30 -07006776 // Always put the cursor after the character to ease edit.
6777 if (granularity == AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER) {
6778 setAccessibilityCursorPosition(end);
6779 } else {
6780 setAccessibilityCursorPosition(start);
6781 }
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006782 sendViewTextTraversedAtGranularityEvent(
6783 AccessibilityNodeInfo.ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
6784 granularity, start, end);
6785 return true;
6786 }
6787
6788 /**
6789 * Gets the text reported for accessibility purposes.
6790 *
6791 * @return The accessibility text.
6792 *
6793 * @hide
6794 */
6795 public CharSequence getIterableTextForAccessibility() {
6796 return mContentDescription;
6797 }
6798
6799 /**
6800 * @hide
6801 */
6802 public int getAccessibilityCursorPosition() {
6803 return mAccessibilityCursorPosition;
6804 }
6805
6806 /**
6807 * @hide
6808 */
6809 public void setAccessibilityCursorPosition(int position) {
6810 mAccessibilityCursorPosition = position;
6811 }
6812
6813 private void sendViewTextTraversedAtGranularityEvent(int action, int granularity,
6814 int fromIndex, int toIndex) {
6815 if (mParent == null) {
6816 return;
6817 }
6818 AccessibilityEvent event = AccessibilityEvent.obtain(
6819 AccessibilityEvent.TYPE_VIEW_TEXT_TRAVERSED_AT_MOVEMENT_GRANULARITY);
6820 onInitializeAccessibilityEvent(event);
6821 onPopulateAccessibilityEvent(event);
6822 event.setFromIndex(fromIndex);
6823 event.setToIndex(toIndex);
6824 event.setAction(action);
6825 event.setMovementGranularity(granularity);
6826 mParent.requestSendAccessibilityEvent(this, event);
6827 }
6828
6829 /**
6830 * @hide
6831 */
6832 public TextSegmentIterator getIteratorForGranularity(int granularity) {
6833 switch (granularity) {
6834 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_CHARACTER: {
6835 CharSequence text = getIterableTextForAccessibility();
6836 if (text != null && text.length() > 0) {
6837 CharacterTextSegmentIterator iterator =
Svetoslav Ganovbbd31552012-06-11 12:08:18 -07006838 CharacterTextSegmentIterator.getInstance(
6839 mContext.getResources().getConfiguration().locale);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006840 iterator.initialize(text.toString());
6841 return iterator;
6842 }
6843 } break;
6844 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_WORD: {
6845 CharSequence text = getIterableTextForAccessibility();
6846 if (text != null && text.length() > 0) {
6847 WordTextSegmentIterator iterator =
Svetoslav Ganovbbd31552012-06-11 12:08:18 -07006848 WordTextSegmentIterator.getInstance(
6849 mContext.getResources().getConfiguration().locale);
Svetoslav Ganov6d17a932012-04-27 19:30:38 -07006850 iterator.initialize(text.toString());
6851 return iterator;
6852 }
6853 } break;
6854 case AccessibilityNodeInfo.MOVEMENT_GRANULARITY_PARAGRAPH: {
6855 CharSequence text = getIterableTextForAccessibility();
6856 if (text != null && text.length() > 0) {
6857 ParagraphTextSegmentIterator iterator =
6858 ParagraphTextSegmentIterator.getInstance();
6859 iterator.initialize(text.toString());
6860 return iterator;
6861 }
6862 } break;
6863 }
6864 return null;
6865 }
6866
Svetoslav Ganov42138042012-03-20 11:51:39 -07006867 /**
Romain Guya440b002010-02-24 15:57:54 -08006868 * @hide
6869 */
6870 public void dispatchStartTemporaryDetach() {
Svetoslav Ganov961bf0e2012-05-08 09:40:03 -07006871 clearAccessibilityFocus();
Romain Guy38c2ece2012-05-24 14:20:56 -07006872 clearDisplayList();
6873
Romain Guya440b002010-02-24 15:57:54 -08006874 onStartTemporaryDetach();
6875 }
6876
6877 /**
6878 * This is called when a container is going to temporarily detach a child, with
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006879 * {@link ViewGroup#detachViewFromParent(View) ViewGroup.detachViewFromParent}.
6880 * It will either be followed by {@link #onFinishTemporaryDetach()} or
Romain Guya440b002010-02-24 15:57:54 -08006881 * {@link #onDetachedFromWindow()} when the container is done.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006882 */
6883 public void onStartTemporaryDetach() {
Romain Guya440b002010-02-24 15:57:54 -08006884 removeUnsetPressCallback();
Dianne Hackborn4702a852012-08-17 15:18:29 -07006885 mPrivateFlags |= PFLAG_CANCEL_NEXT_UP_EVENT;
Romain Guya440b002010-02-24 15:57:54 -08006886 }
6887
6888 /**
6889 * @hide
6890 */
6891 public void dispatchFinishTemporaryDetach() {
6892 onFinishTemporaryDetach();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006893 }
Romain Guy8506ab42009-06-11 17:35:47 -07006894
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006895 /**
6896 * Called after {@link #onStartTemporaryDetach} when the container is done
6897 * changing the view.
6898 */
6899 public void onFinishTemporaryDetach() {
6900 }
Romain Guy8506ab42009-06-11 17:35:47 -07006901
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006902 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006903 * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
6904 * for this view's window. Returns null if the view is not currently attached
6905 * to the window. Normally you will not need to use this directly, but
Romain Guy5c22a8c2011-05-13 11:48:45 -07006906 * just use the standard high-level event callbacks like
6907 * {@link #onKeyDown(int, KeyEvent)}.
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006908 */
6909 public KeyEvent.DispatcherState getKeyDispatcherState() {
6910 return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
6911 }
Joe Malin32736f02011-01-19 16:14:20 -08006912
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07006913 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006914 * Dispatch a key event before it is processed by any input method
6915 * associated with the view hierarchy. This can be used to intercept
6916 * key events in special situations before the IME consumes them; a
6917 * typical example would be handling the BACK key to update the application's
6918 * UI instead of allowing the IME to see it and close itself.
6919 *
6920 * @param event The key event to be dispatched.
6921 * @return True if the event was handled, false otherwise.
6922 */
6923 public boolean dispatchKeyEventPreIme(KeyEvent event) {
6924 return onKeyPreIme(event.getKeyCode(), event);
6925 }
6926
6927 /**
6928 * Dispatch a key event to the next view on the focus path. This path runs
6929 * from the top of the view tree down to the currently focused view. If this
6930 * view has focus, it will dispatch to itself. Otherwise it will dispatch
6931 * the next node down the focus path. This method also fires any key
6932 * listeners.
6933 *
6934 * @param event The key event to be dispatched.
6935 * @return True if the event was handled, false otherwise.
6936 */
6937 public boolean dispatchKeyEvent(KeyEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006938 if (mInputEventConsistencyVerifier != null) {
6939 mInputEventConsistencyVerifier.onKeyEvent(event, 0);
6940 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006941
Jeff Brown21bc5c92011-02-28 18:27:14 -08006942 // Give any attached key listener a first crack at the event.
Romain Guyf607bdc2010-09-10 19:20:06 -07006943 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07006944 ListenerInfo li = mListenerInfo;
6945 if (li != null && li.mOnKeyListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
6946 && li.mOnKeyListener.onKey(this, event.getKeyCode(), event)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006947 return true;
6948 }
6949
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006950 if (event.dispatch(this, mAttachInfo != null
6951 ? mAttachInfo.mKeyDispatchState : null, this)) {
6952 return true;
6953 }
6954
6955 if (mInputEventConsistencyVerifier != null) {
6956 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
6957 }
6958 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006959 }
6960
6961 /**
6962 * Dispatches a key shortcut event.
6963 *
6964 * @param event The key event to be dispatched.
6965 * @return True if the event was handled by the view, false otherwise.
6966 */
6967 public boolean dispatchKeyShortcutEvent(KeyEvent event) {
6968 return onKeyShortcut(event.getKeyCode(), event);
6969 }
6970
6971 /**
6972 * Pass the touch screen motion event down to the target view, or this
6973 * view if it is the target.
6974 *
6975 * @param event The motion event to be dispatched.
6976 * @return True if the event was handled by the view, false otherwise.
6977 */
6978 public boolean dispatchTouchEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08006979 if (mInputEventConsistencyVerifier != null) {
6980 mInputEventConsistencyVerifier.onTouchEvent(event, 0);
6981 }
6982
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006983 if (onFilterTouchEventForSecurity(event)) {
6984 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07006985 ListenerInfo li = mListenerInfo;
6986 if (li != null && li.mOnTouchListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
6987 && li.mOnTouchListener.onTouch(this, event)) {
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006988 return true;
6989 }
6990
6991 if (onTouchEvent(event)) {
6992 return true;
6993 }
Jeff Brown85a31762010-09-01 17:01:00 -07006994 }
6995
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006996 if (mInputEventConsistencyVerifier != null) {
6997 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08006998 }
Jeff Brownbbdc50b2011-04-19 23:46:52 -07006999 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007000 }
7001
7002 /**
Jeff Brown85a31762010-09-01 17:01:00 -07007003 * Filter the touch event to apply security policies.
7004 *
7005 * @param event The motion event to be filtered.
7006 * @return True if the event should be dispatched, false if the event should be dropped.
Joe Malin32736f02011-01-19 16:14:20 -08007007 *
Jeff Brown85a31762010-09-01 17:01:00 -07007008 * @see #getFilterTouchesWhenObscured
7009 */
7010 public boolean onFilterTouchEventForSecurity(MotionEvent event) {
Romain Guyf607bdc2010-09-10 19:20:06 -07007011 //noinspection RedundantIfStatement
Jeff Brown85a31762010-09-01 17:01:00 -07007012 if ((mViewFlags & FILTER_TOUCHES_WHEN_OBSCURED) != 0
7013 && (event.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0) {
7014 // Window is obscured, drop this touch.
7015 return false;
7016 }
7017 return true;
7018 }
7019
7020 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007021 * Pass a trackball motion event down to the focused view.
7022 *
7023 * @param event The motion event to be dispatched.
7024 * @return True if the event was handled by the view, false otherwise.
7025 */
7026 public boolean dispatchTrackballEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08007027 if (mInputEventConsistencyVerifier != null) {
7028 mInputEventConsistencyVerifier.onTrackballEvent(event, 0);
7029 }
7030
Romain Guy02ccac62011-06-24 13:20:23 -07007031 return onTrackballEvent(event);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007032 }
7033
7034 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08007035 * Dispatch a generic motion event.
7036 * <p>
7037 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7038 * are delivered to the view under the pointer. All other generic motion events are
Jeff Browna032cc02011-03-07 16:56:21 -08007039 * delivered to the focused view. Hover events are handled specially and are delivered
Romain Guy5c22a8c2011-05-13 11:48:45 -07007040 * to {@link #onHoverEvent(MotionEvent)}.
Jeff Brown33bbfd22011-02-24 20:55:35 -08007041 * </p>
Jeff Browncb1404e2011-01-15 18:14:15 -08007042 *
7043 * @param event The motion event to be dispatched.
7044 * @return True if the event was handled by the view, false otherwise.
7045 */
7046 public boolean dispatchGenericMotionEvent(MotionEvent event) {
Jeff Brown21bc5c92011-02-28 18:27:14 -08007047 if (mInputEventConsistencyVerifier != null) {
7048 mInputEventConsistencyVerifier.onGenericMotionEvent(event, 0);
7049 }
7050
Jeff Browna032cc02011-03-07 16:56:21 -08007051 final int source = event.getSource();
7052 if ((source & InputDevice.SOURCE_CLASS_POINTER) != 0) {
7053 final int action = event.getAction();
7054 if (action == MotionEvent.ACTION_HOVER_ENTER
7055 || action == MotionEvent.ACTION_HOVER_MOVE
7056 || action == MotionEvent.ACTION_HOVER_EXIT) {
7057 if (dispatchHoverEvent(event)) {
7058 return true;
7059 }
7060 } else if (dispatchGenericPointerEvent(event)) {
7061 return true;
7062 }
7063 } else if (dispatchGenericFocusedEvent(event)) {
7064 return true;
7065 }
7066
Jeff Brown10b62902011-06-20 16:40:37 -07007067 if (dispatchGenericMotionEventInternal(event)) {
7068 return true;
7069 }
7070
7071 if (mInputEventConsistencyVerifier != null) {
7072 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7073 }
7074 return false;
7075 }
7076
7077 private boolean dispatchGenericMotionEventInternal(MotionEvent event) {
Romain Guy7b5b6ab2011-03-14 18:05:08 -07007078 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007079 ListenerInfo li = mListenerInfo;
7080 if (li != null && li.mOnGenericMotionListener != null
7081 && (mViewFlags & ENABLED_MASK) == ENABLED
7082 && li.mOnGenericMotionListener.onGenericMotion(this, event)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08007083 return true;
7084 }
Jeff Brownbbdc50b2011-04-19 23:46:52 -07007085
7086 if (onGenericMotionEvent(event)) {
7087 return true;
7088 }
7089
7090 if (mInputEventConsistencyVerifier != null) {
7091 mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);
7092 }
7093 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08007094 }
7095
7096 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007097 * Dispatch a hover event.
7098 * <p>
Philip Milne6c8ea062012-04-03 17:38:43 -07007099 * Do not call this method directly.
Romain Guy5c22a8c2011-05-13 11:48:45 -07007100 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007101 * </p>
7102 *
7103 * @param event The motion event to be dispatched.
7104 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007105 */
7106 protected boolean dispatchHoverEvent(MotionEvent event) {
Romain Guy02ccac62011-06-24 13:20:23 -07007107 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007108 ListenerInfo li = mListenerInfo;
7109 if (li != null && li.mOnHoverListener != null
7110 && (mViewFlags & ENABLED_MASK) == ENABLED
7111 && li.mOnHoverListener.onHover(this, event)) {
Jeff Brown10b62902011-06-20 16:40:37 -07007112 return true;
7113 }
7114
Jeff Browna032cc02011-03-07 16:56:21 -08007115 return onHoverEvent(event);
7116 }
7117
7118 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07007119 * Returns true if the view has a child to which it has recently sent
7120 * {@link MotionEvent#ACTION_HOVER_ENTER}. If this view is hovered and
7121 * it does not have a hovered child, then it must be the innermost hovered view.
7122 * @hide
7123 */
7124 protected boolean hasHoveredChild() {
7125 return false;
7126 }
7127
7128 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007129 * Dispatch a generic motion event to the view under the first pointer.
7130 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007131 * Do not call this method directly.
7132 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007133 * </p>
7134 *
7135 * @param event The motion event to be dispatched.
7136 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007137 */
7138 protected boolean dispatchGenericPointerEvent(MotionEvent event) {
7139 return false;
7140 }
7141
7142 /**
7143 * Dispatch a generic motion event to the currently focused view.
7144 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007145 * Do not call this method directly.
7146 * Call {@link #dispatchGenericMotionEvent(MotionEvent)} instead.
Jeff Browna032cc02011-03-07 16:56:21 -08007147 * </p>
7148 *
7149 * @param event The motion event to be dispatched.
7150 * @return True if the event was handled by the view, false otherwise.
Jeff Browna032cc02011-03-07 16:56:21 -08007151 */
7152 protected boolean dispatchGenericFocusedEvent(MotionEvent event) {
7153 return false;
7154 }
7155
7156 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -08007157 * Dispatch a pointer event.
7158 * <p>
Romain Guy5c22a8c2011-05-13 11:48:45 -07007159 * Dispatches touch related pointer events to {@link #onTouchEvent(MotionEvent)} and all
7160 * other events to {@link #onGenericMotionEvent(MotionEvent)}. This separation of concerns
7161 * reinforces the invariant that {@link #onTouchEvent(MotionEvent)} is really about touches
Jeff Brown33bbfd22011-02-24 20:55:35 -08007162 * and should not be expected to handle other pointing device features.
7163 * </p>
7164 *
7165 * @param event The motion event to be dispatched.
7166 * @return True if the event was handled by the view, false otherwise.
7167 * @hide
7168 */
7169 public final boolean dispatchPointerEvent(MotionEvent event) {
7170 if (event.isTouchEvent()) {
7171 return dispatchTouchEvent(event);
7172 } else {
7173 return dispatchGenericMotionEvent(event);
7174 }
7175 }
7176
7177 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007178 * Called when the window containing this view gains or loses window focus.
7179 * ViewGroups should override to route to their children.
7180 *
7181 * @param hasFocus True if the window containing this view now has focus,
7182 * false otherwise.
7183 */
7184 public void dispatchWindowFocusChanged(boolean hasFocus) {
7185 onWindowFocusChanged(hasFocus);
7186 }
7187
7188 /**
7189 * Called when the window containing this view gains or loses focus. Note
7190 * that this is separate from view focus: to receive key events, both
7191 * your view and its window must have focus. If a window is displayed
7192 * on top of yours that takes input focus, then your own window will lose
7193 * focus but the view focus will remain unchanged.
7194 *
7195 * @param hasWindowFocus True if the window containing this view now has
7196 * focus, false otherwise.
7197 */
7198 public void onWindowFocusChanged(boolean hasWindowFocus) {
7199 InputMethodManager imm = InputMethodManager.peekInstance();
7200 if (!hasWindowFocus) {
7201 if (isPressed()) {
7202 setPressed(false);
7203 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07007204 if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007205 imm.focusOut(this);
7206 }
Maryam Garrett1549dd12009-12-15 16:06:36 -05007207 removeLongPressCallback();
Tony Wu26edf202010-09-13 19:54:00 +08007208 removeTapCallback();
Romain Guya2431d02009-04-30 16:30:00 -07007209 onFocusLost();
Dianne Hackborn4702a852012-08-17 15:18:29 -07007210 } else if (imm != null && (mPrivateFlags & PFLAG_FOCUSED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007211 imm.focusIn(this);
7212 }
7213 refreshDrawableState();
7214 }
7215
7216 /**
7217 * Returns true if this view is in a window that currently has window focus.
7218 * Note that this is not the same as the view itself having focus.
7219 *
7220 * @return True if this view is in a window that currently has window focus.
7221 */
7222 public boolean hasWindowFocus() {
7223 return mAttachInfo != null && mAttachInfo.mHasWindowFocus;
7224 }
7225
7226 /**
Adam Powell326d8082009-12-09 15:10:07 -08007227 * Dispatch a view visibility change down the view hierarchy.
7228 * ViewGroups should override to route to their children.
7229 * @param changedView The view whose visibility changed. Could be 'this' or
7230 * an ancestor view.
Romain Guy43c9cdf2010-01-27 13:53:55 -08007231 * @param visibility The new visibility of changedView: {@link #VISIBLE},
7232 * {@link #INVISIBLE} or {@link #GONE}.
Adam Powell326d8082009-12-09 15:10:07 -08007233 */
7234 protected void dispatchVisibilityChanged(View changedView, int visibility) {
7235 onVisibilityChanged(changedView, visibility);
7236 }
7237
7238 /**
7239 * Called when the visibility of the view or an ancestor of the view is changed.
7240 * @param changedView The view whose visibility changed. Could be 'this' or
7241 * an ancestor view.
Romain Guy43c9cdf2010-01-27 13:53:55 -08007242 * @param visibility The new visibility of changedView: {@link #VISIBLE},
7243 * {@link #INVISIBLE} or {@link #GONE}.
Adam Powell326d8082009-12-09 15:10:07 -08007244 */
7245 protected void onVisibilityChanged(View changedView, int visibility) {
Adam Powell8568c3a2010-04-19 14:26:11 -07007246 if (visibility == VISIBLE) {
7247 if (mAttachInfo != null) {
7248 initialAwakenScrollBars();
7249 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007250 mPrivateFlags |= PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
Adam Powell8568c3a2010-04-19 14:26:11 -07007251 }
7252 }
Adam Powell326d8082009-12-09 15:10:07 -08007253 }
7254
7255 /**
Romain Guy43c9cdf2010-01-27 13:53:55 -08007256 * Dispatch a hint about whether this view is displayed. For instance, when
7257 * a View moves out of the screen, it might receives a display hint indicating
7258 * the view is not displayed. Applications should not <em>rely</em> on this hint
7259 * as there is no guarantee that they will receive one.
Joe Malin32736f02011-01-19 16:14:20 -08007260 *
Romain Guy43c9cdf2010-01-27 13:53:55 -08007261 * @param hint A hint about whether or not this view is displayed:
7262 * {@link #VISIBLE} or {@link #INVISIBLE}.
7263 */
7264 public void dispatchDisplayHint(int hint) {
7265 onDisplayHint(hint);
7266 }
7267
7268 /**
7269 * Gives this view a hint about whether is displayed or not. For instance, when
7270 * a View moves out of the screen, it might receives a display hint indicating
7271 * the view is not displayed. Applications should not <em>rely</em> on this hint
7272 * as there is no guarantee that they will receive one.
Joe Malin32736f02011-01-19 16:14:20 -08007273 *
Romain Guy43c9cdf2010-01-27 13:53:55 -08007274 * @param hint A hint about whether or not this view is displayed:
7275 * {@link #VISIBLE} or {@link #INVISIBLE}.
7276 */
7277 protected void onDisplayHint(int hint) {
7278 }
7279
7280 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007281 * Dispatch a window visibility change down the view hierarchy.
7282 * ViewGroups should override to route to their children.
7283 *
7284 * @param visibility The new visibility of the window.
7285 *
Philip Milne6c8ea062012-04-03 17:38:43 -07007286 * @see #onWindowVisibilityChanged(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007287 */
7288 public void dispatchWindowVisibilityChanged(int visibility) {
7289 onWindowVisibilityChanged(visibility);
7290 }
7291
7292 /**
7293 * Called when the window containing has change its visibility
7294 * (between {@link #GONE}, {@link #INVISIBLE}, and {@link #VISIBLE}). Note
7295 * that this tells you whether or not your window is being made visible
7296 * to the window manager; this does <em>not</em> tell you whether or not
7297 * your window is obscured by other windows on the screen, even if it
7298 * is itself visible.
7299 *
7300 * @param visibility The new visibility of the window.
7301 */
7302 protected void onWindowVisibilityChanged(int visibility) {
Adam Powell8568c3a2010-04-19 14:26:11 -07007303 if (visibility == VISIBLE) {
7304 initialAwakenScrollBars();
7305 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007306 }
7307
7308 /**
7309 * Returns the current visibility of the window this view is attached to
7310 * (either {@link #GONE}, {@link #INVISIBLE}, or {@link #VISIBLE}).
7311 *
7312 * @return Returns the current visibility of the view's window.
7313 */
7314 public int getWindowVisibility() {
7315 return mAttachInfo != null ? mAttachInfo.mWindowVisibility : GONE;
7316 }
7317
7318 /**
7319 * Retrieve the overall visible display size in which the window this view is
7320 * attached to has been positioned in. This takes into account screen
7321 * decorations above the window, for both cases where the window itself
7322 * is being position inside of them or the window is being placed under
7323 * then and covered insets are used for the window to position its content
7324 * inside. In effect, this tells you the available area where content can
7325 * be placed and remain visible to users.
7326 *
7327 * <p>This function requires an IPC back to the window manager to retrieve
7328 * the requested information, so should not be used in performance critical
7329 * code like drawing.
7330 *
7331 * @param outRect Filled in with the visible display frame. If the view
7332 * is not attached to a window, this is simply the raw display size.
7333 */
7334 public void getWindowVisibleDisplayFrame(Rect outRect) {
7335 if (mAttachInfo != null) {
7336 try {
7337 mAttachInfo.mSession.getDisplayFrame(mAttachInfo.mWindow, outRect);
7338 } catch (RemoteException e) {
7339 return;
7340 }
7341 // XXX This is really broken, and probably all needs to be done
7342 // in the window manager, and we need to know more about whether
7343 // we want the area behind or in front of the IME.
7344 final Rect insets = mAttachInfo.mVisibleInsets;
7345 outRect.left += insets.left;
7346 outRect.top += insets.top;
7347 outRect.right -= insets.right;
7348 outRect.bottom -= insets.bottom;
7349 return;
7350 }
Jeff Brownbd6e1502012-08-28 03:27:37 -07007351 // The view is not attached to a display so we don't have a context.
7352 // Make a best guess about the display size.
7353 Display d = DisplayManagerGlobal.getInstance().getRealDisplay(Display.DEFAULT_DISPLAY);
Dianne Hackborn44bc17c2011-04-20 18:18:51 -07007354 d.getRectSize(outRect);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007355 }
7356
7357 /**
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007358 * Dispatch a notification about a resource configuration change down
7359 * the view hierarchy.
7360 * ViewGroups should override to route to their children.
7361 *
7362 * @param newConfig The new resource configuration.
7363 *
Philip Milne6c8ea062012-04-03 17:38:43 -07007364 * @see #onConfigurationChanged(android.content.res.Configuration)
Dianne Hackborne36d6e22010-02-17 19:46:25 -08007365 */
7366 public void dispatchConfigurationChanged(Configuration newConfig) {
7367 onConfigurationChanged(newConfig);
7368 }
7369
7370 /**
7371 * Called when the current configuration of the resources being used
7372 * by the application have changed. You can use this to decide when
7373 * to reload resources that can changed based on orientation and other
7374 * configuration characterstics. You only need to use this if you are
7375 * not relying on the normal {@link android.app.Activity} mechanism of
7376 * recreating the activity instance upon a configuration change.
7377 *
7378 * @param newConfig The new resource configuration.
7379 */
7380 protected void onConfigurationChanged(Configuration newConfig) {
7381 }
7382
7383 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007384 * Private function to aggregate all per-view attributes in to the view
7385 * root.
7386 */
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007387 void dispatchCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7388 performCollectViewAttributes(attachInfo, visibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007389 }
7390
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007391 void performCollectViewAttributes(AttachInfo attachInfo, int visibility) {
7392 if ((visibility & VISIBILITY_MASK) == VISIBLE) {
Joe Onorato664644d2011-01-23 17:53:23 -08007393 if ((mViewFlags & KEEP_SCREEN_ON) == KEEP_SCREEN_ON) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007394 attachInfo.mKeepScreenOn = true;
Joe Onorato664644d2011-01-23 17:53:23 -08007395 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007396 attachInfo.mSystemUiVisibility |= mSystemUiVisibility;
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007397 ListenerInfo li = mListenerInfo;
7398 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -07007399 attachInfo.mHasSystemUiListeners = true;
Joe Onorato664644d2011-01-23 17:53:23 -08007400 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007401 }
7402 }
7403
7404 void needGlobalAttributesUpdate(boolean force) {
Joe Onorato664644d2011-01-23 17:53:23 -08007405 final AttachInfo ai = mAttachInfo;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007406 if (ai != null) {
Joe Onorato664644d2011-01-23 17:53:23 -08007407 if (force || ai.mKeepScreenOn || (ai.mSystemUiVisibility != 0)
7408 || ai.mHasSystemUiListeners) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007409 ai.mRecomputeGlobalAttributes = true;
7410 }
7411 }
7412 }
7413
7414 /**
7415 * Returns whether the device is currently in touch mode. Touch mode is entered
7416 * once the user begins interacting with the device by touch, and affects various
7417 * things like whether focus is always visible to the user.
7418 *
7419 * @return Whether the device is in touch mode.
7420 */
7421 @ViewDebug.ExportedProperty
7422 public boolean isInTouchMode() {
7423 if (mAttachInfo != null) {
7424 return mAttachInfo.mInTouchMode;
7425 } else {
Dianne Hackborn6dd005b2011-07-18 13:22:50 -07007426 return ViewRootImpl.isInTouchMode();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007427 }
7428 }
7429
7430 /**
7431 * Returns the context the view is running in, through which it can
7432 * access the current theme, resources, etc.
7433 *
7434 * @return The view's Context.
7435 */
7436 @ViewDebug.CapturedViewProperty
7437 public final Context getContext() {
7438 return mContext;
7439 }
7440
7441 /**
7442 * Handle a key event before it is processed by any input method
7443 * associated with the view hierarchy. This can be used to intercept
7444 * key events in special situations before the IME consumes them; a
7445 * typical example would be handling the BACK key to update the application's
7446 * UI instead of allowing the IME to see it and close itself.
7447 *
7448 * @param keyCode The value in event.getKeyCode().
7449 * @param event Description of the key event.
7450 * @return If you handled the event, return true. If you want to allow the
7451 * event to be handled by the next receiver, return false.
7452 */
7453 public boolean onKeyPreIme(int keyCode, KeyEvent event) {
7454 return false;
7455 }
7456
7457 /**
Jeff Brown995e7742010-12-22 16:59:36 -08007458 * Default implementation of {@link KeyEvent.Callback#onKeyDown(int, KeyEvent)
7459 * KeyEvent.Callback.onKeyDown()}: perform press of the view
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007460 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or {@link KeyEvent#KEYCODE_ENTER}
7461 * is released, if the view is enabled and clickable.
7462 *
Jean Chalard405bc512012-05-29 19:12:34 +09007463 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7464 * although some may elect to do so in some situations. Do not rely on this to
7465 * catch software key presses.
7466 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007467 * @param keyCode A key code that represents the button pressed, from
7468 * {@link android.view.KeyEvent}.
7469 * @param event The KeyEvent object that defines the button action.
7470 */
7471 public boolean onKeyDown(int keyCode, KeyEvent event) {
7472 boolean result = false;
7473
7474 switch (keyCode) {
7475 case KeyEvent.KEYCODE_DPAD_CENTER:
7476 case KeyEvent.KEYCODE_ENTER: {
7477 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7478 return true;
7479 }
7480 // Long clickable items don't necessarily have to be clickable
7481 if (((mViewFlags & CLICKABLE) == CLICKABLE ||
7482 (mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) &&
7483 (event.getRepeatCount() == 0)) {
7484 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007485 checkForLongClick(0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007486 return true;
7487 }
7488 break;
7489 }
7490 }
7491 return result;
7492 }
7493
7494 /**
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007495 * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
7496 * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
7497 * the event).
Jean Chalard405bc512012-05-29 19:12:34 +09007498 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7499 * although some may elect to do so in some situations. Do not rely on this to
7500 * catch software key presses.
Dianne Hackborn83fe3f52009-09-12 23:38:30 -07007501 */
7502 public boolean onKeyLongPress(int keyCode, KeyEvent event) {
7503 return false;
7504 }
7505
7506 /**
Jeff Brown995e7742010-12-22 16:59:36 -08007507 * Default implementation of {@link KeyEvent.Callback#onKeyUp(int, KeyEvent)
7508 * KeyEvent.Callback.onKeyUp()}: perform clicking of the view
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007509 * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
7510 * {@link KeyEvent#KEYCODE_ENTER} is released.
Jean Chalard405bc512012-05-29 19:12:34 +09007511 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7512 * although some may elect to do so in some situations. Do not rely on this to
7513 * catch software key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007514 *
7515 * @param keyCode A key code that represents the button pressed, from
7516 * {@link android.view.KeyEvent}.
7517 * @param event The KeyEvent object that defines the button action.
7518 */
7519 public boolean onKeyUp(int keyCode, KeyEvent event) {
7520 boolean result = false;
7521
7522 switch (keyCode) {
7523 case KeyEvent.KEYCODE_DPAD_CENTER:
7524 case KeyEvent.KEYCODE_ENTER: {
7525 if ((mViewFlags & ENABLED_MASK) == DISABLED) {
7526 return true;
7527 }
7528 if ((mViewFlags & CLICKABLE) == CLICKABLE && isPressed()) {
7529 setPressed(false);
7530
7531 if (!mHasPerformedLongPress) {
7532 // This is a tap, so remove the longpress check
Maryam Garrett1549dd12009-12-15 16:06:36 -05007533 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007534
7535 result = performClick();
7536 }
7537 }
7538 break;
7539 }
7540 }
7541 return result;
7542 }
7543
7544 /**
7545 * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
7546 * KeyEvent.Callback.onKeyMultiple()}: always returns false (doesn't handle
7547 * the event).
Jean Chalard405bc512012-05-29 19:12:34 +09007548 * <p>Key presses in software keyboards will generally NOT trigger this listener,
7549 * although some may elect to do so in some situations. Do not rely on this to
7550 * catch software key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007551 *
7552 * @param keyCode A key code that represents the button pressed, from
7553 * {@link android.view.KeyEvent}.
7554 * @param repeatCount The number of times the action was made.
7555 * @param event The KeyEvent object that defines the button action.
7556 */
7557 public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
7558 return false;
7559 }
7560
7561 /**
Jeff Brown64da12a2011-01-04 19:57:47 -08007562 * Called on the focused view when a key shortcut event is not handled.
7563 * Override this method to implement local key shortcuts for the View.
7564 * Key shortcuts can also be implemented by setting the
7565 * {@link MenuItem#setShortcut(char, char) shortcut} property of menu items.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007566 *
7567 * @param keyCode The value in event.getKeyCode().
7568 * @param event Description of the key event.
7569 * @return If you handled the event, return true. If you want to allow the
7570 * event to be handled by the next receiver, return false.
7571 */
7572 public boolean onKeyShortcut(int keyCode, KeyEvent event) {
7573 return false;
7574 }
7575
7576 /**
7577 * Check whether the called view is a text editor, in which case it
7578 * would make sense to automatically display a soft input window for
7579 * it. Subclasses should override this if they implement
7580 * {@link #onCreateInputConnection(EditorInfo)} to return true if
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007581 * a call on that method would return a non-null InputConnection, and
7582 * they are really a first-class editor that the user would normally
7583 * start typing on when the go into a window containing your view.
Romain Guy8506ab42009-06-11 17:35:47 -07007584 *
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007585 * <p>The default implementation always returns false. This does
7586 * <em>not</em> mean that its {@link #onCreateInputConnection(EditorInfo)}
7587 * will not be called or the user can not otherwise perform edits on your
7588 * view; it is just a hint to the system that this is not the primary
7589 * purpose of this view.
Romain Guy8506ab42009-06-11 17:35:47 -07007590 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007591 * @return Returns true if this view is a text editor, else false.
7592 */
7593 public boolean onCheckIsTextEditor() {
7594 return false;
7595 }
Romain Guy8506ab42009-06-11 17:35:47 -07007596
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007597 /**
7598 * Create a new InputConnection for an InputMethod to interact
7599 * with the view. The default implementation returns null, since it doesn't
7600 * support input methods. You can override this to implement such support.
7601 * This is only needed for views that take focus and text input.
Romain Guy8506ab42009-06-11 17:35:47 -07007602 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007603 * <p>When implementing this, you probably also want to implement
7604 * {@link #onCheckIsTextEditor()} to indicate you will return a
7605 * non-null InputConnection.
7606 *
7607 * @param outAttrs Fill in with attribute information about the connection.
7608 */
7609 public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
7610 return null;
7611 }
7612
7613 /**
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007614 * Called by the {@link android.view.inputmethod.InputMethodManager}
7615 * when a view who is not the current
7616 * input connection target is trying to make a call on the manager. The
7617 * default implementation returns false; you can override this to return
7618 * true for certain views if you are performing InputConnection proxying
7619 * to them.
7620 * @param view The View that is making the InputMethodManager call.
7621 * @return Return true to allow the call, false to reject.
7622 */
7623 public boolean checkInputConnectionProxy(View view) {
7624 return false;
7625 }
Romain Guy8506ab42009-06-11 17:35:47 -07007626
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -07007627 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007628 * Show the context menu for this view. It is not safe to hold on to the
7629 * menu after returning from this method.
7630 *
Gilles Debunnef788a9f2010-07-22 10:17:23 -07007631 * You should normally not overload this method. Overload
7632 * {@link #onCreateContextMenu(ContextMenu)} or define an
7633 * {@link OnCreateContextMenuListener} to add items to the context menu.
7634 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007635 * @param menu The context menu to populate
7636 */
7637 public void createContextMenu(ContextMenu menu) {
7638 ContextMenuInfo menuInfo = getContextMenuInfo();
7639
7640 // Sets the current menu info so all items added to menu will have
7641 // my extra info set.
7642 ((MenuBuilder)menu).setCurrentMenuInfo(menuInfo);
7643
7644 onCreateContextMenu(menu);
Dianne Hackborn0500b3c2011-11-01 15:28:43 -07007645 ListenerInfo li = mListenerInfo;
7646 if (li != null && li.mOnCreateContextMenuListener != null) {
7647 li.mOnCreateContextMenuListener.onCreateContextMenu(menu, this, menuInfo);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007648 }
7649
7650 // Clear the extra information so subsequent items that aren't mine don't
7651 // have my extra info.
7652 ((MenuBuilder)menu).setCurrentMenuInfo(null);
7653
7654 if (mParent != null) {
7655 mParent.createContextMenu(menu);
7656 }
7657 }
7658
7659 /**
7660 * Views should implement this if they have extra information to associate
7661 * with the context menu. The return result is supplied as a parameter to
7662 * the {@link OnCreateContextMenuListener#onCreateContextMenu(ContextMenu, View, ContextMenuInfo)}
7663 * callback.
7664 *
7665 * @return Extra information about the item for which the context menu
7666 * should be shown. This information will vary across different
7667 * subclasses of View.
7668 */
7669 protected ContextMenuInfo getContextMenuInfo() {
7670 return null;
7671 }
7672
7673 /**
7674 * Views should implement this if the view itself is going to add items to
7675 * the context menu.
7676 *
7677 * @param menu the context menu to populate
7678 */
7679 protected void onCreateContextMenu(ContextMenu menu) {
7680 }
7681
7682 /**
7683 * Implement this method to handle trackball motion events. The
7684 * <em>relative</em> movement of the trackball since the last event
7685 * can be retrieve with {@link MotionEvent#getX MotionEvent.getX()} and
7686 * {@link MotionEvent#getY MotionEvent.getY()}. These are normalized so
7687 * that a movement of 1 corresponds to the user pressing one DPAD key (so
7688 * they will often be fractional values, representing the more fine-grained
7689 * movement information available from a trackball).
7690 *
7691 * @param event The motion event.
7692 * @return True if the event was handled, false otherwise.
7693 */
7694 public boolean onTrackballEvent(MotionEvent event) {
7695 return false;
7696 }
7697
7698 /**
Jeff Browncb1404e2011-01-15 18:14:15 -08007699 * Implement this method to handle generic motion events.
7700 * <p>
Jeff Brown33bbfd22011-02-24 20:55:35 -08007701 * Generic motion events describe joystick movements, mouse hovers, track pad
7702 * touches, scroll wheel movements and other input events. The
Jeff Browncb1404e2011-01-15 18:14:15 -08007703 * {@link MotionEvent#getSource() source} of the motion event specifies
7704 * the class of input that was received. Implementations of this method
7705 * must examine the bits in the source before processing the event.
7706 * The following code example shows how this is done.
Jeff Brown33bbfd22011-02-24 20:55:35 -08007707 * </p><p>
7708 * Generic motion events with source class {@link InputDevice#SOURCE_CLASS_POINTER}
7709 * are delivered to the view under the pointer. All other generic motion events are
7710 * delivered to the focused view.
Jeff Browncb1404e2011-01-15 18:14:15 -08007711 * </p>
Scott Mainb303d832011-10-12 16:45:18 -07007712 * <pre> public boolean onGenericMotionEvent(MotionEvent event) {
Jeff Browncb1404e2011-01-15 18:14:15 -08007713 * if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08007714 * if (event.getAction() == MotionEvent.ACTION_MOVE) {
7715 * // process the joystick movement...
7716 * return true;
7717 * }
7718 * }
7719 * if ((event.getSource() &amp; InputDevice.SOURCE_CLASS_POINTER) != 0) {
7720 * switch (event.getAction()) {
7721 * case MotionEvent.ACTION_HOVER_MOVE:
7722 * // process the mouse hover movement...
7723 * return true;
7724 * case MotionEvent.ACTION_SCROLL:
7725 * // process the scroll wheel movement...
7726 * return true;
7727 * }
Jeff Browncb1404e2011-01-15 18:14:15 -08007728 * }
7729 * return super.onGenericMotionEvent(event);
Scott Mainb303d832011-10-12 16:45:18 -07007730 * }</pre>
Jeff Browncb1404e2011-01-15 18:14:15 -08007731 *
7732 * @param event The generic motion event being processed.
Jeff Browna032cc02011-03-07 16:56:21 -08007733 * @return True if the event was handled, false otherwise.
Jeff Browncb1404e2011-01-15 18:14:15 -08007734 */
7735 public boolean onGenericMotionEvent(MotionEvent event) {
7736 return false;
7737 }
7738
7739 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007740 * Implement this method to handle hover events.
7741 * <p>
Jeff Brown10b62902011-06-20 16:40:37 -07007742 * This method is called whenever a pointer is hovering into, over, or out of the
7743 * bounds of a view and the view is not currently being touched.
7744 * Hover events are represented as pointer events with action
7745 * {@link MotionEvent#ACTION_HOVER_ENTER}, {@link MotionEvent#ACTION_HOVER_MOVE},
7746 * or {@link MotionEvent#ACTION_HOVER_EXIT}.
7747 * </p>
7748 * <ul>
7749 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_ENTER}
7750 * when the pointer enters the bounds of the view.</li>
7751 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_MOVE}
7752 * when the pointer has already entered the bounds of the view and has moved.</li>
7753 * <li>The view receives a hover event with action {@link MotionEvent#ACTION_HOVER_EXIT}
7754 * when the pointer has exited the bounds of the view or when the pointer is
7755 * about to go down due to a button click, tap, or similar user action that
7756 * causes the view to be touched.</li>
7757 * </ul>
7758 * <p>
7759 * The view should implement this method to return true to indicate that it is
7760 * handling the hover event, such as by changing its drawable state.
Jeff Browna032cc02011-03-07 16:56:21 -08007761 * </p><p>
Jeff Brown10b62902011-06-20 16:40:37 -07007762 * The default implementation calls {@link #setHovered} to update the hovered state
7763 * of the view when a hover enter or hover exit event is received, if the view
Jeff Browna1b24182011-07-28 13:38:24 -07007764 * is enabled and is clickable. The default implementation also sends hover
7765 * accessibility events.
Jeff Browna032cc02011-03-07 16:56:21 -08007766 * </p>
7767 *
7768 * @param event The motion event that describes the hover.
Jeff Brown10b62902011-06-20 16:40:37 -07007769 * @return True if the view handled the hover event.
7770 *
7771 * @see #isHovered
7772 * @see #setHovered
7773 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007774 */
7775 public boolean onHoverEvent(MotionEvent event) {
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007776 // The root view may receive hover (or touch) events that are outside the bounds of
7777 // the window. This code ensures that we only send accessibility events for
7778 // hovers that are actually within the bounds of the root view.
Svetoslav Ganov42138042012-03-20 11:51:39 -07007779 final int action = event.getActionMasked();
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007780 if (!mSendingHoverAccessibilityEvents) {
7781 if ((action == MotionEvent.ACTION_HOVER_ENTER
7782 || action == MotionEvent.ACTION_HOVER_MOVE)
7783 && !hasHoveredChild()
7784 && pointInView(event.getX(), event.getY())) {
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07007785 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007786 mSendingHoverAccessibilityEvents = true;
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007787 }
7788 } else {
7789 if (action == MotionEvent.ACTION_HOVER_EXIT
Svetoslav Ganov42138042012-03-20 11:51:39 -07007790 || (action == MotionEvent.ACTION_MOVE
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007791 && !pointInView(event.getX(), event.getY()))) {
7792 mSendingHoverAccessibilityEvents = false;
Svetoslav Ganov8ffe8b32012-06-15 10:31:31 -07007793 sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007794 // If the window does not have input focus we take away accessibility
7795 // focus as soon as the user stop hovering over the view.
Jeff Brown59a422e2012-04-19 15:19:19 -07007796 if (mAttachInfo != null && !mAttachInfo.mHasWindowFocus) {
Svetoslav Ganov45a02e02012-06-17 15:07:29 -07007797 getViewRootImpl().setAccessibilityFocus(null, null);
Svetoslav Ganov42138042012-03-20 11:51:39 -07007798 }
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007799 }
Jeff Browna1b24182011-07-28 13:38:24 -07007800 }
7801
Jeff Brown87b7f802011-06-21 18:35:45 -07007802 if (isHoverable()) {
Svetoslav Ganov4c1c1012011-08-31 18:39:18 -07007803 switch (action) {
Jeff Brown10b62902011-06-20 16:40:37 -07007804 case MotionEvent.ACTION_HOVER_ENTER:
7805 setHovered(true);
7806 break;
7807 case MotionEvent.ACTION_HOVER_EXIT:
7808 setHovered(false);
7809 break;
7810 }
Jeff Browna1b24182011-07-28 13:38:24 -07007811
7812 // Dispatch the event to onGenericMotionEvent before returning true.
7813 // This is to provide compatibility with existing applications that
7814 // handled HOVER_MOVE events in onGenericMotionEvent and that would
7815 // break because of the new default handling for hoverable views
7816 // in onHoverEvent.
7817 // Note that onGenericMotionEvent will be called by default when
7818 // onHoverEvent returns false (refer to dispatchGenericMotionEvent).
7819 dispatchGenericMotionEventInternal(event);
Jeff Brown10b62902011-06-20 16:40:37 -07007820 return true;
Jeff Browna032cc02011-03-07 16:56:21 -08007821 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07007822
Svetoslav Ganov736c2752011-04-22 18:30:36 -07007823 return false;
Jeff Browna032cc02011-03-07 16:56:21 -08007824 }
7825
7826 /**
Jeff Brown87b7f802011-06-21 18:35:45 -07007827 * Returns true if the view should handle {@link #onHoverEvent}
7828 * by calling {@link #setHovered} to change its hovered state.
7829 *
7830 * @return True if the view is hoverable.
7831 */
7832 private boolean isHoverable() {
7833 final int viewFlags = mViewFlags;
7834 if ((viewFlags & ENABLED_MASK) == DISABLED) {
7835 return false;
7836 }
7837
7838 return (viewFlags & CLICKABLE) == CLICKABLE
7839 || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
7840 }
7841
7842 /**
Jeff Browna032cc02011-03-07 16:56:21 -08007843 * Returns true if the view is currently hovered.
7844 *
7845 * @return True if the view is currently hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007846 *
7847 * @see #setHovered
7848 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007849 */
Jeff Brown10b62902011-06-20 16:40:37 -07007850 @ViewDebug.ExportedProperty
Jeff Browna032cc02011-03-07 16:56:21 -08007851 public boolean isHovered() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007852 return (mPrivateFlags & PFLAG_HOVERED) != 0;
Jeff Browna032cc02011-03-07 16:56:21 -08007853 }
7854
7855 /**
7856 * Sets whether the view is currently hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007857 * <p>
7858 * Calling this method also changes the drawable state of the view. This
7859 * enables the view to react to hover by using different drawable resources
7860 * to change its appearance.
7861 * </p><p>
7862 * The {@link #onHoverChanged} method is called when the hovered state changes.
7863 * </p>
Jeff Browna032cc02011-03-07 16:56:21 -08007864 *
7865 * @param hovered True if the view is hovered.
Jeff Brown10b62902011-06-20 16:40:37 -07007866 *
7867 * @see #isHovered
7868 * @see #onHoverChanged
Jeff Browna032cc02011-03-07 16:56:21 -08007869 */
7870 public void setHovered(boolean hovered) {
7871 if (hovered) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007872 if ((mPrivateFlags & PFLAG_HOVERED) == 0) {
7873 mPrivateFlags |= PFLAG_HOVERED;
Jeff Browna032cc02011-03-07 16:56:21 -08007874 refreshDrawableState();
Jeff Brown10b62902011-06-20 16:40:37 -07007875 onHoverChanged(true);
Jeff Browna032cc02011-03-07 16:56:21 -08007876 }
7877 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007878 if ((mPrivateFlags & PFLAG_HOVERED) != 0) {
7879 mPrivateFlags &= ~PFLAG_HOVERED;
Jeff Browna032cc02011-03-07 16:56:21 -08007880 refreshDrawableState();
Jeff Brown10b62902011-06-20 16:40:37 -07007881 onHoverChanged(false);
Jeff Browna032cc02011-03-07 16:56:21 -08007882 }
7883 }
7884 }
7885
7886 /**
Jeff Brown10b62902011-06-20 16:40:37 -07007887 * Implement this method to handle hover state changes.
7888 * <p>
7889 * This method is called whenever the hover state changes as a result of a
7890 * call to {@link #setHovered}.
7891 * </p>
7892 *
7893 * @param hovered The current hover state, as returned by {@link #isHovered}.
7894 *
7895 * @see #isHovered
7896 * @see #setHovered
7897 */
7898 public void onHoverChanged(boolean hovered) {
Jeff Brown10b62902011-06-20 16:40:37 -07007899 }
7900
7901 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007902 * Implement this method to handle touch screen motion events.
7903 *
7904 * @param event The motion event.
7905 * @return True if the event was handled, false otherwise.
7906 */
7907 public boolean onTouchEvent(MotionEvent event) {
7908 final int viewFlags = mViewFlags;
7909
7910 if ((viewFlags & ENABLED_MASK) == DISABLED) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007911 if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
Adam Powell4d6f0662012-02-21 15:11:11 -08007912 setPressed(false);
Svetoslav Ganov77b80c02011-03-15 20:52:58 -07007913 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007914 // A disabled view that is clickable still consumes the touch
7915 // events, it just doesn't respond to them.
7916 return (((viewFlags & CLICKABLE) == CLICKABLE ||
7917 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
7918 }
7919
7920 if (mTouchDelegate != null) {
7921 if (mTouchDelegate.onTouchEvent(event)) {
7922 return true;
7923 }
7924 }
7925
7926 if (((viewFlags & CLICKABLE) == CLICKABLE ||
7927 (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
7928 switch (event.getAction()) {
7929 case MotionEvent.ACTION_UP:
Dianne Hackborn4702a852012-08-17 15:18:29 -07007930 boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
7931 if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007932 // take focus if we don't have it already and we should in
7933 // touch mode.
7934 boolean focusTaken = false;
7935 if (isFocusable() && isFocusableInTouchMode() && !isFocused()) {
7936 focusTaken = requestFocus();
7937 }
7938
Dianne Hackbornbe1f6222011-01-20 15:24:28 -08007939 if (prepressed) {
7940 // The button is being released before we actually
7941 // showed it as pressed. Make it show the pressed
7942 // state now (before scheduling the click) to ensure
7943 // the user sees it.
Adam Powell4d6f0662012-02-21 15:11:11 -08007944 setPressed(true);
Dianne Hackbornbe1f6222011-01-20 15:24:28 -08007945 }
Joe Malin32736f02011-01-19 16:14:20 -08007946
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007947 if (!mHasPerformedLongPress) {
7948 // This is a tap, so remove the longpress check
Maryam Garrett1549dd12009-12-15 16:06:36 -05007949 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007950
7951 // Only perform take click actions if we were in the pressed state
7952 if (!focusTaken) {
Adam Powella35d7682010-03-12 14:48:13 -08007953 // Use a Runnable and post this rather than calling
7954 // performClick directly. This lets other visual state
7955 // of the view update before click actions start.
7956 if (mPerformClick == null) {
7957 mPerformClick = new PerformClick();
7958 }
7959 if (!post(mPerformClick)) {
7960 performClick();
7961 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007962 }
7963 }
7964
7965 if (mUnsetPressedState == null) {
7966 mUnsetPressedState = new UnsetPressedState();
7967 }
7968
Adam Powelle14579b2009-12-16 18:39:52 -08007969 if (prepressed) {
Adam Powelle14579b2009-12-16 18:39:52 -08007970 postDelayed(mUnsetPressedState,
7971 ViewConfiguration.getPressedStateDuration());
7972 } else if (!post(mUnsetPressedState)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007973 // If the post failed, unpress right now
7974 mUnsetPressedState.run();
7975 }
Adam Powelle14579b2009-12-16 18:39:52 -08007976 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08007977 }
7978 break;
7979
7980 case MotionEvent.ACTION_DOWN:
Adam Powell3b023392010-03-11 16:30:28 -08007981 mHasPerformedLongPress = false;
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007982
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07007983 if (performButtonActionOnTouchDown(event)) {
7984 break;
7985 }
7986
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007987 // Walk up the hierarchy to determine if we're inside a scrolling container.
Adam Powell10298662011-08-14 18:26:30 -07007988 boolean isInScrollingContainer = isInScrollingContainer();
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007989
7990 // For views inside a scrolling container, delay the pressed feedback for
7991 // a short period in case this is a scroll.
7992 if (isInScrollingContainer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07007993 mPrivateFlags |= PFLAG_PREPRESSED;
Patrick Dubroye0a799a2011-05-04 16:19:22 -07007994 if (mPendingCheckForTap == null) {
7995 mPendingCheckForTap = new CheckForTap();
7996 }
7997 postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());
7998 } else {
7999 // Not inside a scrolling container, so show the feedback right away
Adam Powell4d6f0662012-02-21 15:11:11 -08008000 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -07008001 checkForLongClick(0);
8002 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008003 break;
8004
8005 case MotionEvent.ACTION_CANCEL:
Adam Powell4d6f0662012-02-21 15:11:11 -08008006 setPressed(false);
Adam Powelle14579b2009-12-16 18:39:52 -08008007 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008008 break;
8009
8010 case MotionEvent.ACTION_MOVE:
8011 final int x = (int) event.getX();
8012 final int y = (int) event.getY();
8013
8014 // Be lenient about moving outside of buttons
Chet Haasec3aa3612010-06-17 08:50:37 -07008015 if (!pointInView(x, y, mTouchSlop)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008016 // Outside button
Adam Powelle14579b2009-12-16 18:39:52 -08008017 removeTapCallback();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008018 if ((mPrivateFlags & PFLAG_PRESSED) != 0) {
Adam Powelle14579b2009-12-16 18:39:52 -08008019 // Remove any future long press/tap checks
Maryam Garrett1549dd12009-12-15 16:06:36 -05008020 removeLongPressCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008021
Adam Powell4d6f0662012-02-21 15:11:11 -08008022 setPressed(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008023 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008024 }
8025 break;
8026 }
8027 return true;
8028 }
8029
8030 return false;
8031 }
8032
8033 /**
Adam Powell10298662011-08-14 18:26:30 -07008034 * @hide
8035 */
8036 public boolean isInScrollingContainer() {
8037 ViewParent p = getParent();
8038 while (p != null && p instanceof ViewGroup) {
8039 if (((ViewGroup) p).shouldDelayChildPressedState()) {
8040 return true;
8041 }
8042 p = p.getParent();
8043 }
8044 return false;
8045 }
8046
8047 /**
Maryam Garrett1549dd12009-12-15 16:06:36 -05008048 * Remove the longpress detection timer.
8049 */
8050 private void removeLongPressCallback() {
8051 if (mPendingCheckForLongPress != null) {
8052 removeCallbacks(mPendingCheckForLongPress);
8053 }
8054 }
Adam Powell3cb8b632011-01-21 15:34:14 -08008055
8056 /**
8057 * Remove the pending click action
8058 */
8059 private void removePerformClickCallback() {
8060 if (mPerformClick != null) {
8061 removeCallbacks(mPerformClick);
8062 }
8063 }
8064
Adam Powelle14579b2009-12-16 18:39:52 -08008065 /**
Romain Guya440b002010-02-24 15:57:54 -08008066 * Remove the prepress detection timer.
8067 */
8068 private void removeUnsetPressCallback() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008069 if ((mPrivateFlags & PFLAG_PRESSED) != 0 && mUnsetPressedState != null) {
Romain Guya440b002010-02-24 15:57:54 -08008070 setPressed(false);
8071 removeCallbacks(mUnsetPressedState);
8072 }
8073 }
8074
8075 /**
Adam Powelle14579b2009-12-16 18:39:52 -08008076 * Remove the tap detection timer.
8077 */
8078 private void removeTapCallback() {
8079 if (mPendingCheckForTap != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008080 mPrivateFlags &= ~PFLAG_PREPRESSED;
Adam Powelle14579b2009-12-16 18:39:52 -08008081 removeCallbacks(mPendingCheckForTap);
8082 }
8083 }
Maryam Garrett1549dd12009-12-15 16:06:36 -05008084
8085 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008086 * Cancels a pending long press. Your subclass can use this if you
8087 * want the context menu to come up if the user presses and holds
8088 * at the same place, but you don't want it to come up if they press
8089 * and then move around enough to cause scrolling.
8090 */
8091 public void cancelLongPress() {
Maryam Garrett1549dd12009-12-15 16:06:36 -05008092 removeLongPressCallback();
Adam Powell732ebb12010-02-02 15:28:14 -08008093
8094 /*
8095 * The prepressed state handled by the tap callback is a display
8096 * construct, but the tap callback will post a long press callback
8097 * less its own timeout. Remove it here.
8098 */
8099 removeTapCallback();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008100 }
8101
8102 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -07008103 * Remove the pending callback for sending a
8104 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
8105 */
8106 private void removeSendViewScrolledAccessibilityEventCallback() {
8107 if (mSendViewScrolledAccessibilityEvent != null) {
8108 removeCallbacks(mSendViewScrolledAccessibilityEvent);
Svetoslav Ganov4a812ae2012-05-29 16:46:10 -07008109 mSendViewScrolledAccessibilityEvent.mIsPending = false;
Svetoslav Ganova0156172011-06-26 17:55:44 -07008110 }
8111 }
8112
8113 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008114 * Sets the TouchDelegate for this View.
8115 */
8116 public void setTouchDelegate(TouchDelegate delegate) {
8117 mTouchDelegate = delegate;
8118 }
8119
8120 /**
8121 * Gets the TouchDelegate for this View.
8122 */
8123 public TouchDelegate getTouchDelegate() {
8124 return mTouchDelegate;
8125 }
8126
8127 /**
8128 * Set flags controlling behavior of this view.
8129 *
8130 * @param flags Constant indicating the value which should be set
8131 * @param mask Constant indicating the bit range that should be changed
8132 */
8133 void setFlags(int flags, int mask) {
8134 int old = mViewFlags;
8135 mViewFlags = (mViewFlags & ~mask) | (flags & mask);
8136
8137 int changed = mViewFlags ^ old;
8138 if (changed == 0) {
8139 return;
8140 }
8141 int privateFlags = mPrivateFlags;
8142
8143 /* Check if the FOCUSABLE bit has changed */
8144 if (((changed & FOCUSABLE_MASK) != 0) &&
Dianne Hackborn4702a852012-08-17 15:18:29 -07008145 ((privateFlags & PFLAG_HAS_BOUNDS) !=0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008146 if (((old & FOCUSABLE_MASK) == FOCUSABLE)
Dianne Hackborn4702a852012-08-17 15:18:29 -07008147 && ((privateFlags & PFLAG_FOCUSED) != 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008148 /* Give up focus if we are no longer focusable */
8149 clearFocus();
8150 } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
Dianne Hackborn4702a852012-08-17 15:18:29 -07008151 && ((privateFlags & PFLAG_FOCUSED) == 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008152 /*
8153 * Tell the view system that we are now available to take focus
8154 * if no one else already has it.
8155 */
8156 if (mParent != null) mParent.focusableViewAvailable(this);
8157 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07008158 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8159 notifyAccessibilityStateChanged();
8160 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008161 }
8162
8163 if ((flags & VISIBILITY_MASK) == VISIBLE) {
8164 if ((changed & VISIBILITY_MASK) != 0) {
8165 /*
Chet Haase4324ead2011-08-24 21:31:03 -07008166 * If this view is becoming visible, invalidate it in case it changed while
Chet Haaseaceafe62011-08-26 15:44:33 -07008167 * it was not visible. Marking it drawn ensures that the invalidation will
8168 * go through.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008169 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07008170 mPrivateFlags |= PFLAG_DRAWN;
Chet Haase4324ead2011-08-24 21:31:03 -07008171 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008172
8173 needGlobalAttributesUpdate(true);
8174
8175 // a view becoming visible is worth notifying the parent
8176 // about in case nothing has focus. even if this specific view
8177 // isn't focusable, it may contain something that is, so let
8178 // the root view try to give this focus if nothing else does.
8179 if ((mParent != null) && (mBottom > mTop) && (mRight > mLeft)) {
8180 mParent.focusableViewAvailable(this);
8181 }
8182 }
8183 }
8184
8185 /* Check if the GONE bit has changed */
8186 if ((changed & GONE) != 0) {
8187 needGlobalAttributesUpdate(false);
8188 requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008189
Romain Guyecd80ee2009-12-03 17:13:02 -08008190 if (((mViewFlags & VISIBILITY_MASK) == GONE)) {
8191 if (hasFocus()) clearFocus();
Svetoslav Ganov42138042012-03-20 11:51:39 -07008192 clearAccessibilityFocus();
Romain Guyecd80ee2009-12-03 17:13:02 -08008193 destroyDrawingCache();
Chet Haaseaceafe62011-08-26 15:44:33 -07008194 if (mParent instanceof View) {
8195 // GONE views noop invalidation, so invalidate the parent
8196 ((View) mParent).invalidate(true);
8197 }
8198 // Mark the view drawn to ensure that it gets invalidated properly the next
8199 // time it is visible and gets invalidated
Dianne Hackborn4702a852012-08-17 15:18:29 -07008200 mPrivateFlags |= PFLAG_DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008201 }
8202 if (mAttachInfo != null) {
8203 mAttachInfo.mViewVisibilityChanged = true;
8204 }
8205 }
8206
8207 /* Check if the VISIBLE bit has changed */
8208 if ((changed & INVISIBLE) != 0) {
8209 needGlobalAttributesUpdate(false);
Chet Haasec8a9a702011-06-17 12:13:42 -07008210 /*
8211 * If this view is becoming invisible, set the DRAWN flag so that
8212 * the next invalidate() will not be skipped.
8213 */
Dianne Hackborn4702a852012-08-17 15:18:29 -07008214 mPrivateFlags |= PFLAG_DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008215
8216 if (((mViewFlags & VISIBILITY_MASK) == INVISIBLE) && hasFocus()) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07008217 // root view becoming invisible shouldn't clear focus and accessibility focus
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008218 if (getRootView() != this) {
8219 clearFocus();
Svetoslav Ganov42138042012-03-20 11:51:39 -07008220 clearAccessibilityFocus();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008221 }
8222 }
8223 if (mAttachInfo != null) {
8224 mAttachInfo.mViewVisibilityChanged = true;
8225 }
8226 }
8227
Adam Powell326d8082009-12-09 15:10:07 -08008228 if ((changed & VISIBILITY_MASK) != 0) {
Chet Haase5e25c2c2010-09-16 11:15:56 -07008229 if (mParent instanceof ViewGroup) {
Romain Guyfe455af2012-02-15 16:40:20 -08008230 ((ViewGroup) mParent).onChildVisibilityChanged(this,
8231 (changed & VISIBILITY_MASK), (flags & VISIBILITY_MASK));
Romain Guy0fd89bf2011-01-26 15:41:30 -08008232 ((View) mParent).invalidate(true);
Chet Haasee4e6e202011-08-29 14:34:30 -07008233 } else if (mParent != null) {
8234 mParent.invalidateChild(this, null);
Chet Haase5e25c2c2010-09-16 11:15:56 -07008235 }
Adam Powell326d8082009-12-09 15:10:07 -08008236 dispatchVisibilityChanged(this, (flags & VISIBILITY_MASK));
8237 }
8238
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008239 if ((changed & WILL_NOT_CACHE_DRAWING) != 0) {
8240 destroyDrawingCache();
8241 }
8242
8243 if ((changed & DRAWING_CACHE_ENABLED) != 0) {
8244 destroyDrawingCache();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008245 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
Romain Guy0fd89bf2011-01-26 15:41:30 -08008246 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008247 }
8248
8249 if ((changed & DRAWING_CACHE_QUALITY_MASK) != 0) {
8250 destroyDrawingCache();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008251 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008252 }
8253
8254 if ((changed & DRAW_MASK) != 0) {
8255 if ((mViewFlags & WILL_NOT_DRAW) != 0) {
Philip Milne6c8ea062012-04-03 17:38:43 -07008256 if (mBackground != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008257 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
8258 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008259 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008260 mPrivateFlags |= PFLAG_SKIP_DRAW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008261 }
8262 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07008263 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008264 }
8265 requestLayout();
Romain Guy0fd89bf2011-01-26 15:41:30 -08008266 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008267 }
8268
8269 if ((changed & KEEP_SCREEN_ON) != 0) {
Joe Onorato664644d2011-01-23 17:53:23 -08008270 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008271 mParent.recomputeViewAttributes(this);
8272 }
8273 }
Svetoslav Ganov42138042012-03-20 11:51:39 -07008274
8275 if (AccessibilityManager.getInstance(mContext).isEnabled()
8276 && ((changed & FOCUSABLE) != 0 || (changed & CLICKABLE) != 0
8277 || (changed & LONG_CLICKABLE) != 0 || (changed & ENABLED) != 0)) {
8278 notifyAccessibilityStateChanged();
8279 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008280 }
8281
8282 /**
8283 * Change the view's z order in the tree, so it's on top of other sibling
8284 * views
8285 */
8286 public void bringToFront() {
8287 if (mParent != null) {
8288 mParent.bringChildToFront(this);
8289 }
8290 }
8291
8292 /**
8293 * This is called in response to an internal scroll in this view (i.e., the
8294 * view scrolled its own contents). This is typically as a result of
8295 * {@link #scrollBy(int, int)} or {@link #scrollTo(int, int)} having been
8296 * called.
8297 *
8298 * @param l Current horizontal scroll origin.
8299 * @param t Current vertical scroll origin.
8300 * @param oldl Previous horizontal scroll origin.
8301 * @param oldt Previous vertical scroll origin.
8302 */
8303 protected void onScrollChanged(int l, int t, int oldl, int oldt) {
Svetoslav Ganova0156172011-06-26 17:55:44 -07008304 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
8305 postSendViewScrolledAccessibilityEventCallback();
8306 }
8307
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008308 mBackgroundSizeChanged = true;
8309
8310 final AttachInfo ai = mAttachInfo;
8311 if (ai != null) {
8312 ai.mViewScrollChanged = true;
8313 }
8314 }
8315
8316 /**
Chet Haase21cd1382010-09-01 17:42:29 -07008317 * Interface definition for a callback to be invoked when the layout bounds of a view
8318 * changes due to layout processing.
8319 */
8320 public interface OnLayoutChangeListener {
8321 /**
8322 * Called when the focus state of a view has changed.
8323 *
8324 * @param v The view whose state has changed.
8325 * @param left The new value of the view's left property.
8326 * @param top The new value of the view's top property.
8327 * @param right The new value of the view's right property.
8328 * @param bottom The new value of the view's bottom property.
8329 * @param oldLeft The previous value of the view's left property.
8330 * @param oldTop The previous value of the view's top property.
8331 * @param oldRight The previous value of the view's right property.
8332 * @param oldBottom The previous value of the view's bottom property.
8333 */
8334 void onLayoutChange(View v, int left, int top, int right, int bottom,
8335 int oldLeft, int oldTop, int oldRight, int oldBottom);
8336 }
8337
8338 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008339 * This is called during layout when the size of this view has changed. If
8340 * you were just added to the view hierarchy, you're called with the old
8341 * values of 0.
8342 *
8343 * @param w Current width of this view.
8344 * @param h Current height of this view.
8345 * @param oldw Old width of this view.
8346 * @param oldh Old height of this view.
8347 */
8348 protected void onSizeChanged(int w, int h, int oldw, int oldh) {
8349 }
8350
8351 /**
8352 * Called by draw to draw the child views. This may be overridden
8353 * by derived classes to gain control just before its children are drawn
8354 * (but after its own view has been drawn).
8355 * @param canvas the canvas on which to draw the view
8356 */
8357 protected void dispatchDraw(Canvas canvas) {
Svetoslav Ganov42138042012-03-20 11:51:39 -07008358
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008359 }
8360
8361 /**
8362 * Gets the parent of this view. Note that the parent is a
8363 * ViewParent and not necessarily a View.
8364 *
8365 * @return Parent of this view.
8366 */
8367 public final ViewParent getParent() {
8368 return mParent;
8369 }
8370
8371 /**
Chet Haasecca2c982011-05-20 14:34:18 -07008372 * Set the horizontal scrolled position of your view. This will cause a call to
8373 * {@link #onScrollChanged(int, int, int, int)} and the view will be
8374 * invalidated.
8375 * @param value the x position to scroll to
8376 */
8377 public void setScrollX(int value) {
8378 scrollTo(value, mScrollY);
8379 }
8380
8381 /**
8382 * Set the vertical scrolled position of your view. This will cause a call to
8383 * {@link #onScrollChanged(int, int, int, int)} and the view will be
8384 * invalidated.
8385 * @param value the y position to scroll to
8386 */
8387 public void setScrollY(int value) {
8388 scrollTo(mScrollX, value);
8389 }
8390
8391 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008392 * Return the scrolled left position of this view. This is the left edge of
8393 * the displayed part of your view. You do not need to draw any pixels
8394 * farther left, since those are outside of the frame of your view on
8395 * screen.
8396 *
8397 * @return The left edge of the displayed part of your view, in pixels.
8398 */
8399 public final int getScrollX() {
8400 return mScrollX;
8401 }
8402
8403 /**
8404 * Return the scrolled top position of this view. This is the top edge of
8405 * the displayed part of your view. You do not need to draw any pixels above
8406 * it, since those are outside of the frame of your view on screen.
8407 *
8408 * @return The top edge of the displayed part of your view, in pixels.
8409 */
8410 public final int getScrollY() {
8411 return mScrollY;
8412 }
8413
8414 /**
8415 * Return the width of the your view.
8416 *
8417 * @return The width of your view, in pixels.
8418 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07008419 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008420 public final int getWidth() {
8421 return mRight - mLeft;
8422 }
8423
8424 /**
8425 * Return the height of your view.
8426 *
8427 * @return The height of your view, in pixels.
8428 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -07008429 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008430 public final int getHeight() {
8431 return mBottom - mTop;
8432 }
8433
8434 /**
8435 * Return the visible drawing bounds of your view. Fills in the output
8436 * rectangle with the values from getScrollX(), getScrollY(),
8437 * getWidth(), and getHeight().
8438 *
8439 * @param outRect The (scrolled) drawing bounds of the view.
8440 */
8441 public void getDrawingRect(Rect outRect) {
8442 outRect.left = mScrollX;
8443 outRect.top = mScrollY;
8444 outRect.right = mScrollX + (mRight - mLeft);
8445 outRect.bottom = mScrollY + (mBottom - mTop);
8446 }
8447
8448 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008449 * Like {@link #getMeasuredWidthAndState()}, but only returns the
8450 * raw width component (that is the result is masked by
8451 * {@link #MEASURED_SIZE_MASK}).
8452 *
8453 * @return The raw measured width of this view.
8454 */
8455 public final int getMeasuredWidth() {
8456 return mMeasuredWidth & MEASURED_SIZE_MASK;
8457 }
8458
8459 /**
8460 * Return the full width measurement information for this view as computed
Romain Guy5c22a8c2011-05-13 11:48:45 -07008461 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
Dianne Hackborn189ee182010-12-02 21:48:53 -08008462 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008463 * This should be used during measurement and layout calculations only. Use
8464 * {@link #getWidth()} to see how wide a view is after layout.
8465 *
Dianne Hackborn189ee182010-12-02 21:48:53 -08008466 * @return The measured width of this view as a bit mask.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008467 */
Dianne Hackborn189ee182010-12-02 21:48:53 -08008468 public final int getMeasuredWidthAndState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008469 return mMeasuredWidth;
8470 }
8471
8472 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008473 * Like {@link #getMeasuredHeightAndState()}, but only returns the
8474 * raw width component (that is the result is masked by
8475 * {@link #MEASURED_SIZE_MASK}).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008476 *
Dianne Hackborn189ee182010-12-02 21:48:53 -08008477 * @return The raw measured height of this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008478 */
8479 public final int getMeasuredHeight() {
Dianne Hackborn189ee182010-12-02 21:48:53 -08008480 return mMeasuredHeight & MEASURED_SIZE_MASK;
8481 }
8482
8483 /**
8484 * Return the full height measurement information for this view as computed
Romain Guy5c22a8c2011-05-13 11:48:45 -07008485 * by the most recent call to {@link #measure(int, int)}. This result is a bit mask
Dianne Hackborn189ee182010-12-02 21:48:53 -08008486 * as defined by {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
8487 * This should be used during measurement and layout calculations only. Use
8488 * {@link #getHeight()} to see how wide a view is after layout.
8489 *
8490 * @return The measured width of this view as a bit mask.
8491 */
8492 public final int getMeasuredHeightAndState() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08008493 return mMeasuredHeight;
8494 }
8495
8496 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -08008497 * Return only the state bits of {@link #getMeasuredWidthAndState()}
8498 * and {@link #getMeasuredHeightAndState()}, combined into one integer.
8499 * The width component is in the regular bits {@link #MEASURED_STATE_MASK}
8500 * and the height component is at the shifted bits
8501 * {@link #MEASURED_HEIGHT_STATE_SHIFT}>>{@link #MEASURED_STATE_MASK}.
8502 */
8503 public final int getMeasuredState() {
8504 return (mMeasuredWidth&MEASURED_STATE_MASK)
8505 | ((mMeasuredHeight>>MEASURED_HEIGHT_STATE_SHIFT)
8506 & (MEASURED_STATE_MASK>>MEASURED_HEIGHT_STATE_SHIFT));
8507 }
8508
8509 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008510 * The transform matrix of this view, which is calculated based on the current
8511 * roation, scale, and pivot properties.
8512 *
8513 * @see #getRotation()
8514 * @see #getScaleX()
8515 * @see #getScaleY()
8516 * @see #getPivotX()
8517 * @see #getPivotY()
8518 * @return The current transform matrix for the view
8519 */
8520 public Matrix getMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008521 if (mTransformationInfo != null) {
8522 updateMatrix();
8523 return mTransformationInfo.mMatrix;
8524 }
8525 return Matrix.IDENTITY_MATRIX;
Romain Guy33e72ae2010-07-17 12:40:29 -07008526 }
8527
8528 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07008529 * Utility function to determine if the value is far enough away from zero to be
8530 * considered non-zero.
8531 * @param value A floating point value to check for zero-ness
8532 * @return whether the passed-in value is far enough away from zero to be considered non-zero
8533 */
8534 private static boolean nonzero(float value) {
8535 return (value < -NONZERO_EPSILON || value > NONZERO_EPSILON);
8536 }
8537
8538 /**
Jeff Brown86671742010-09-30 20:00:15 -07008539 * Returns true if the transform matrix is the identity matrix.
8540 * Recomputes the matrix if necessary.
Joe Malin32736f02011-01-19 16:14:20 -08008541 *
Romain Guy33e72ae2010-07-17 12:40:29 -07008542 * @return True if the transform matrix is the identity matrix, false otherwise.
8543 */
Jeff Brown86671742010-09-30 20:00:15 -07008544 final boolean hasIdentityMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008545 if (mTransformationInfo != null) {
8546 updateMatrix();
8547 return mTransformationInfo.mMatrixIsIdentity;
8548 }
8549 return true;
8550 }
8551
8552 void ensureTransformationInfo() {
8553 if (mTransformationInfo == null) {
8554 mTransformationInfo = new TransformationInfo();
8555 }
Jeff Brown86671742010-09-30 20:00:15 -07008556 }
8557
8558 /**
8559 * Recomputes the transform matrix if necessary.
8560 */
Romain Guy2fe9a8f2010-10-04 20:17:01 -07008561 private void updateMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008562 final TransformationInfo info = mTransformationInfo;
8563 if (info == null) {
8564 return;
8565 }
8566 if (info.mMatrixDirty) {
Chet Haasec3aa3612010-06-17 08:50:37 -07008567 // transform-related properties have changed since the last time someone
8568 // asked for the matrix; recalculate it with the current values
Chet Haasefd2b0022010-08-06 13:08:56 -07008569
8570 // Figure out if we need to update the pivot point
Dianne Hackborn4702a852012-08-17 15:18:29 -07008571 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008572 if ((mRight - mLeft) != info.mPrevWidth || (mBottom - mTop) != info.mPrevHeight) {
8573 info.mPrevWidth = mRight - mLeft;
8574 info.mPrevHeight = mBottom - mTop;
8575 info.mPivotX = info.mPrevWidth / 2f;
8576 info.mPivotY = info.mPrevHeight / 2f;
Chet Haasefd2b0022010-08-06 13:08:56 -07008577 }
8578 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008579 info.mMatrix.reset();
8580 if (!nonzero(info.mRotationX) && !nonzero(info.mRotationY)) {
8581 info.mMatrix.setTranslate(info.mTranslationX, info.mTranslationY);
8582 info.mMatrix.preRotate(info.mRotation, info.mPivotX, info.mPivotY);
8583 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
Chet Haase897247b2010-09-09 14:54:47 -07008584 } else {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008585 if (info.mCamera == null) {
8586 info.mCamera = new Camera();
8587 info.matrix3D = new Matrix();
Chet Haasefd2b0022010-08-06 13:08:56 -07008588 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008589 info.mCamera.save();
8590 info.mMatrix.preScale(info.mScaleX, info.mScaleY, info.mPivotX, info.mPivotY);
8591 info.mCamera.rotate(info.mRotationX, info.mRotationY, -info.mRotation);
8592 info.mCamera.getMatrix(info.matrix3D);
8593 info.matrix3D.preTranslate(-info.mPivotX, -info.mPivotY);
8594 info.matrix3D.postTranslate(info.mPivotX + info.mTranslationX,
8595 info.mPivotY + info.mTranslationY);
8596 info.mMatrix.postConcat(info.matrix3D);
8597 info.mCamera.restore();
Chet Haasefd2b0022010-08-06 13:08:56 -07008598 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008599 info.mMatrixDirty = false;
8600 info.mMatrixIsIdentity = info.mMatrix.isIdentity();
8601 info.mInverseMatrixDirty = true;
Chet Haasec3aa3612010-06-17 08:50:37 -07008602 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008603 }
8604
8605 /**
Tobias Duboisdefdb1e2010-12-15 11:35:30 +01008606 * When searching for a view to focus this rectangle is used when considering if this view is
8607 * a good candidate for receiving focus.
8608 *
8609 * By default, the rectangle is the {@link #getDrawingRect}) of the view.
8610 *
8611 * @param r The rectangle to fill in, in this view's coordinates.
8612 */
8613 public void getFocusRect(Rect r) {
8614 getDrawingRect(r);
8615 }
8616
8617 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008618 * Utility method to retrieve the inverse of the current mMatrix property.
8619 * We cache the matrix to avoid recalculating it when transform properties
8620 * have not changed.
8621 *
8622 * @return The inverse of the current matrix of this view.
8623 */
Jeff Brown86671742010-09-30 20:00:15 -07008624 final Matrix getInverseMatrix() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008625 final TransformationInfo info = mTransformationInfo;
8626 if (info != null) {
8627 updateMatrix();
8628 if (info.mInverseMatrixDirty) {
8629 if (info.mInverseMatrix == null) {
8630 info.mInverseMatrix = new Matrix();
8631 }
8632 info.mMatrix.invert(info.mInverseMatrix);
8633 info.mInverseMatrixDirty = false;
Chet Haasec3aa3612010-06-17 08:50:37 -07008634 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008635 return info.mInverseMatrix;
Chet Haasec3aa3612010-06-17 08:50:37 -07008636 }
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008637 return Matrix.IDENTITY_MATRIX;
Chet Haasec3aa3612010-06-17 08:50:37 -07008638 }
8639
8640 /**
Chet Haasea1cff502012-02-21 13:43:44 -08008641 * Gets the distance along the Z axis from the camera to this view.
8642 *
8643 * @see #setCameraDistance(float)
8644 *
8645 * @return The distance along the Z axis.
8646 */
8647 public float getCameraDistance() {
8648 ensureTransformationInfo();
8649 final float dpi = mResources.getDisplayMetrics().densityDpi;
8650 final TransformationInfo info = mTransformationInfo;
8651 if (info.mCamera == null) {
8652 info.mCamera = new Camera();
8653 info.matrix3D = new Matrix();
8654 }
8655 return -(info.mCamera.getLocationZ() * dpi);
8656 }
8657
8658 /**
Romain Guya5364ee2011-02-24 14:46:04 -08008659 * <p>Sets the distance along the Z axis (orthogonal to the X/Y plane on which
8660 * views are drawn) from the camera to this view. The camera's distance
8661 * affects 3D transformations, for instance rotations around the X and Y
8662 * axis. If the rotationX or rotationY properties are changed and this view is
Philip Milne6c8ea062012-04-03 17:38:43 -07008663 * large (more than half the size of the screen), it is recommended to always
Romain Guya5364ee2011-02-24 14:46:04 -08008664 * use a camera distance that's greater than the height (X axis rotation) or
8665 * the width (Y axis rotation) of this view.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008666 *
Romain Guya5364ee2011-02-24 14:46:04 -08008667 * <p>The distance of the camera from the view plane can have an affect on the
8668 * perspective distortion of the view when it is rotated around the x or y axis.
8669 * For example, a large distance will result in a large viewing angle, and there
8670 * will not be much perspective distortion of the view as it rotates. A short
Philip Milne6c8ea062012-04-03 17:38:43 -07008671 * distance may cause much more perspective distortion upon rotation, and can
Romain Guya5364ee2011-02-24 14:46:04 -08008672 * also result in some drawing artifacts if the rotated view ends up partially
8673 * behind the camera (which is why the recommendation is to use a distance at
8674 * least as far as the size of the view, if the view is to be rotated.)</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008675 *
Romain Guya5364ee2011-02-24 14:46:04 -08008676 * <p>The distance is expressed in "depth pixels." The default distance depends
8677 * on the screen density. For instance, on a medium density display, the
8678 * default distance is 1280. On a high density display, the default distance
8679 * is 1920.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008680 *
Romain Guya5364ee2011-02-24 14:46:04 -08008681 * <p>If you want to specify a distance that leads to visually consistent
8682 * results across various densities, use the following formula:</p>
8683 * <pre>
8684 * float scale = context.getResources().getDisplayMetrics().density;
8685 * view.setCameraDistance(distance * scale);
8686 * </pre>
Philip Milne6c8ea062012-04-03 17:38:43 -07008687 *
Romain Guya5364ee2011-02-24 14:46:04 -08008688 * <p>The density scale factor of a high density display is 1.5,
8689 * and 1920 = 1280 * 1.5.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -07008690 *
Romain Guya5364ee2011-02-24 14:46:04 -08008691 * @param distance The distance in "depth pixels", if negative the opposite
8692 * value is used
Philip Milne6c8ea062012-04-03 17:38:43 -07008693 *
8694 * @see #setRotationX(float)
8695 * @see #setRotationY(float)
Romain Guya5364ee2011-02-24 14:46:04 -08008696 */
8697 public void setCameraDistance(float distance) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008698 invalidateViewProperty(true, false);
Romain Guya5364ee2011-02-24 14:46:04 -08008699
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008700 ensureTransformationInfo();
Romain Guya5364ee2011-02-24 14:46:04 -08008701 final float dpi = mResources.getDisplayMetrics().densityDpi;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008702 final TransformationInfo info = mTransformationInfo;
8703 if (info.mCamera == null) {
8704 info.mCamera = new Camera();
8705 info.matrix3D = new Matrix();
Romain Guya5364ee2011-02-24 14:46:04 -08008706 }
8707
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008708 info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
8709 info.mMatrixDirty = true;
Romain Guya5364ee2011-02-24 14:46:04 -08008710
Chet Haase9d1992d2012-03-13 11:03:25 -07008711 invalidateViewProperty(false, false);
Chet Haase1271e2c2012-04-20 09:54:27 -07008712 if (mDisplayList != null) {
Chet Haaseb85967b2012-03-26 14:37:51 -07008713 mDisplayList.setCameraDistance(-Math.abs(distance) / dpi);
Chet Haasea1cff502012-02-21 13:43:44 -08008714 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008715 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008716 // View was rejected last time it was drawn by its parent; this may have changed
8717 invalidateParentIfNeeded();
8718 }
Romain Guya5364ee2011-02-24 14:46:04 -08008719 }
8720
8721 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008722 * The degrees that the view is rotated around the pivot point.
8723 *
Philip Milne6c8ea062012-04-03 17:38:43 -07008724 * @see #setRotation(float)
Chet Haasec3aa3612010-06-17 08:50:37 -07008725 * @see #getPivotX()
8726 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008727 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008728 * @return The degrees of rotation.
8729 */
Chet Haasea5531132012-02-02 13:41:44 -08008730 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008731 public float getRotation() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008732 return mTransformationInfo != null ? mTransformationInfo.mRotation : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07008733 }
8734
8735 /**
Chet Haase897247b2010-09-09 14:54:47 -07008736 * Sets the degrees that the view is rotated around the pivot point. Increasing values
8737 * result in clockwise rotation.
Chet Haasec3aa3612010-06-17 08:50:37 -07008738 *
8739 * @param rotation The degrees of rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008740 *
8741 * @see #getRotation()
Chet Haasec3aa3612010-06-17 08:50:37 -07008742 * @see #getPivotX()
8743 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008744 * @see #setRotationX(float)
8745 * @see #setRotationY(float)
Chet Haase73066682010-11-29 15:55:32 -08008746 *
8747 * @attr ref android.R.styleable#View_rotation
Chet Haasec3aa3612010-06-17 08:50:37 -07008748 */
8749 public void setRotation(float rotation) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008750 ensureTransformationInfo();
8751 final TransformationInfo info = mTransformationInfo;
8752 if (info.mRotation != rotation) {
Chet Haasec3aa3612010-06-17 08:50:37 -07008753 // Double-invalidation is necessary to capture view's old and new areas
Chet Haase9d1992d2012-03-13 11:03:25 -07008754 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008755 info.mRotation = rotation;
8756 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008757 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008758 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008759 mDisplayList.setRotation(rotation);
8760 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008761 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008762 // View was rejected last time it was drawn by its parent; this may have changed
8763 invalidateParentIfNeeded();
8764 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008765 }
8766 }
8767
8768 /**
Chet Haasefd2b0022010-08-06 13:08:56 -07008769 * The degrees that the view is rotated around the vertical axis through the pivot point.
8770 *
8771 * @see #getPivotX()
8772 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008773 * @see #setRotationY(float)
8774 *
Chet Haasefd2b0022010-08-06 13:08:56 -07008775 * @return The degrees of Y rotation.
8776 */
Chet Haasea5531132012-02-02 13:41:44 -08008777 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasefd2b0022010-08-06 13:08:56 -07008778 public float getRotationY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008779 return mTransformationInfo != null ? mTransformationInfo.mRotationY : 0;
Chet Haasefd2b0022010-08-06 13:08:56 -07008780 }
8781
8782 /**
Chet Haase897247b2010-09-09 14:54:47 -07008783 * Sets the degrees that the view is rotated around the vertical axis through the pivot point.
8784 * Increasing values result in counter-clockwise rotation from the viewpoint of looking
8785 * down the y axis.
Philip Milne6c8ea062012-04-03 17:38:43 -07008786 *
Romain Guya5364ee2011-02-24 14:46:04 -08008787 * When rotating large views, it is recommended to adjust the camera distance
8788 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
Chet Haasefd2b0022010-08-06 13:08:56 -07008789 *
8790 * @param rotationY The degrees of Y rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008791 *
8792 * @see #getRotationY()
Chet Haasefd2b0022010-08-06 13:08:56 -07008793 * @see #getPivotX()
8794 * @see #getPivotY()
Romain Guya5364ee2011-02-24 14:46:04 -08008795 * @see #setRotation(float)
Philip Milne6c8ea062012-04-03 17:38:43 -07008796 * @see #setRotationX(float)
8797 * @see #setCameraDistance(float)
Chet Haase73066682010-11-29 15:55:32 -08008798 *
8799 * @attr ref android.R.styleable#View_rotationY
Chet Haasefd2b0022010-08-06 13:08:56 -07008800 */
8801 public void setRotationY(float rotationY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008802 ensureTransformationInfo();
8803 final TransformationInfo info = mTransformationInfo;
8804 if (info.mRotationY != rotationY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008805 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008806 info.mRotationY = rotationY;
8807 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008808 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008809 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008810 mDisplayList.setRotationY(rotationY);
8811 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008812 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008813 // View was rejected last time it was drawn by its parent; this may have changed
8814 invalidateParentIfNeeded();
8815 }
Chet Haasefd2b0022010-08-06 13:08:56 -07008816 }
8817 }
8818
8819 /**
8820 * The degrees that the view is rotated around the horizontal axis through the pivot point.
8821 *
8822 * @see #getPivotX()
8823 * @see #getPivotY()
Philip Milne6c8ea062012-04-03 17:38:43 -07008824 * @see #setRotationX(float)
8825 *
Chet Haasefd2b0022010-08-06 13:08:56 -07008826 * @return The degrees of X rotation.
8827 */
Chet Haasea5531132012-02-02 13:41:44 -08008828 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasefd2b0022010-08-06 13:08:56 -07008829 public float getRotationX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008830 return mTransformationInfo != null ? mTransformationInfo.mRotationX : 0;
Chet Haasefd2b0022010-08-06 13:08:56 -07008831 }
8832
8833 /**
Chet Haase897247b2010-09-09 14:54:47 -07008834 * Sets the degrees that the view is rotated around the horizontal axis through the pivot point.
8835 * Increasing values result in clockwise rotation from the viewpoint of looking down the
8836 * x axis.
Philip Milne6c8ea062012-04-03 17:38:43 -07008837 *
Romain Guya5364ee2011-02-24 14:46:04 -08008838 * When rotating large views, it is recommended to adjust the camera distance
8839 * accordingly. Refer to {@link #setCameraDistance(float)} for more information.
Chet Haasefd2b0022010-08-06 13:08:56 -07008840 *
8841 * @param rotationX The degrees of X rotation.
Philip Milne6c8ea062012-04-03 17:38:43 -07008842 *
8843 * @see #getRotationX()
Chet Haasefd2b0022010-08-06 13:08:56 -07008844 * @see #getPivotX()
8845 * @see #getPivotY()
Romain Guya5364ee2011-02-24 14:46:04 -08008846 * @see #setRotation(float)
Philip Milne6c8ea062012-04-03 17:38:43 -07008847 * @see #setRotationY(float)
8848 * @see #setCameraDistance(float)
Chet Haase73066682010-11-29 15:55:32 -08008849 *
8850 * @attr ref android.R.styleable#View_rotationX
Chet Haasefd2b0022010-08-06 13:08:56 -07008851 */
8852 public void setRotationX(float rotationX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008853 ensureTransformationInfo();
8854 final TransformationInfo info = mTransformationInfo;
8855 if (info.mRotationX != rotationX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008856 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008857 info.mRotationX = rotationX;
8858 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008859 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008860 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008861 mDisplayList.setRotationX(rotationX);
8862 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008863 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008864 // View was rejected last time it was drawn by its parent; this may have changed
8865 invalidateParentIfNeeded();
8866 }
Chet Haasefd2b0022010-08-06 13:08:56 -07008867 }
8868 }
8869
8870 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07008871 * The amount that the view is scaled in x around the pivot point, as a proportion of
8872 * the view's unscaled width. A value of 1, the default, means that no scaling is applied.
8873 *
Joe Onorato93162322010-09-16 15:42:01 -04008874 * <p>By default, this is 1.0f.
8875 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008876 * @see #getPivotX()
8877 * @see #getPivotY()
8878 * @return The scaling factor.
8879 */
Chet Haasea5531132012-02-02 13:41:44 -08008880 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008881 public float getScaleX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008882 return mTransformationInfo != null ? mTransformationInfo.mScaleX : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008883 }
8884
8885 /**
8886 * Sets the amount that the view is scaled in x around the pivot point, as a proportion of
8887 * the view's unscaled width. A value of 1 means that no scaling is applied.
8888 *
8889 * @param scaleX The scaling factor.
8890 * @see #getPivotX()
8891 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008892 *
8893 * @attr ref android.R.styleable#View_scaleX
Chet Haasec3aa3612010-06-17 08:50:37 -07008894 */
8895 public void setScaleX(float scaleX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008896 ensureTransformationInfo();
8897 final TransformationInfo info = mTransformationInfo;
8898 if (info.mScaleX != scaleX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008899 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008900 info.mScaleX = scaleX;
8901 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008902 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008903 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008904 mDisplayList.setScaleX(scaleX);
8905 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008906 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008907 // View was rejected last time it was drawn by its parent; this may have changed
8908 invalidateParentIfNeeded();
8909 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008910 }
8911 }
8912
8913 /**
8914 * The amount that the view is scaled in y around the pivot point, as a proportion of
8915 * the view's unscaled height. A value of 1, the default, means that no scaling is applied.
8916 *
Joe Onorato93162322010-09-16 15:42:01 -04008917 * <p>By default, this is 1.0f.
8918 *
Chet Haasec3aa3612010-06-17 08:50:37 -07008919 * @see #getPivotX()
8920 * @see #getPivotY()
8921 * @return The scaling factor.
8922 */
Chet Haasea5531132012-02-02 13:41:44 -08008923 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008924 public float getScaleY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008925 return mTransformationInfo != null ? mTransformationInfo.mScaleY : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07008926 }
8927
8928 /**
8929 * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
8930 * the view's unscaled width. A value of 1 means that no scaling is applied.
8931 *
8932 * @param scaleY The scaling factor.
8933 * @see #getPivotX()
8934 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008935 *
8936 * @attr ref android.R.styleable#View_scaleY
Chet Haasec3aa3612010-06-17 08:50:37 -07008937 */
8938 public void setScaleY(float scaleY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008939 ensureTransformationInfo();
8940 final TransformationInfo info = mTransformationInfo;
8941 if (info.mScaleY != scaleY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008942 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008943 info.mScaleY = scaleY;
8944 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008945 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008946 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008947 mDisplayList.setScaleY(scaleY);
8948 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07008949 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07008950 // View was rejected last time it was drawn by its parent; this may have changed
8951 invalidateParentIfNeeded();
8952 }
Chet Haasec3aa3612010-06-17 08:50:37 -07008953 }
8954 }
8955
8956 /**
8957 * The x location of the point around which the view is {@link #setRotation(float) rotated}
8958 * and {@link #setScaleX(float) scaled}.
8959 *
8960 * @see #getRotation()
8961 * @see #getScaleX()
8962 * @see #getScaleY()
8963 * @see #getPivotY()
8964 * @return The x location of the pivot point.
Philip Milne6c8ea062012-04-03 17:38:43 -07008965 *
8966 * @attr ref android.R.styleable#View_transformPivotX
Chet Haasec3aa3612010-06-17 08:50:37 -07008967 */
Chet Haasea5531132012-02-02 13:41:44 -08008968 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07008969 public float getPivotX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008970 return mTransformationInfo != null ? mTransformationInfo.mPivotX : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07008971 }
8972
8973 /**
8974 * Sets the x location of the point around which the view is
8975 * {@link #setRotation(float) rotated} and {@link #setScaleX(float) scaled}.
Chet Haasefd2b0022010-08-06 13:08:56 -07008976 * By default, the pivot point is centered on the object.
8977 * Setting this property disables this behavior and causes the view to use only the
8978 * explicitly set pivotX and pivotY values.
Chet Haasec3aa3612010-06-17 08:50:37 -07008979 *
8980 * @param pivotX The x location of the pivot point.
8981 * @see #getRotation()
8982 * @see #getScaleX()
8983 * @see #getScaleY()
8984 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08008985 *
8986 * @attr ref android.R.styleable#View_transformPivotX
Chet Haasec3aa3612010-06-17 08:50:37 -07008987 */
8988 public void setPivotX(float pivotX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008989 ensureTransformationInfo();
Dianne Hackborn4702a852012-08-17 15:18:29 -07008990 mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008991 final TransformationInfo info = mTransformationInfo;
8992 if (info.mPivotX != pivotX) {
Chet Haase9d1992d2012-03-13 11:03:25 -07008993 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07008994 info.mPivotX = pivotX;
8995 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07008996 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07008997 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08008998 mDisplayList.setPivotX(pivotX);
8999 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009000 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009001 // View was rejected last time it was drawn by its parent; this may have changed
9002 invalidateParentIfNeeded();
9003 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009004 }
9005 }
9006
9007 /**
9008 * The y location of the point around which the view is {@link #setRotation(float) rotated}
9009 * and {@link #setScaleY(float) scaled}.
9010 *
9011 * @see #getRotation()
9012 * @see #getScaleX()
9013 * @see #getScaleY()
9014 * @see #getPivotY()
9015 * @return The y location of the pivot point.
Philip Milne6c8ea062012-04-03 17:38:43 -07009016 *
9017 * @attr ref android.R.styleable#View_transformPivotY
Chet Haasec3aa3612010-06-17 08:50:37 -07009018 */
Chet Haasea5531132012-02-02 13:41:44 -08009019 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07009020 public float getPivotY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009021 return mTransformationInfo != null ? mTransformationInfo.mPivotY : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07009022 }
9023
9024 /**
9025 * Sets the y location of the point around which the view is {@link #setRotation(float) rotated}
Chet Haasefd2b0022010-08-06 13:08:56 -07009026 * and {@link #setScaleY(float) scaled}. By default, the pivot point is centered on the object.
9027 * Setting this property disables this behavior and causes the view to use only the
9028 * explicitly set pivotX and pivotY values.
Chet Haasec3aa3612010-06-17 08:50:37 -07009029 *
9030 * @param pivotY The y location of the pivot point.
9031 * @see #getRotation()
9032 * @see #getScaleX()
9033 * @see #getScaleY()
9034 * @see #getPivotY()
Chet Haase73066682010-11-29 15:55:32 -08009035 *
9036 * @attr ref android.R.styleable#View_transformPivotY
Chet Haasec3aa3612010-06-17 08:50:37 -07009037 */
9038 public void setPivotY(float pivotY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009039 ensureTransformationInfo();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009040 mPrivateFlags |= PFLAG_PIVOT_EXPLICITLY_SET;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009041 final TransformationInfo info = mTransformationInfo;
9042 if (info.mPivotY != pivotY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009043 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009044 info.mPivotY = pivotY;
9045 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009046 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009047 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009048 mDisplayList.setPivotY(pivotY);
9049 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009050 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009051 // View was rejected last time it was drawn by its parent; this may have changed
9052 invalidateParentIfNeeded();
9053 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009054 }
9055 }
9056
9057 /**
9058 * The opacity of the view. This is a value from 0 to 1, where 0 means the view is
9059 * completely transparent and 1 means the view is completely opaque.
9060 *
Joe Onorato93162322010-09-16 15:42:01 -04009061 * <p>By default this is 1.0f.
Chet Haasec3aa3612010-06-17 08:50:37 -07009062 * @return The opacity of the view.
9063 */
Chet Haasea5531132012-02-02 13:41:44 -08009064 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasec3aa3612010-06-17 08:50:37 -07009065 public float getAlpha() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009066 return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;
Chet Haasec3aa3612010-06-17 08:50:37 -07009067 }
9068
9069 /**
Chet Haasedb8c9a62012-03-21 18:54:18 -07009070 * Returns whether this View has content which overlaps. This function, intended to be
9071 * overridden by specific View types, is an optimization when alpha is set on a view. If
9072 * rendering overlaps in a view with alpha < 1, that view is drawn to an offscreen buffer
9073 * and then composited it into place, which can be expensive. If the view has no overlapping
9074 * rendering, the view can draw each primitive with the appropriate alpha value directly.
9075 * An example of overlapping rendering is a TextView with a background image, such as a
9076 * Button. An example of non-overlapping rendering is a TextView with no background, or
9077 * an ImageView with only the foreground image. The default implementation returns true;
9078 * subclasses should override if they have cases which can be optimized.
9079 *
9080 * @return true if the content in this view might overlap, false otherwise.
9081 */
9082 public boolean hasOverlappingRendering() {
9083 return true;
9084 }
9085
9086 /**
Romain Guy171c5922011-01-06 10:04:23 -08009087 * <p>Sets the opacity of the view. This is a value from 0 to 1, where 0 means the view is
9088 * completely transparent and 1 means the view is completely opaque.</p>
Joe Malin32736f02011-01-19 16:14:20 -08009089 *
Romain Guy171c5922011-01-06 10:04:23 -08009090 * <p>If this view overrides {@link #onSetAlpha(int)} to return true, then this view is
9091 * responsible for applying the opacity itself. Otherwise, calling this method is
9092 * equivalent to calling {@link #setLayerType(int, android.graphics.Paint)} and
Joe Malin32736f02011-01-19 16:14:20 -08009093 * setting a hardware layer.</p>
Chet Haasec3aa3612010-06-17 08:50:37 -07009094 *
Chet Haasea5531132012-02-02 13:41:44 -08009095 * <p>Note that setting alpha to a translucent value (0 < alpha < 1) may have
9096 * performance implications. It is generally best to use the alpha property sparingly and
9097 * transiently, as in the case of fading animations.</p>
9098 *
Chet Haasec3aa3612010-06-17 08:50:37 -07009099 * @param alpha The opacity of the view.
Chet Haase73066682010-11-29 15:55:32 -08009100 *
Joe Malin32736f02011-01-19 16:14:20 -08009101 * @see #setLayerType(int, android.graphics.Paint)
9102 *
Chet Haase73066682010-11-29 15:55:32 -08009103 * @attr ref android.R.styleable#View_alpha
Chet Haasec3aa3612010-06-17 08:50:37 -07009104 */
9105 public void setAlpha(float alpha) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009106 ensureTransformationInfo();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009107 if (mTransformationInfo.mAlpha != alpha) {
9108 mTransformationInfo.mAlpha = alpha;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009109 if (onSetAlpha((int) (alpha * 255))) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009110 mPrivateFlags |= PFLAG_ALPHA_SET;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009111 // subclass is handling alpha - don't optimize rendering cache invalidation
Chet Haase9d1992d2012-03-13 11:03:25 -07009112 invalidateParentCaches();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009113 invalidate(true);
9114 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009115 mPrivateFlags &= ~PFLAG_ALPHA_SET;
Chet Haase9d1992d2012-03-13 11:03:25 -07009116 invalidateViewProperty(true, false);
Chet Haase1271e2c2012-04-20 09:54:27 -07009117 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009118 mDisplayList.setAlpha(alpha);
9119 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009120 }
Chet Haaseed032702010-10-01 14:05:54 -07009121 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009122 }
9123
9124 /**
Chet Haasea00f3862011-02-22 06:34:40 -08009125 * Faster version of setAlpha() which performs the same steps except there are
9126 * no calls to invalidate(). The caller of this function should perform proper invalidation
9127 * on the parent and this object. The return value indicates whether the subclass handles
9128 * alpha (the return value for onSetAlpha()).
9129 *
9130 * @param alpha The new value for the alpha property
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009131 * @return true if the View subclass handles alpha (the return value for onSetAlpha()) and
9132 * the new value for the alpha property is different from the old value
Chet Haasea00f3862011-02-22 06:34:40 -08009133 */
9134 boolean setAlphaNoInvalidation(float alpha) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009135 ensureTransformationInfo();
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009136 if (mTransformationInfo.mAlpha != alpha) {
9137 mTransformationInfo.mAlpha = alpha;
9138 boolean subclassHandlesAlpha = onSetAlpha((int) (alpha * 255));
9139 if (subclassHandlesAlpha) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009140 mPrivateFlags |= PFLAG_ALPHA_SET;
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009141 return true;
9142 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009143 mPrivateFlags &= ~PFLAG_ALPHA_SET;
Chet Haase1271e2c2012-04-20 09:54:27 -07009144 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009145 mDisplayList.setAlpha(alpha);
9146 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009147 }
Chet Haasea00f3862011-02-22 06:34:40 -08009148 }
Michael Jurkaa7a7eed2012-01-17 06:06:17 -08009149 return false;
Chet Haasea00f3862011-02-22 06:34:40 -08009150 }
9151
9152 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009153 * Top position of this view relative to its parent.
9154 *
9155 * @return The top of this view, in pixels.
9156 */
9157 @ViewDebug.CapturedViewProperty
9158 public final int getTop() {
9159 return mTop;
9160 }
9161
9162 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009163 * Sets the top position of this view relative to its parent. This method is meant to be called
9164 * by the layout system and should not generally be called otherwise, because the property
9165 * may be changed at any time by the layout.
9166 *
9167 * @param top The top of this view, in pixels.
9168 */
9169 public final void setTop(int top) {
9170 if (top != mTop) {
Jeff Brown86671742010-09-30 20:00:15 -07009171 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009172 final boolean matrixIsIdentity = mTransformationInfo == null
9173 || mTransformationInfo.mMatrixIsIdentity;
9174 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009175 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009176 int minTop;
9177 int yLoc;
9178 if (top < mTop) {
9179 minTop = top;
9180 yLoc = top - mTop;
9181 } else {
9182 minTop = mTop;
9183 yLoc = 0;
9184 }
Chet Haasee9140a72011-02-16 16:23:29 -08009185 invalidate(0, yLoc, mRight - mLeft, mBottom - minTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009186 }
9187 } else {
9188 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009189 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009190 }
9191
Chet Haaseed032702010-10-01 14:05:54 -07009192 int width = mRight - mLeft;
9193 int oldHeight = mBottom - mTop;
9194
Chet Haase21cd1382010-09-01 17:42:29 -07009195 mTop = top;
Chet Haase1271e2c2012-04-20 09:54:27 -07009196 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009197 mDisplayList.setTop(mTop);
9198 }
Chet Haase21cd1382010-09-01 17:42:29 -07009199
Chet Haaseed032702010-10-01 14:05:54 -07009200 onSizeChanged(width, mBottom - mTop, width, oldHeight);
9201
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009202 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009203 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009204 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009205 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009206 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009207 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009208 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009209 }
Chet Haase55dbb652010-12-21 20:15:08 -08009210 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009211 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009212 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009213 // View was rejected last time it was drawn by its parent; this may have changed
9214 invalidateParentIfNeeded();
9215 }
Chet Haase21cd1382010-09-01 17:42:29 -07009216 }
9217 }
9218
9219 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009220 * Bottom position of this view relative to its parent.
9221 *
9222 * @return The bottom of this view, in pixels.
9223 */
9224 @ViewDebug.CapturedViewProperty
9225 public final int getBottom() {
9226 return mBottom;
9227 }
9228
9229 /**
Michael Jurkadab559a2011-01-04 20:31:51 -08009230 * True if this view has changed since the last time being drawn.
9231 *
9232 * @return The dirty state of this view.
9233 */
9234 public boolean isDirty() {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009235 return (mPrivateFlags & PFLAG_DIRTY_MASK) != 0;
Michael Jurkadab559a2011-01-04 20:31:51 -08009236 }
9237
9238 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009239 * Sets the bottom position of this view relative to its parent. This method is meant to be
9240 * called by the layout system and should not generally be called otherwise, because the
9241 * property may be changed at any time by the layout.
9242 *
9243 * @param bottom The bottom of this view, in pixels.
9244 */
9245 public final void setBottom(int bottom) {
9246 if (bottom != mBottom) {
Jeff Brown86671742010-09-30 20:00:15 -07009247 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009248 final boolean matrixIsIdentity = mTransformationInfo == null
9249 || mTransformationInfo.mMatrixIsIdentity;
9250 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009251 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009252 int maxBottom;
9253 if (bottom < mBottom) {
9254 maxBottom = mBottom;
9255 } else {
9256 maxBottom = bottom;
9257 }
Chet Haasee9140a72011-02-16 16:23:29 -08009258 invalidate(0, 0, mRight - mLeft, maxBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009259 }
9260 } else {
9261 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009262 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009263 }
9264
Chet Haaseed032702010-10-01 14:05:54 -07009265 int width = mRight - mLeft;
9266 int oldHeight = mBottom - mTop;
9267
Chet Haase21cd1382010-09-01 17:42:29 -07009268 mBottom = bottom;
Chet Haase1271e2c2012-04-20 09:54:27 -07009269 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009270 mDisplayList.setBottom(mBottom);
9271 }
Chet Haase21cd1382010-09-01 17:42:29 -07009272
Chet Haaseed032702010-10-01 14:05:54 -07009273 onSizeChanged(width, mBottom - mTop, width, oldHeight);
9274
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009275 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009276 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009277 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009278 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009279 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009280 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009281 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009282 }
Chet Haase55dbb652010-12-21 20:15:08 -08009283 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009284 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009285 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009286 // View was rejected last time it was drawn by its parent; this may have changed
9287 invalidateParentIfNeeded();
9288 }
Chet Haase21cd1382010-09-01 17:42:29 -07009289 }
9290 }
9291
9292 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009293 * Left position of this view relative to its parent.
9294 *
9295 * @return The left edge of this view, in pixels.
9296 */
9297 @ViewDebug.CapturedViewProperty
9298 public final int getLeft() {
9299 return mLeft;
9300 }
9301
9302 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009303 * Sets the left position of this view relative to its parent. This method is meant to be called
9304 * by the layout system and should not generally be called otherwise, because the property
9305 * may be changed at any time by the layout.
9306 *
9307 * @param left The bottom of this view, in pixels.
9308 */
9309 public final void setLeft(int left) {
9310 if (left != mLeft) {
Jeff Brown86671742010-09-30 20:00:15 -07009311 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009312 final boolean matrixIsIdentity = mTransformationInfo == null
9313 || mTransformationInfo.mMatrixIsIdentity;
9314 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009315 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009316 int minLeft;
9317 int xLoc;
9318 if (left < mLeft) {
9319 minLeft = left;
9320 xLoc = left - mLeft;
9321 } else {
9322 minLeft = mLeft;
9323 xLoc = 0;
9324 }
Chet Haasee9140a72011-02-16 16:23:29 -08009325 invalidate(xLoc, 0, mRight - minLeft, mBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009326 }
9327 } else {
9328 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009329 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009330 }
9331
Chet Haaseed032702010-10-01 14:05:54 -07009332 int oldWidth = mRight - mLeft;
9333 int height = mBottom - mTop;
9334
Chet Haase21cd1382010-09-01 17:42:29 -07009335 mLeft = left;
Chet Haase1271e2c2012-04-20 09:54:27 -07009336 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009337 mDisplayList.setLeft(left);
9338 }
Chet Haase21cd1382010-09-01 17:42:29 -07009339
Chet Haaseed032702010-10-01 14:05:54 -07009340 onSizeChanged(mRight - mLeft, height, oldWidth, height);
9341
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009342 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009343 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009344 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009345 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009346 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009347 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009348 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009349 }
Chet Haase55dbb652010-12-21 20:15:08 -08009350 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009351 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009352 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009353 // View was rejected last time it was drawn by its parent; this may have changed
9354 invalidateParentIfNeeded();
9355 }
Chet Haase21cd1382010-09-01 17:42:29 -07009356 }
9357 }
9358
9359 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009360 * Right position of this view relative to its parent.
9361 *
9362 * @return The right edge of this view, in pixels.
9363 */
9364 @ViewDebug.CapturedViewProperty
9365 public final int getRight() {
9366 return mRight;
9367 }
9368
9369 /**
Chet Haase21cd1382010-09-01 17:42:29 -07009370 * Sets the right position of this view relative to its parent. This method is meant to be called
9371 * by the layout system and should not generally be called otherwise, because the property
9372 * may be changed at any time by the layout.
9373 *
9374 * @param right The bottom of this view, in pixels.
9375 */
9376 public final void setRight(int right) {
9377 if (right != mRight) {
Jeff Brown86671742010-09-30 20:00:15 -07009378 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009379 final boolean matrixIsIdentity = mTransformationInfo == null
9380 || mTransformationInfo.mMatrixIsIdentity;
9381 if (matrixIsIdentity) {
Chet Haasee9140a72011-02-16 16:23:29 -08009382 if (mAttachInfo != null) {
Chet Haase21cd1382010-09-01 17:42:29 -07009383 int maxRight;
9384 if (right < mRight) {
9385 maxRight = mRight;
9386 } else {
9387 maxRight = right;
9388 }
Chet Haasee9140a72011-02-16 16:23:29 -08009389 invalidate(0, 0, maxRight - mLeft, mBottom - mTop);
Chet Haase21cd1382010-09-01 17:42:29 -07009390 }
9391 } else {
9392 // Double-invalidation is necessary to capture view's old and new areas
Romain Guy0fd89bf2011-01-26 15:41:30 -08009393 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009394 }
9395
Chet Haaseed032702010-10-01 14:05:54 -07009396 int oldWidth = mRight - mLeft;
9397 int height = mBottom - mTop;
9398
Chet Haase21cd1382010-09-01 17:42:29 -07009399 mRight = right;
Chet Haase1271e2c2012-04-20 09:54:27 -07009400 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009401 mDisplayList.setRight(mRight);
9402 }
Chet Haase21cd1382010-09-01 17:42:29 -07009403
Chet Haaseed032702010-10-01 14:05:54 -07009404 onSizeChanged(mRight - mLeft, height, oldWidth, height);
9405
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009406 if (!matrixIsIdentity) {
Dianne Hackborn4702a852012-08-17 15:18:29 -07009407 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009408 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009409 mTransformationInfo.mMatrixDirty = true;
Chet Haase6c7ad5d2010-12-28 08:40:00 -08009410 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009411 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Romain Guy0fd89bf2011-01-26 15:41:30 -08009412 invalidate(true);
Chet Haase21cd1382010-09-01 17:42:29 -07009413 }
Chet Haase55dbb652010-12-21 20:15:08 -08009414 mBackgroundSizeChanged = true;
Chet Haase678e0ad2011-01-25 09:37:18 -08009415 invalidateParentIfNeeded();
Dianne Hackborn4702a852012-08-17 15:18:29 -07009416 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009417 // View was rejected last time it was drawn by its parent; this may have changed
9418 invalidateParentIfNeeded();
9419 }
Chet Haase21cd1382010-09-01 17:42:29 -07009420 }
9421 }
9422
9423 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009424 * The visual x position of this view, in pixels. This is equivalent to the
9425 * {@link #setTranslationX(float) translationX} property plus the current
Joe Malin32736f02011-01-19 16:14:20 -08009426 * {@link #getLeft() left} property.
Chet Haasec3aa3612010-06-17 08:50:37 -07009427 *
Chet Haasedf030d22010-07-30 17:22:38 -07009428 * @return The visual x position of this view, in pixels.
Chet Haasec3aa3612010-06-17 08:50:37 -07009429 */
Chet Haasea5531132012-02-02 13:41:44 -08009430 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009431 public float getX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009432 return mLeft + (mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0);
Chet Haasedf030d22010-07-30 17:22:38 -07009433 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009434
Chet Haasedf030d22010-07-30 17:22:38 -07009435 /**
9436 * Sets the visual x position of this view, in pixels. This is equivalent to setting the
9437 * {@link #setTranslationX(float) translationX} property to be the difference between
9438 * the x value passed in and the current {@link #getLeft() left} property.
9439 *
9440 * @param x The visual x position of this view, in pixels.
9441 */
9442 public void setX(float x) {
9443 setTranslationX(x - mLeft);
9444 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009445
Chet Haasedf030d22010-07-30 17:22:38 -07009446 /**
9447 * The visual y position of this view, in pixels. This is equivalent to the
9448 * {@link #setTranslationY(float) translationY} property plus the current
9449 * {@link #getTop() top} property.
9450 *
9451 * @return The visual y position of this view, in pixels.
9452 */
Chet Haasea5531132012-02-02 13:41:44 -08009453 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009454 public float getY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009455 return mTop + (mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0);
Chet Haasedf030d22010-07-30 17:22:38 -07009456 }
9457
9458 /**
9459 * Sets the visual y position of this view, in pixels. This is equivalent to setting the
9460 * {@link #setTranslationY(float) translationY} property to be the difference between
9461 * the y value passed in and the current {@link #getTop() top} property.
9462 *
9463 * @param y The visual y position of this view, in pixels.
9464 */
9465 public void setY(float y) {
9466 setTranslationY(y - mTop);
9467 }
9468
9469
9470 /**
9471 * The horizontal location of this view relative to its {@link #getLeft() left} position.
9472 * This position is post-layout, in addition to wherever the object's
9473 * layout placed it.
9474 *
9475 * @return The horizontal position of this view relative to its left position, in pixels.
9476 */
Chet Haasea5531132012-02-02 13:41:44 -08009477 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009478 public float getTranslationX() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009479 return mTransformationInfo != null ? mTransformationInfo.mTranslationX : 0;
Chet Haasedf030d22010-07-30 17:22:38 -07009480 }
9481
9482 /**
9483 * Sets the horizontal location of this view relative to its {@link #getLeft() left} position.
9484 * This effectively positions the object post-layout, in addition to wherever the object's
9485 * layout placed it.
9486 *
9487 * @param translationX The horizontal position of this view relative to its left position,
9488 * in pixels.
Chet Haase73066682010-11-29 15:55:32 -08009489 *
9490 * @attr ref android.R.styleable#View_translationX
Chet Haasedf030d22010-07-30 17:22:38 -07009491 */
9492 public void setTranslationX(float translationX) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009493 ensureTransformationInfo();
9494 final TransformationInfo info = mTransformationInfo;
9495 if (info.mTranslationX != translationX) {
Chet Haasedf030d22010-07-30 17:22:38 -07009496 // Double-invalidation is necessary to capture view's old and new areas
Chet Haase9d1992d2012-03-13 11:03:25 -07009497 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009498 info.mTranslationX = translationX;
9499 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009500 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009501 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009502 mDisplayList.setTranslationX(translationX);
9503 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009504 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009505 // View was rejected last time it was drawn by its parent; this may have changed
9506 invalidateParentIfNeeded();
9507 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009508 }
9509 }
9510
9511 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009512 * The horizontal location of this view relative to its {@link #getTop() top} position.
9513 * This position is post-layout, in addition to wherever the object's
9514 * layout placed it.
Chet Haasec3aa3612010-06-17 08:50:37 -07009515 *
Chet Haasedf030d22010-07-30 17:22:38 -07009516 * @return The vertical position of this view relative to its top position,
9517 * in pixels.
Chet Haasec3aa3612010-06-17 08:50:37 -07009518 */
Chet Haasea5531132012-02-02 13:41:44 -08009519 @ViewDebug.ExportedProperty(category = "drawing")
Chet Haasedf030d22010-07-30 17:22:38 -07009520 public float getTranslationY() {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009521 return mTransformationInfo != null ? mTransformationInfo.mTranslationY : 0;
Chet Haasec3aa3612010-06-17 08:50:37 -07009522 }
9523
9524 /**
Chet Haasedf030d22010-07-30 17:22:38 -07009525 * Sets the vertical location of this view relative to its {@link #getTop() top} position.
9526 * This effectively positions the object post-layout, in addition to wherever the object's
9527 * layout placed it.
Chet Haasec3aa3612010-06-17 08:50:37 -07009528 *
Chet Haasedf030d22010-07-30 17:22:38 -07009529 * @param translationY The vertical position of this view relative to its top position,
9530 * in pixels.
Chet Haase73066682010-11-29 15:55:32 -08009531 *
9532 * @attr ref android.R.styleable#View_translationY
Chet Haasec3aa3612010-06-17 08:50:37 -07009533 */
Chet Haasedf030d22010-07-30 17:22:38 -07009534 public void setTranslationY(float translationY) {
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009535 ensureTransformationInfo();
9536 final TransformationInfo info = mTransformationInfo;
9537 if (info.mTranslationY != translationY) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009538 invalidateViewProperty(true, false);
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009539 info.mTranslationY = translationY;
9540 info.mMatrixDirty = true;
Chet Haase9d1992d2012-03-13 11:03:25 -07009541 invalidateViewProperty(false, true);
Chet Haase1271e2c2012-04-20 09:54:27 -07009542 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009543 mDisplayList.setTranslationY(translationY);
9544 }
Dianne Hackborn4702a852012-08-17 15:18:29 -07009545 if ((mPrivateFlags2 & PFLAG2_VIEW_QUICK_REJECTED) == PFLAG2_VIEW_QUICK_REJECTED) {
Chet Haase1a3ab172012-05-11 08:41:20 -07009546 // View was rejected last time it was drawn by its parent; this may have changed
9547 invalidateParentIfNeeded();
9548 }
Chet Haasedf030d22010-07-30 17:22:38 -07009549 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009550 }
9551
9552 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009553 * Hit rectangle in parent's coordinates
9554 *
9555 * @param outRect The hit rectangle of the view.
9556 */
9557 public void getHitRect(Rect outRect) {
Jeff Brown86671742010-09-30 20:00:15 -07009558 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009559 final TransformationInfo info = mTransformationInfo;
9560 if (info == null || info.mMatrixIsIdentity || mAttachInfo == null) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009561 outRect.set(mLeft, mTop, mRight, mBottom);
9562 } else {
9563 final RectF tmpRect = mAttachInfo.mTmpTransformRect;
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009564 tmpRect.set(-info.mPivotX, -info.mPivotY,
9565 getWidth() - info.mPivotX, getHeight() - info.mPivotY);
9566 info.mMatrix.mapRect(tmpRect);
Romain Guy33e72ae2010-07-17 12:40:29 -07009567 outRect.set((int) tmpRect.left + mLeft, (int) tmpRect.top + mTop,
9568 (int) tmpRect.right + mLeft, (int) tmpRect.bottom + mTop);
Chet Haasec3aa3612010-06-17 08:50:37 -07009569 }
9570 }
9571
9572 /**
Jeff Brown20e987b2010-08-23 12:01:02 -07009573 * Determines whether the given point, in local coordinates is inside the view.
9574 */
9575 /*package*/ final boolean pointInView(float localX, float localY) {
9576 return localX >= 0 && localX < (mRight - mLeft)
9577 && localY >= 0 && localY < (mBottom - mTop);
9578 }
9579
9580 /**
Chet Haasec3aa3612010-06-17 08:50:37 -07009581 * Utility method to determine whether the given point, in local coordinates,
9582 * is inside the view, where the area of the view is expanded by the slop factor.
9583 * This method is called while processing touch-move events to determine if the event
9584 * is still within the view.
9585 */
9586 private boolean pointInView(float localX, float localY, float slop) {
Jeff Brown20e987b2010-08-23 12:01:02 -07009587 return localX >= -slop && localY >= -slop && localX < ((mRight - mLeft) + slop) &&
Romain Guy33e72ae2010-07-17 12:40:29 -07009588 localY < ((mBottom - mTop) + slop);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009589 }
9590
9591 /**
9592 * When a view has focus and the user navigates away from it, the next view is searched for
9593 * starting from the rectangle filled in by this method.
9594 *
Romain Guy5c22a8c2011-05-13 11:48:45 -07009595 * By default, the rectange is the {@link #getDrawingRect(android.graphics.Rect)})
9596 * of the view. However, if your view maintains some idea of internal selection,
9597 * such as a cursor, or a selected row or column, you should override this method and
9598 * fill in a more specific rectangle.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009599 *
9600 * @param r The rectangle to fill in, in this view's coordinates.
9601 */
9602 public void getFocusedRect(Rect r) {
9603 getDrawingRect(r);
9604 }
9605
9606 /**
9607 * If some part of this view is not clipped by any of its parents, then
9608 * return that area in r in global (root) coordinates. To convert r to local
Gilles Debunnecea45132011-11-24 02:19:27 +01009609 * coordinates (without taking possible View rotations into account), offset
9610 * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
9611 * If the view is completely clipped or translated out, return false.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009612 *
9613 * @param r If true is returned, r holds the global coordinates of the
9614 * visible portion of this view.
9615 * @param globalOffset If true is returned, globalOffset holds the dx,dy
9616 * between this view and its root. globalOffet may be null.
9617 * @return true if r is non-empty (i.e. part of the view is visible at the
9618 * root level.
9619 */
9620 public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
9621 int width = mRight - mLeft;
9622 int height = mBottom - mTop;
9623 if (width > 0 && height > 0) {
9624 r.set(0, 0, width, height);
9625 if (globalOffset != null) {
9626 globalOffset.set(-mScrollX, -mScrollY);
9627 }
9628 return mParent == null || mParent.getChildVisibleRect(this, r, globalOffset);
9629 }
9630 return false;
9631 }
9632
9633 public final boolean getGlobalVisibleRect(Rect r) {
9634 return getGlobalVisibleRect(r, null);
9635 }
9636
9637 public final boolean getLocalVisibleRect(Rect r) {
Romain Guyab4c4f4f2012-05-06 13:11:24 -07009638 final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009639 if (getGlobalVisibleRect(r, offset)) {
9640 r.offset(-offset.x, -offset.y); // make r local
9641 return true;
9642 }
9643 return false;
9644 }
9645
9646 /**
9647 * Offset this view's vertical location by the specified number of pixels.
9648 *
9649 * @param offset the number of pixels to offset the view by
9650 */
9651 public void offsetTopAndBottom(int offset) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009652 if (offset != 0) {
Jeff Brown86671742010-09-30 20:00:15 -07009653 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009654 final boolean matrixIsIdentity = mTransformationInfo == null
9655 || mTransformationInfo.mMatrixIsIdentity;
9656 if (matrixIsIdentity) {
Chet Haase1271e2c2012-04-20 09:54:27 -07009657 if (mDisplayList != null) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009658 invalidateViewProperty(false, false);
9659 } else {
9660 final ViewParent p = mParent;
9661 if (p != null && mAttachInfo != null) {
9662 final Rect r = mAttachInfo.mTmpInvalRect;
9663 int minTop;
9664 int maxBottom;
9665 int yLoc;
9666 if (offset < 0) {
9667 minTop = mTop + offset;
9668 maxBottom = mBottom;
9669 yLoc = offset;
9670 } else {
9671 minTop = mTop;
9672 maxBottom = mBottom + offset;
9673 yLoc = 0;
9674 }
9675 r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
9676 p.invalidateChild(this, r);
Chet Haase8fbf8d22010-07-30 15:01:32 -07009677 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009678 }
9679 } else {
Chet Haase9d1992d2012-03-13 11:03:25 -07009680 invalidateViewProperty(false, false);
Chet Haasec3aa3612010-06-17 08:50:37 -07009681 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009682
Chet Haasec3aa3612010-06-17 08:50:37 -07009683 mTop += offset;
9684 mBottom += offset;
Chet Haase1271e2c2012-04-20 09:54:27 -07009685 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009686 mDisplayList.offsetTopBottom(offset);
Chet Haase9d1992d2012-03-13 11:03:25 -07009687 invalidateViewProperty(false, false);
9688 } else {
9689 if (!matrixIsIdentity) {
9690 invalidateViewProperty(false, true);
9691 }
9692 invalidateParentIfNeeded();
Chet Haasea1cff502012-02-21 13:43:44 -08009693 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009694 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009695 }
9696
9697 /**
9698 * Offset this view's horizontal location by the specified amount of pixels.
9699 *
9700 * @param offset the numer of pixels to offset the view by
9701 */
9702 public void offsetLeftAndRight(int offset) {
Chet Haasec3aa3612010-06-17 08:50:37 -07009703 if (offset != 0) {
Jeff Brown86671742010-09-30 20:00:15 -07009704 updateMatrix();
Dianne Hackbornddb715b2011-09-09 14:43:39 -07009705 final boolean matrixIsIdentity = mTransformationInfo == null
9706 || mTransformationInfo.mMatrixIsIdentity;
9707 if (matrixIsIdentity) {
Chet Haase1271e2c2012-04-20 09:54:27 -07009708 if (mDisplayList != null) {
Chet Haase9d1992d2012-03-13 11:03:25 -07009709 invalidateViewProperty(false, false);
9710 } else {
9711 final ViewParent p = mParent;
9712 if (p != null && mAttachInfo != null) {
9713 final Rect r = mAttachInfo.mTmpInvalRect;
9714 int minLeft;
9715 int maxRight;
9716 if (offset < 0) {
9717 minLeft = mLeft + offset;
9718 maxRight = mRight;
9719 } else {
9720 minLeft = mLeft;
9721 maxRight = mRight + offset;
9722 }
9723 r.set(0, 0, maxRight - minLeft, mBottom - mTop);
9724 p.invalidateChild(this, r);
Chet Haase8fbf8d22010-07-30 15:01:32 -07009725 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009726 }
9727 } else {
Chet Haase9d1992d2012-03-13 11:03:25 -07009728 invalidateViewProperty(false, false);
Chet Haasec3aa3612010-06-17 08:50:37 -07009729 }
Romain Guy33e72ae2010-07-17 12:40:29 -07009730
Chet Haasec3aa3612010-06-17 08:50:37 -07009731 mLeft += offset;
9732 mRight += offset;
Chet Haase1271e2c2012-04-20 09:54:27 -07009733 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -08009734 mDisplayList.offsetLeftRight(offset);
Chet Haase9d1992d2012-03-13 11:03:25 -07009735 invalidateViewProperty(false, false);
9736 } else {
9737 if (!matrixIsIdentity) {
9738 invalidateViewProperty(false, true);
9739 }
9740 invalidateParentIfNeeded();
Chet Haasea1cff502012-02-21 13:43:44 -08009741 }
Chet Haasec3aa3612010-06-17 08:50:37 -07009742 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009743 }
9744
9745 /**
9746 * Get the LayoutParams associated with this view. All views should have
9747 * layout parameters. These supply parameters to the <i>parent</i> of this
9748 * view specifying how it should be arranged. There are many subclasses of
9749 * ViewGroup.LayoutParams, and these correspond to the different subclasses
9750 * of ViewGroup that are responsible for arranging their children.
Romain Guy01c174b2011-02-22 11:51:06 -08009751 *
9752 * This method may return null if this View is not attached to a parent
9753 * ViewGroup or {@link #setLayoutParams(android.view.ViewGroup.LayoutParams)}
9754 * was not invoked successfully. When a View is attached to a parent
9755 * ViewGroup, this method must not return null.
9756 *
9757 * @return The LayoutParams associated with this view, or null if no
9758 * parameters have been set yet
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009759 */
Konstantin Lopyrev91a7f5f2010-08-10 18:54:54 -07009760 @ViewDebug.ExportedProperty(deepExport = true, prefix = "layout_")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009761 public ViewGroup.LayoutParams getLayoutParams() {
9762 return mLayoutParams;
9763 }
9764
9765 /**
9766 * Set the layout parameters associated with this view. These supply
9767 * parameters to the <i>parent</i> of this view specifying how it should be
9768 * arranged. There are many subclasses of ViewGroup.LayoutParams, and these
9769 * correspond to the different subclasses of ViewGroup that are responsible
9770 * for arranging their children.
9771 *
Romain Guy01c174b2011-02-22 11:51:06 -08009772 * @param params The layout parameters for this view, cannot be null
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009773 */
9774 public void setLayoutParams(ViewGroup.LayoutParams params) {
9775 if (params == null) {
Romain Guy01c174b2011-02-22 11:51:06 -08009776 throw new NullPointerException("Layout parameters cannot be null");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009777 }
9778 mLayoutParams = params;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07009779 resolveLayoutParams();
Philip Milned7dd8902012-01-26 16:55:30 -08009780 if (mParent instanceof ViewGroup) {
9781 ((ViewGroup) mParent).onSetLayoutParams(this, params);
9782 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009783 requestLayout();
9784 }
9785
9786 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -07009787 * Resolve the layout parameters depending on the resolved layout direction
9788 */
9789 private void resolveLayoutParams() {
9790 if (mLayoutParams != null) {
9791 mLayoutParams.onResolveLayoutDirection(getResolvedLayoutDirection());
9792 }
9793 }
9794
9795 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009796 * Set the scrolled position of your view. This will cause a call to
9797 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9798 * invalidated.
9799 * @param x the x position to scroll to
9800 * @param y the y position to scroll to
9801 */
9802 public void scrollTo(int x, int y) {
9803 if (mScrollX != x || mScrollY != y) {
9804 int oldX = mScrollX;
9805 int oldY = mScrollY;
9806 mScrollX = x;
9807 mScrollY = y;
Romain Guy0fd89bf2011-01-26 15:41:30 -08009808 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009809 onScrollChanged(mScrollX, mScrollY, oldX, oldY);
Mike Cleronf116bf82009-09-27 19:14:12 -07009810 if (!awakenScrollBars()) {
Adam Powelldf3ae4f2012-04-10 18:55:22 -07009811 postInvalidateOnAnimation();
Mike Cleronf116bf82009-09-27 19:14:12 -07009812 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08009813 }
9814 }
9815
9816 /**
9817 * Move the scrolled position of your view. This will cause a call to
9818 * {@link #onScrollChanged(int, int, int, int)} and the view will be
9819 * invalidated.
9820 * @param x the amount of pixels to scroll by horizontally
9821 * @param y the amount of pixels to scroll by vertically
9822 */
9823 public void scrollBy(int x, int y) {
9824 scrollTo(mScrollX + x, mScrollY + y);
9825 }
9826
9827 /**
Mike Cleronf116bf82009-09-27 19:14:12 -07009828 * <p>Trigger the scrollbars to draw. When invoked this method starts an
9829 * animation to fade the scrollbars out after a default delay. If a subclass
9830 * provides animated scrolling, the start delay should equal the duration
9831 * of the scrolling animation.</p>
9832 *
9833 * <p>The animation starts only if at least one of the scrollbars is
9834 * enabled, as specified by {@link #isHorizontalScrollBarEnabled()} and
9835 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9836 * this method returns true, and false otherwise. If the animation is
9837 * started, this method calls {@link #invalidate()}; in that case the
9838 * caller should not call {@link #invalidate()}.</p>
9839 *
9840 * <p>This method should be invoked every time a subclass directly updates
Mike Cleronfe81d382009-09-28 14:22:16 -07009841 * the scroll parameters.</p>
Mike Cleronf116bf82009-09-27 19:14:12 -07009842 *
9843 * <p>This method is automatically invoked by {@link #scrollBy(int, int)}
9844 * and {@link #scrollTo(int, int)}.</p>
9845 *
9846 * @return true if the animation is played, false otherwise
9847 *
9848 * @see #awakenScrollBars(int)
Mike Cleronf116bf82009-09-27 19:14:12 -07009849 * @see #scrollBy(int, int)
9850 * @see #scrollTo(int, int)
9851 * @see #isHorizontalScrollBarEnabled()
9852 * @see #isVerticalScrollBarEnabled()
9853 * @see #setHorizontalScrollBarEnabled(boolean)
9854 * @see #setVerticalScrollBarEnabled(boolean)
9855 */
9856 protected boolean awakenScrollBars() {
9857 return mScrollCache != null &&
Mike Cleron290947b2009-09-29 18:34:32 -07009858 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade, true);
Mike Cleronf116bf82009-09-27 19:14:12 -07009859 }
9860
9861 /**
Adam Powell8568c3a2010-04-19 14:26:11 -07009862 * Trigger the scrollbars to draw.
9863 * This method differs from awakenScrollBars() only in its default duration.
9864 * initialAwakenScrollBars() will show the scroll bars for longer than
9865 * usual to give the user more of a chance to notice them.
9866 *
9867 * @return true if the animation is played, false otherwise.
9868 */
9869 private boolean initialAwakenScrollBars() {
9870 return mScrollCache != null &&
9871 awakenScrollBars(mScrollCache.scrollBarDefaultDelayBeforeFade * 4, true);
9872 }
9873
9874 /**
Mike Cleronf116bf82009-09-27 19:14:12 -07009875 * <p>
9876 * Trigger the scrollbars to draw. When invoked this method starts an
9877 * animation to fade the scrollbars out after a fixed delay. If a subclass
9878 * provides animated scrolling, the start delay should equal the duration of
9879 * the scrolling animation.
9880 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009881 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009882 * <p>
9883 * The animation starts only if at least one of the scrollbars is enabled,
9884 * as specified by {@link #isHorizontalScrollBarEnabled()} and
9885 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9886 * this method returns true, and false otherwise. If the animation is
9887 * started, this method calls {@link #invalidate()}; in that case the caller
9888 * should not call {@link #invalidate()}.
9889 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009890 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009891 * <p>
9892 * This method should be invoked everytime a subclass directly updates the
Mike Cleronfe81d382009-09-28 14:22:16 -07009893 * scroll parameters.
Mike Cleronf116bf82009-09-27 19:14:12 -07009894 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009895 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009896 * @param startDelay the delay, in milliseconds, after which the animation
9897 * should start; when the delay is 0, the animation starts
9898 * immediately
9899 * @return true if the animation is played, false otherwise
Joe Malin32736f02011-01-19 16:14:20 -08009900 *
Mike Cleronf116bf82009-09-27 19:14:12 -07009901 * @see #scrollBy(int, int)
9902 * @see #scrollTo(int, int)
9903 * @see #isHorizontalScrollBarEnabled()
9904 * @see #isVerticalScrollBarEnabled()
9905 * @see #setHorizontalScrollBarEnabled(boolean)
9906 * @see #setVerticalScrollBarEnabled(boolean)
9907 */
9908 protected boolean awakenScrollBars(int startDelay) {
Mike Cleron290947b2009-09-29 18:34:32 -07009909 return awakenScrollBars(startDelay, true);
9910 }
Joe Malin32736f02011-01-19 16:14:20 -08009911
Mike Cleron290947b2009-09-29 18:34:32 -07009912 /**
9913 * <p>
9914 * Trigger the scrollbars to draw. When invoked this method starts an
9915 * animation to fade the scrollbars out after a fixed delay. If a subclass
9916 * provides animated scrolling, the start delay should equal the duration of
9917 * the scrolling animation.
9918 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009919 *
Mike Cleron290947b2009-09-29 18:34:32 -07009920 * <p>
9921 * The animation starts only if at least one of the scrollbars is enabled,
9922 * as specified by {@link #isHorizontalScrollBarEnabled()} and
9923 * {@link #isVerticalScrollBarEnabled()}. When the animation is started,
9924 * this method returns true, and false otherwise. If the animation is
Joe Malin32736f02011-01-19 16:14:20 -08009925 * started, this method calls {@link #invalidate()} if the invalidate parameter
Mike Cleron290947b2009-09-29 18:34:32 -07009926 * is set to true; in that case the caller
9927 * should not call {@link #invalidate()}.
9928 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009929 *
Mike Cleron290947b2009-09-29 18:34:32 -07009930 * <p>
9931 * This method should be invoked everytime a subclass directly updates the
9932 * scroll parameters.
9933 * </p>
Joe Malin32736f02011-01-19 16:14:20 -08009934 *
Mike Cleron290947b2009-09-29 18:34:32 -07009935 * @param startDelay the delay, in milliseconds, after which the animation
9936 * should start; when the delay is 0, the animation starts
9937 * immediately
Joe Malin32736f02011-01-19 16:14:20 -08009938 *
Mike Cleron290947b2009-09-29 18:34:32 -07009939 * @param invalidate Wheter this method should call invalidate
Joe Malin32736f02011-01-19 16:14:20 -08009940 *
Mike Cleron290947b2009-09-29 18:34:32 -07009941 * @return true if the animation is played, false otherwise
Joe Malin32736f02011-01-19 16:14:20 -08009942 *
Mike Cleron290947b2009-09-29 18:34:32 -07009943 * @see #scrollBy(int, int)
9944 * @see #scrollTo(int, int)
9945 * @see #isHorizontalScrollBarEnabled()
9946 * @see #isVerticalScrollBarEnabled()
9947 * @see #setHorizontalScrollBarEnabled(boolean)
9948 * @see #setVerticalScrollBarEnabled(boolean)
9949 */
9950 protected boolean awakenScrollBars(int startDelay, boolean invalidate) {
Mike Cleronf116bf82009-09-27 19:14:12 -07009951 final ScrollabilityCache scrollCache = mScrollCache;
Joe Malin32736f02011-01-19 16:14:20 -08009952
Mike Cleronf116bf82009-09-27 19:14:12 -07009953 if (scrollCache == null || !scrollCache.fadeScrollBars) {
9954 return false;
9955 }
9956
9957 if (scrollCache.scrollBar == null) {
9958 scrollCache.scrollBar = new ScrollBarDrawable();
9959 }
9960
9961 if (isHorizontalScrollBarEnabled() || isVerticalScrollBarEnabled()) {
9962
Mike Cleron290947b2009-09-29 18:34:32 -07009963 if (invalidate) {
9964 // Invalidate to show the scrollbars
Adam Powelldf3ae4f2012-04-10 18:55:22 -07009965 postInvalidateOnAnimation();
Mike Cleron290947b2009-09-29 18:34:32 -07009966 }
Mike Cleronf116bf82009-09-27 19:14:12 -07009967
9968 if (scrollCache.state == ScrollabilityCache.OFF) {
9969 // FIXME: this is copied from WindowManagerService.
9970 // We should get this value from the system when it
9971 // is possible to do so.
9972 final int KEY_REPEAT_FIRST_DELAY = 750;
9973 startDelay = Math.max(KEY_REPEAT_FIRST_DELAY, startDelay);
9974 }
9975
9976 // Tell mScrollCache when we should start fading. This may
9977 // extend the fade start time if one was already scheduled
Mike Cleron3ecd58c2009-09-28 11:39:02 -07009978 long fadeStartTime = AnimationUtils.currentAnimationTimeMillis() + startDelay;
Mike Cleronf116bf82009-09-27 19:14:12 -07009979 scrollCache.fadeStartTime = fadeStartTime;
9980 scrollCache.state = ScrollabilityCache.ON;
9981
9982 // Schedule our fader to run, unscheduling any old ones first
9983 if (mAttachInfo != null) {
9984 mAttachInfo.mHandler.removeCallbacks(scrollCache);
9985 mAttachInfo.mHandler.postAtTime(scrollCache, fadeStartTime);
9986 }
9987
9988 return true;
9989 }
9990
9991 return false;
9992 }
9993
9994 /**
Chet Haaseaceafe62011-08-26 15:44:33 -07009995 * Do not invalidate views which are not visible and which are not running an animation. They
9996 * will not get drawn and they should not set dirty flags as if they will be drawn
9997 */
9998 private boolean skipInvalidate() {
9999 return (mViewFlags & VISIBILITY_MASK) != VISIBLE && mCurrentAnimation == null &&
10000 (!(mParent instanceof ViewGroup) ||
10001 !((ViewGroup) mParent).isViewTransitioning(this));
10002 }
10003 /**
Joe Fernandez558459f2011-10-13 16:47:36 -070010004 * Mark the area defined by dirty as needing to be drawn. If the view is
Romain Guy5c22a8c2011-05-13 11:48:45 -070010005 * visible, {@link #onDraw(android.graphics.Canvas)} will be called at some point
10006 * in the future. This must be called from a UI thread. To call from a non-UI
10007 * thread, call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010008 *
10009 * WARNING: This method is destructive to dirty.
10010 * @param dirty the rectangle representing the bounds of the dirty region
10011 */
10012 public void invalidate(Rect dirty) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010013 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010014 return;
10015 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070010016 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10017 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10018 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10019 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10020 mPrivateFlags |= PFLAG_INVALIDATED;
10021 mPrivateFlags |= PFLAG_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010022 final ViewParent p = mParent;
10023 final AttachInfo ai = mAttachInfo;
Romain Guy7d7b5492011-01-24 16:33:45 -080010024 //noinspection PointlessBooleanExpression,ConstantConditions
10025 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10026 if (p != null && ai != null && ai.mHardwareAccelerated) {
10027 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010028 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010029 p.invalidateChild(this, null);
10030 return;
10031 }
Romain Guyaf636eb2010-12-09 17:47:21 -080010032 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010033 if (p != null && ai != null) {
10034 final int scrollX = mScrollX;
10035 final int scrollY = mScrollY;
10036 final Rect r = ai.mTmpInvalRect;
10037 r.set(dirty.left - scrollX, dirty.top - scrollY,
10038 dirty.right - scrollX, dirty.bottom - scrollY);
10039 mParent.invalidateChild(this, r);
10040 }
10041 }
10042 }
10043
10044 /**
Joe Fernandez558459f2011-10-13 16:47:36 -070010045 * 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 -080010046 * The coordinates of the dirty rect are relative to the view.
Romain Guy5c22a8c2011-05-13 11:48:45 -070010047 * If the view is visible, {@link #onDraw(android.graphics.Canvas)}
10048 * will be called at some point in the future. This must be called from
10049 * a UI thread. To call from a non-UI thread, call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010050 * @param l the left position of the dirty region
10051 * @param t the top position of the dirty region
10052 * @param r the right position of the dirty region
10053 * @param b the bottom position of the dirty region
10054 */
10055 public void invalidate(int l, int t, int r, int b) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010056 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010057 return;
10058 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070010059 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10060 (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID ||
10061 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED) {
10062 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
10063 mPrivateFlags |= PFLAG_INVALIDATED;
10064 mPrivateFlags |= PFLAG_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010065 final ViewParent p = mParent;
10066 final AttachInfo ai = mAttachInfo;
Romain Guy7d7b5492011-01-24 16:33:45 -080010067 //noinspection PointlessBooleanExpression,ConstantConditions
10068 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10069 if (p != null && ai != null && ai.mHardwareAccelerated) {
10070 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010071 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010072 p.invalidateChild(this, null);
10073 return;
10074 }
Chet Haasef2f7d8f2010-12-03 14:08:14 -080010075 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010076 if (p != null && ai != null && l < r && t < b) {
10077 final int scrollX = mScrollX;
10078 final int scrollY = mScrollY;
10079 final Rect tmpr = ai.mTmpInvalRect;
10080 tmpr.set(l - scrollX, t - scrollY, r - scrollX, b - scrollY);
10081 p.invalidateChild(this, tmpr);
10082 }
10083 }
10084 }
10085
10086 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070010087 * Invalidate the whole view. If the view is visible,
10088 * {@link #onDraw(android.graphics.Canvas)} will be called at some point in
10089 * the future. This must be called from a UI thread. To call from a non-UI thread,
10090 * call {@link #postInvalidate()}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010091 */
10092 public void invalidate() {
Chet Haaseed032702010-10-01 14:05:54 -070010093 invalidate(true);
10094 }
Joe Malin32736f02011-01-19 16:14:20 -080010095
Chet Haaseed032702010-10-01 14:05:54 -070010096 /**
10097 * This is where the invalidate() work actually happens. A full invalidate()
10098 * causes the drawing cache to be invalidated, but this function can be called with
10099 * invalidateCache set to false to skip that invalidation step for cases that do not
10100 * need it (for example, a component that remains at the same dimensions with the same
10101 * content).
10102 *
10103 * @param invalidateCache Whether the drawing cache for this view should be invalidated as
10104 * well. This is usually true for a full invalidate, but may be set to false if the
10105 * View's contents or dimensions have not changed.
10106 */
Romain Guy849d0a32011-02-01 17:20:48 -080010107 void invalidate(boolean invalidateCache) {
Chet Haaseaceafe62011-08-26 15:44:33 -070010108 if (skipInvalidate()) {
Chet Haasea68c5cf2011-08-22 14:27:51 -070010109 return;
10110 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070010111 if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS) ||
10112 (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) ||
10113 (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED || isOpaque() != mLastIsOpaque) {
Romain Guy0fd89bf2011-01-26 15:41:30 -080010114 mLastIsOpaque = isOpaque();
Dianne Hackborn4702a852012-08-17 15:18:29 -070010115 mPrivateFlags &= ~PFLAG_DRAWN;
10116 mPrivateFlags |= PFLAG_DIRTY;
Chet Haaseed032702010-10-01 14:05:54 -070010117 if (invalidateCache) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010118 mPrivateFlags |= PFLAG_INVALIDATED;
10119 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
Chet Haaseed032702010-10-01 14:05:54 -070010120 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010121 final AttachInfo ai = mAttachInfo;
Chet Haase70d4ba12010-10-06 09:46:45 -070010122 final ViewParent p = mParent;
Romain Guy7d7b5492011-01-24 16:33:45 -080010123 //noinspection PointlessBooleanExpression,ConstantConditions
10124 if (!HardwareRenderer.RENDER_DIRTY_REGIONS) {
10125 if (p != null && ai != null && ai.mHardwareAccelerated) {
10126 // fast-track for GL-enabled applications; just invalidate the whole hierarchy
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070010127 // with a null dirty rect, which tells the ViewAncestor to redraw everything
Romain Guy7d7b5492011-01-24 16:33:45 -080010128 p.invalidateChild(this, null);
10129 return;
10130 }
Chet Haasef2f7d8f2010-12-03 14:08:14 -080010131 }
Michael Jurkaebefea42010-11-15 16:04:01 -080010132
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010133 if (p != null && ai != null) {
10134 final Rect r = ai.mTmpInvalRect;
10135 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10136 // Don't call invalidate -- we don't want to internally scroll
10137 // our own bounds
10138 p.invalidateChild(this, r);
10139 }
10140 }
10141 }
10142
10143 /**
Chet Haase9d1992d2012-03-13 11:03:25 -070010144 * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
10145 * set any flags or handle all of the cases handled by the default invalidation methods.
10146 * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
10147 * dirty rect. This method calls into fast invalidation methods in ViewGroup that
10148 * walk up the hierarchy, transforming the dirty rect as necessary.
10149 *
10150 * The method also handles normal invalidation logic if display list properties are not
10151 * being used in this view. The invalidateParent and forceRedraw flags are used by that
10152 * backup approach, to handle these cases used in the various property-setting methods.
10153 *
10154 * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
10155 * are not being used in this view
10156 * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
10157 * list properties are not being used in this view
10158 */
10159 void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010160 if (mDisplayList == null || (mPrivateFlags & PFLAG_DRAW_ANIMATION) == PFLAG_DRAW_ANIMATION) {
Chet Haase9d1992d2012-03-13 11:03:25 -070010161 if (invalidateParent) {
10162 invalidateParentCaches();
10163 }
10164 if (forceRedraw) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010165 mPrivateFlags |= PFLAG_DRAWN; // force another invalidation with the new orientation
Chet Haase9d1992d2012-03-13 11:03:25 -070010166 }
10167 invalidate(false);
10168 } else {
10169 final AttachInfo ai = mAttachInfo;
10170 final ViewParent p = mParent;
10171 if (p != null && ai != null) {
10172 final Rect r = ai.mTmpInvalRect;
10173 r.set(0, 0, mRight - mLeft, mBottom - mTop);
10174 if (mParent instanceof ViewGroup) {
10175 ((ViewGroup) mParent).invalidateChildFast(this, r);
10176 } else {
10177 mParent.invalidateChild(this, r);
10178 }
10179 }
10180 }
10181 }
10182
10183 /**
10184 * Utility method to transform a given Rect by the current matrix of this view.
10185 */
10186 void transformRect(final Rect rect) {
10187 if (!getMatrix().isIdentity()) {
10188 RectF boundingRect = mAttachInfo.mTmpTransformRect;
10189 boundingRect.set(rect);
10190 getMatrix().mapRect(boundingRect);
10191 rect.set((int) (boundingRect.left - 0.5f),
10192 (int) (boundingRect.top - 0.5f),
10193 (int) (boundingRect.right + 0.5f),
10194 (int) (boundingRect.bottom + 0.5f));
10195 }
10196 }
10197
10198 /**
Romain Guy0fd89bf2011-01-26 15:41:30 -080010199 * Used to indicate that the parent of this view should clear its caches. This functionality
Chet Haasedaf98e92011-01-10 14:10:36 -080010200 * is used to force the parent to rebuild its display list (when hardware-accelerated),
10201 * which is necessary when various parent-managed properties of the view change, such as
Romain Guy0fd89bf2011-01-26 15:41:30 -080010202 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only
10203 * clears the parent caches and does not causes an invalidate event.
Chet Haasedaf98e92011-01-10 14:10:36 -080010204 *
10205 * @hide
10206 */
Romain Guy0fd89bf2011-01-26 15:41:30 -080010207 protected void invalidateParentCaches() {
10208 if (mParent instanceof View) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010209 ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;
Romain Guy0fd89bf2011-01-26 15:41:30 -080010210 }
10211 }
Joe Malin32736f02011-01-19 16:14:20 -080010212
Romain Guy0fd89bf2011-01-26 15:41:30 -080010213 /**
10214 * Used to indicate that the parent of this view should be invalidated. This functionality
10215 * is used to force the parent to rebuild its display list (when hardware-accelerated),
10216 * which is necessary when various parent-managed properties of the view change, such as
10217 * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method will propagate
10218 * an invalidation event to the parent.
10219 *
10220 * @hide
10221 */
10222 protected void invalidateParentIfNeeded() {
Chet Haasedaf98e92011-01-10 14:10:36 -080010223 if (isHardwareAccelerated() && mParent instanceof View) {
Romain Guy0fd89bf2011-01-26 15:41:30 -080010224 ((View) mParent).invalidate(true);
Chet Haasedaf98e92011-01-10 14:10:36 -080010225 }
10226 }
10227
10228 /**
Romain Guy24443ea2009-05-11 11:56:30 -070010229 * Indicates whether this View is opaque. An opaque View guarantees that it will
10230 * draw all the pixels overlapping its bounds using a fully opaque color.
10231 *
10232 * Subclasses of View should override this method whenever possible to indicate
10233 * whether an instance is opaque. Opaque Views are treated in a special way by
10234 * the View hierarchy, possibly allowing it to perform optimizations during
10235 * invalidate/draw passes.
Romain Guy8506ab42009-06-11 17:35:47 -070010236 *
Romain Guy24443ea2009-05-11 11:56:30 -070010237 * @return True if this View is guaranteed to be fully opaque, false otherwise.
Romain Guy24443ea2009-05-11 11:56:30 -070010238 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070010239 @ViewDebug.ExportedProperty(category = "drawing")
Romain Guy24443ea2009-05-11 11:56:30 -070010240 public boolean isOpaque() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010241 return (mPrivateFlags & PFLAG_OPAQUE_MASK) == PFLAG_OPAQUE_MASK &&
Romain Guyf8773082012-07-12 18:01:00 -070010242 ((mTransformationInfo != null ? mTransformationInfo.mAlpha : 1.0f) >= 1.0f);
Romain Guy8f1344f52009-05-15 16:03:59 -070010243 }
10244
Adam Powell20232d02010-12-08 21:08:53 -080010245 /**
10246 * @hide
10247 */
10248 protected void computeOpaqueFlags() {
Romain Guy8f1344f52009-05-15 16:03:59 -070010249 // Opaque if:
10250 // - Has a background
10251 // - Background is opaque
10252 // - Doesn't have scrollbars or scrollbars are inside overlay
10253
Philip Milne6c8ea062012-04-03 17:38:43 -070010254 if (mBackground != null && mBackground.getOpacity() == PixelFormat.OPAQUE) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010255 mPrivateFlags |= PFLAG_OPAQUE_BACKGROUND;
Romain Guy8f1344f52009-05-15 16:03:59 -070010256 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010257 mPrivateFlags &= ~PFLAG_OPAQUE_BACKGROUND;
Romain Guy8f1344f52009-05-15 16:03:59 -070010258 }
10259
10260 final int flags = mViewFlags;
10261 if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
10262 (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010263 mPrivateFlags |= PFLAG_OPAQUE_SCROLLBARS;
Romain Guy8f1344f52009-05-15 16:03:59 -070010264 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010265 mPrivateFlags &= ~PFLAG_OPAQUE_SCROLLBARS;
Romain Guy8f1344f52009-05-15 16:03:59 -070010266 }
10267 }
10268
10269 /**
10270 * @hide
10271 */
10272 protected boolean hasOpaqueScrollbars() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070010273 return (mPrivateFlags & PFLAG_OPAQUE_SCROLLBARS) == PFLAG_OPAQUE_SCROLLBARS;
Romain Guy24443ea2009-05-11 11:56:30 -070010274 }
10275
10276 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010277 * @return A handler associated with the thread running the View. This
10278 * handler can be used to pump events in the UI events queue.
10279 */
10280 public Handler getHandler() {
10281 if (mAttachInfo != null) {
10282 return mAttachInfo.mHandler;
10283 }
10284 return null;
10285 }
10286
10287 /**
Jeff Browna175a5b2012-02-15 19:18:31 -080010288 * Gets the view root associated with the View.
10289 * @return The view root, or null if none.
10290 * @hide
10291 */
10292 public ViewRootImpl getViewRootImpl() {
10293 if (mAttachInfo != null) {
10294 return mAttachInfo.mViewRootImpl;
10295 }
10296 return null;
10297 }
10298
10299 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010300 * <p>Causes the Runnable to be added to the message queue.
10301 * The runnable will be run on the user interface thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010302 *
Romain Guye63a4f32011-08-11 11:33:31 -070010303 * <p>This method can be invoked from outside of the UI thread
10304 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010305 *
10306 * @param action The Runnable that will be executed.
10307 *
10308 * @return Returns true if the Runnable was successfully placed in to the
10309 * message queue. Returns false on failure, usually because the
10310 * looper processing the message queue is exiting.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010311 *
10312 * @see #postDelayed
10313 * @see #removeCallbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010314 */
10315 public boolean post(Runnable action) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010316 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010317 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010318 return attachInfo.mHandler.post(action);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010319 }
Jeff Browna175a5b2012-02-15 19:18:31 -080010320 // Assume that post will succeed later
10321 ViewRootImpl.getRunQueue().post(action);
10322 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010323 }
10324
10325 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010326 * <p>Causes the Runnable to be added to the message queue, to be run
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010327 * after the specified amount of time elapses.
Romain Guye63a4f32011-08-11 11:33:31 -070010328 * The runnable will be run on the user interface thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010329 *
Romain Guye63a4f32011-08-11 11:33:31 -070010330 * <p>This method can be invoked from outside of the UI thread
10331 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010332 *
10333 * @param action The Runnable that will be executed.
10334 * @param delayMillis The delay (in milliseconds) until the Runnable
10335 * will be executed.
10336 *
10337 * @return true if the Runnable was successfully placed in to the
10338 * message queue. Returns false on failure, usually because the
10339 * looper processing the message queue is exiting. Note that a
10340 * result of true does not mean the Runnable will be processed --
10341 * if the looper is quit before the delivery time of the message
10342 * occurs then the message will be dropped.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010343 *
10344 * @see #post
10345 * @see #removeCallbacks
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010346 */
10347 public boolean postDelayed(Runnable action, long delayMillis) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010348 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010349 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010350 return attachInfo.mHandler.postDelayed(action, delayMillis);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010351 }
Jeff Browna175a5b2012-02-15 19:18:31 -080010352 // Assume that post will succeed later
10353 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10354 return true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010355 }
10356
10357 /**
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010358 * <p>Causes the Runnable to execute on the next animation time step.
10359 * The runnable will be run on the user interface thread.</p>
10360 *
10361 * <p>This method can be invoked from outside of the UI thread
10362 * only when this View is attached to a window.</p>
10363 *
10364 * @param action The Runnable that will be executed.
10365 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010366 * @see #postOnAnimationDelayed
10367 * @see #removeCallbacks
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010368 */
10369 public void postOnAnimation(Runnable action) {
10370 final AttachInfo attachInfo = mAttachInfo;
10371 if (attachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010372 attachInfo.mViewRootImpl.mChoreographer.postCallback(
10373 Choreographer.CALLBACK_ANIMATION, action, null);
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010374 } else {
10375 // Assume that post will succeed later
10376 ViewRootImpl.getRunQueue().post(action);
10377 }
10378 }
10379
10380 /**
10381 * <p>Causes the Runnable to execute on the next animation time step,
10382 * after the specified amount of time elapses.
10383 * The runnable will be run on the user interface thread.</p>
10384 *
10385 * <p>This method can be invoked from outside of the UI thread
10386 * only when this View is attached to a window.</p>
10387 *
10388 * @param action The Runnable that will be executed.
10389 * @param delayMillis The delay (in milliseconds) until the Runnable
10390 * will be executed.
10391 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010392 * @see #postOnAnimation
10393 * @see #removeCallbacks
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010394 */
10395 public void postOnAnimationDelayed(Runnable action, long delayMillis) {
10396 final AttachInfo attachInfo = mAttachInfo;
10397 if (attachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010398 attachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
10399 Choreographer.CALLBACK_ANIMATION, action, null, delayMillis);
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080010400 } else {
10401 // Assume that post will succeed later
10402 ViewRootImpl.getRunQueue().postDelayed(action, delayMillis);
10403 }
10404 }
10405
10406 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010407 * <p>Removes the specified Runnable from the message queue.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010408 *
Romain Guye63a4f32011-08-11 11:33:31 -070010409 * <p>This method can be invoked from outside of the UI thread
10410 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010411 *
10412 * @param action The Runnable to remove from the message handling queue
10413 *
10414 * @return true if this view could ask the Handler to remove the Runnable,
10415 * false otherwise. When the returned value is true, the Runnable
10416 * may or may not have been actually removed from the message queue
10417 * (for instance, if the Runnable was not in the queue already.)
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010418 *
10419 * @see #post
10420 * @see #postDelayed
10421 * @see #postOnAnimation
10422 * @see #postOnAnimationDelayed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010423 */
10424 public boolean removeCallbacks(Runnable action) {
Jeff Brown43ea54b2012-03-09 14:37:48 -080010425 if (action != null) {
10426 final AttachInfo attachInfo = mAttachInfo;
10427 if (attachInfo != null) {
10428 attachInfo.mHandler.removeCallbacks(action);
Jeff Brownebb2d8d2012-03-23 17:14:34 -070010429 attachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
10430 Choreographer.CALLBACK_ANIMATION, action, null);
Jeff Brown43ea54b2012-03-09 14:37:48 -080010431 } else {
10432 // Assume that post will succeed later
10433 ViewRootImpl.getRunQueue().removeCallbacks(action);
10434 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010435 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010436 return true;
10437 }
10438
10439 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010440 * <p>Cause an invalidate to happen on a subsequent cycle through the event loop.
10441 * Use this to invalidate the View from a non-UI thread.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010442 *
Romain Guye63a4f32011-08-11 11:33:31 -070010443 * <p>This method can be invoked from outside of the UI thread
10444 * only when this View is attached to a window.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010445 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010446 * @see #invalidate()
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010447 * @see #postInvalidateDelayed(long)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010448 */
10449 public void postInvalidate() {
10450 postInvalidateDelayed(0);
10451 }
10452
10453 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010454 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10455 * through the event loop. Use this to invalidate the View from a non-UI thread.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010456 *
Romain Guye63a4f32011-08-11 11:33:31 -070010457 * <p>This method can be invoked from outside of the UI thread
10458 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010459 *
10460 * @param left The left coordinate of the rectangle to invalidate.
10461 * @param top The top coordinate of the rectangle to invalidate.
10462 * @param right The right coordinate of the rectangle to invalidate.
10463 * @param bottom The bottom coordinate of the rectangle to invalidate.
10464 *
10465 * @see #invalidate(int, int, int, int)
10466 * @see #invalidate(Rect)
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010467 * @see #postInvalidateDelayed(long, int, int, int, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010468 */
10469 public void postInvalidate(int left, int top, int right, int bottom) {
10470 postInvalidateDelayed(0, left, top, right, bottom);
10471 }
10472
10473 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010474 * <p>Cause an invalidate to happen on a subsequent cycle through the event
10475 * loop. Waits for the specified amount of time.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010476 *
Romain Guye63a4f32011-08-11 11:33:31 -070010477 * <p>This method can be invoked from outside of the UI thread
10478 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010479 *
10480 * @param delayMilliseconds the duration in milliseconds to delay the
10481 * invalidation by
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010482 *
10483 * @see #invalidate()
10484 * @see #postInvalidate()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010485 */
10486 public void postInvalidateDelayed(long delayMilliseconds) {
10487 // We try only with the AttachInfo because there's no point in invalidating
10488 // if we are not attached to our window
Jeff Browna175a5b2012-02-15 19:18:31 -080010489 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010490 if (attachInfo != null) {
Jeff Browna175a5b2012-02-15 19:18:31 -080010491 attachInfo.mViewRootImpl.dispatchInvalidateDelayed(this, delayMilliseconds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010492 }
10493 }
10494
10495 /**
Romain Guye63a4f32011-08-11 11:33:31 -070010496 * <p>Cause an invalidate of the specified area to happen on a subsequent cycle
10497 * through the event loop. Waits for the specified amount of time.</p>
Philip Milne6c8ea062012-04-03 17:38:43 -070010498 *
Romain Guye63a4f32011-08-11 11:33:31 -070010499 * <p>This method can be invoked from outside of the UI thread
10500 * only when this View is attached to a window.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010501 *
10502 * @param delayMilliseconds the duration in milliseconds to delay the
10503 * invalidation by
10504 * @param left The left coordinate of the rectangle to invalidate.
10505 * @param top The top coordinate of the rectangle to invalidate.
10506 * @param right The right coordinate of the rectangle to invalidate.
10507 * @param bottom The bottom coordinate of the rectangle to invalidate.
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010508 *
10509 * @see #invalidate(int, int, int, int)
10510 * @see #invalidate(Rect)
10511 * @see #postInvalidate(int, int, int, int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010512 */
10513 public void postInvalidateDelayed(long delayMilliseconds, int left, int top,
10514 int right, int bottom) {
10515
10516 // We try only with the AttachInfo because there's no point in invalidating
10517 // if we are not attached to our window
Jeff Browna175a5b2012-02-15 19:18:31 -080010518 final AttachInfo attachInfo = mAttachInfo;
Romain Guyc5a43a22011-03-24 13:28:56 -070010519 if (attachInfo != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010520 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10521 info.target = this;
10522 info.left = left;
10523 info.top = top;
10524 info.right = right;
10525 info.bottom = bottom;
10526
Jeff Browna175a5b2012-02-15 19:18:31 -080010527 attachInfo.mViewRootImpl.dispatchInvalidateRectDelayed(info, delayMilliseconds);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010528 }
10529 }
10530
10531 /**
Jeff Brown6cb7b462012-03-05 13:21:17 -080010532 * <p>Cause an invalidate to happen on the next animation time step, typically the
10533 * next display frame.</p>
10534 *
10535 * <p>This method can be invoked from outside of the UI thread
10536 * only when this View is attached to a window.</p>
10537 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010538 * @see #invalidate()
Jeff Brown6cb7b462012-03-05 13:21:17 -080010539 */
10540 public void postInvalidateOnAnimation() {
10541 // We try only with the AttachInfo because there's no point in invalidating
10542 // if we are not attached to our window
10543 final AttachInfo attachInfo = mAttachInfo;
10544 if (attachInfo != null) {
10545 attachInfo.mViewRootImpl.dispatchInvalidateOnAnimation(this);
10546 }
10547 }
10548
10549 /**
10550 * <p>Cause an invalidate of the specified area to happen on the next animation
10551 * time step, typically the next display frame.</p>
10552 *
10553 * <p>This method can be invoked from outside of the UI thread
10554 * only when this View is attached to a window.</p>
10555 *
10556 * @param left The left coordinate of the rectangle to invalidate.
10557 * @param top The top coordinate of the rectangle to invalidate.
10558 * @param right The right coordinate of the rectangle to invalidate.
10559 * @param bottom The bottom coordinate of the rectangle to invalidate.
10560 *
Jeff Brown4d6a82d2012-04-11 14:23:51 -070010561 * @see #invalidate(int, int, int, int)
10562 * @see #invalidate(Rect)
Jeff Brown6cb7b462012-03-05 13:21:17 -080010563 */
10564 public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {
10565 // We try only with the AttachInfo because there's no point in invalidating
10566 // if we are not attached to our window
10567 final AttachInfo attachInfo = mAttachInfo;
10568 if (attachInfo != null) {
10569 final AttachInfo.InvalidateInfo info = AttachInfo.InvalidateInfo.acquire();
10570 info.target = this;
10571 info.left = left;
10572 info.top = top;
10573 info.right = right;
10574 info.bottom = bottom;
10575
10576 attachInfo.mViewRootImpl.dispatchInvalidateRectOnAnimation(info);
10577 }
10578 }
10579
10580 /**
Svetoslav Ganova0156172011-06-26 17:55:44 -070010581 * Post a callback to send a {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} event.
10582 * This event is sent at most once every
10583 * {@link ViewConfiguration#getSendRecurringAccessibilityEventsInterval()}.
10584 */
10585 private void postSendViewScrolledAccessibilityEventCallback() {
10586 if (mSendViewScrolledAccessibilityEvent == null) {
10587 mSendViewScrolledAccessibilityEvent = new SendViewScrolledAccessibilityEvent();
10588 }
10589 if (!mSendViewScrolledAccessibilityEvent.mIsPending) {
10590 mSendViewScrolledAccessibilityEvent.mIsPending = true;
10591 postDelayed(mSendViewScrolledAccessibilityEvent,
10592 ViewConfiguration.getSendRecurringAccessibilityEventsInterval());
10593 }
10594 }
10595
10596 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010597 * Called by a parent to request that a child update its values for mScrollX
10598 * and mScrollY if necessary. This will typically be done if the child is
10599 * animating a scroll using a {@link android.widget.Scroller Scroller}
10600 * object.
10601 */
10602 public void computeScroll() {
10603 }
10604
10605 /**
10606 * <p>Indicate whether the horizontal edges are faded when the view is
10607 * scrolled horizontally.</p>
10608 *
10609 * @return true if the horizontal edges should are faded on scroll, false
10610 * otherwise
10611 *
10612 * @see #setHorizontalFadingEdgeEnabled(boolean)
Philip Milne6c8ea062012-04-03 17:38:43 -070010613 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010614 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010615 */
10616 public boolean isHorizontalFadingEdgeEnabled() {
10617 return (mViewFlags & FADING_EDGE_HORIZONTAL) == FADING_EDGE_HORIZONTAL;
10618 }
10619
10620 /**
10621 * <p>Define whether the horizontal edges should be faded when this view
10622 * is scrolled horizontally.</p>
10623 *
10624 * @param horizontalFadingEdgeEnabled true if the horizontal edges should
10625 * be faded when the view is scrolled
10626 * horizontally
10627 *
10628 * @see #isHorizontalFadingEdgeEnabled()
Philip Milne6c8ea062012-04-03 17:38:43 -070010629 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010630 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010631 */
10632 public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {
10633 if (isHorizontalFadingEdgeEnabled() != horizontalFadingEdgeEnabled) {
10634 if (horizontalFadingEdgeEnabled) {
10635 initScrollCache();
10636 }
10637
10638 mViewFlags ^= FADING_EDGE_HORIZONTAL;
10639 }
10640 }
10641
10642 /**
10643 * <p>Indicate whether the vertical edges are faded when the view is
10644 * scrolled horizontally.</p>
10645 *
10646 * @return true if the vertical edges should are faded on scroll, false
10647 * otherwise
10648 *
10649 * @see #setVerticalFadingEdgeEnabled(boolean)
Philip Milne6c8ea062012-04-03 17:38:43 -070010650 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010651 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010652 */
10653 public boolean isVerticalFadingEdgeEnabled() {
10654 return (mViewFlags & FADING_EDGE_VERTICAL) == FADING_EDGE_VERTICAL;
10655 }
10656
10657 /**
10658 * <p>Define whether the vertical edges should be faded when this view
10659 * is scrolled vertically.</p>
10660 *
10661 * @param verticalFadingEdgeEnabled true if the vertical edges should
10662 * be faded when the view is scrolled
10663 * vertically
10664 *
10665 * @see #isVerticalFadingEdgeEnabled()
Philip Milne6c8ea062012-04-03 17:38:43 -070010666 *
Romain Guy1ef3fdb2011-09-09 15:30:30 -070010667 * @attr ref android.R.styleable#View_requiresFadingEdge
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010668 */
10669 public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {
10670 if (isVerticalFadingEdgeEnabled() != verticalFadingEdgeEnabled) {
10671 if (verticalFadingEdgeEnabled) {
10672 initScrollCache();
10673 }
10674
10675 mViewFlags ^= FADING_EDGE_VERTICAL;
10676 }
10677 }
10678
10679 /**
10680 * Returns the strength, or intensity, of the top faded edge. The strength is
10681 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10682 * returns 0.0 or 1.0 but no value in between.
10683 *
10684 * Subclasses should override this method to provide a smoother fade transition
10685 * when scrolling occurs.
10686 *
10687 * @return the intensity of the top fade as a float between 0.0f and 1.0f
10688 */
10689 protected float getTopFadingEdgeStrength() {
10690 return computeVerticalScrollOffset() > 0 ? 1.0f : 0.0f;
10691 }
10692
10693 /**
10694 * Returns the strength, or intensity, of the bottom faded edge. The strength is
10695 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10696 * returns 0.0 or 1.0 but no value in between.
10697 *
10698 * Subclasses should override this method to provide a smoother fade transition
10699 * when scrolling occurs.
10700 *
10701 * @return the intensity of the bottom fade as a float between 0.0f and 1.0f
10702 */
10703 protected float getBottomFadingEdgeStrength() {
10704 return computeVerticalScrollOffset() + computeVerticalScrollExtent() <
10705 computeVerticalScrollRange() ? 1.0f : 0.0f;
10706 }
10707
10708 /**
10709 * Returns the strength, or intensity, of the left faded edge. The strength is
10710 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10711 * returns 0.0 or 1.0 but no value in between.
10712 *
10713 * Subclasses should override this method to provide a smoother fade transition
10714 * when scrolling occurs.
10715 *
10716 * @return the intensity of the left fade as a float between 0.0f and 1.0f
10717 */
10718 protected float getLeftFadingEdgeStrength() {
10719 return computeHorizontalScrollOffset() > 0 ? 1.0f : 0.0f;
10720 }
10721
10722 /**
10723 * Returns the strength, or intensity, of the right faded edge. The strength is
10724 * a value between 0.0 (no fade) and 1.0 (full fade). The default implementation
10725 * returns 0.0 or 1.0 but no value in between.
10726 *
10727 * Subclasses should override this method to provide a smoother fade transition
10728 * when scrolling occurs.
10729 *
10730 * @return the intensity of the right fade as a float between 0.0f and 1.0f
10731 */
10732 protected float getRightFadingEdgeStrength() {
10733 return computeHorizontalScrollOffset() + computeHorizontalScrollExtent() <
10734 computeHorizontalScrollRange() ? 1.0f : 0.0f;
10735 }
10736
10737 /**
10738 * <p>Indicate whether the horizontal scrollbar should be drawn or not. The
10739 * scrollbar is not drawn by default.</p>
10740 *
10741 * @return true if the horizontal scrollbar should be painted, false
10742 * otherwise
10743 *
10744 * @see #setHorizontalScrollBarEnabled(boolean)
10745 */
10746 public boolean isHorizontalScrollBarEnabled() {
10747 return (mViewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
10748 }
10749
10750 /**
10751 * <p>Define whether the horizontal scrollbar should be drawn or not. The
10752 * scrollbar is not drawn by default.</p>
10753 *
10754 * @param horizontalScrollBarEnabled true if the horizontal scrollbar should
10755 * be painted
10756 *
10757 * @see #isHorizontalScrollBarEnabled()
10758 */
10759 public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
10760 if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
10761 mViewFlags ^= SCROLLBARS_HORIZONTAL;
Romain Guy8f1344f52009-05-15 16:03:59 -070010762 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010763 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010764 }
10765 }
10766
10767 /**
10768 * <p>Indicate whether the vertical scrollbar should be drawn or not. The
10769 * scrollbar is not drawn by default.</p>
10770 *
10771 * @return true if the vertical scrollbar should be painted, false
10772 * otherwise
10773 *
10774 * @see #setVerticalScrollBarEnabled(boolean)
10775 */
10776 public boolean isVerticalScrollBarEnabled() {
10777 return (mViewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL;
10778 }
10779
10780 /**
10781 * <p>Define whether the vertical scrollbar should be drawn or not. The
10782 * scrollbar is not drawn by default.</p>
10783 *
10784 * @param verticalScrollBarEnabled true if the vertical scrollbar should
10785 * be painted
10786 *
10787 * @see #isVerticalScrollBarEnabled()
10788 */
10789 public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
10790 if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
10791 mViewFlags ^= SCROLLBARS_VERTICAL;
Romain Guy8f1344f52009-05-15 16:03:59 -070010792 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010793 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010794 }
10795 }
10796
Adam Powell20232d02010-12-08 21:08:53 -080010797 /**
10798 * @hide
10799 */
10800 protected void recomputePadding() {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070010801 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight, mUserPaddingBottom);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010802 }
Joe Malin32736f02011-01-19 16:14:20 -080010803
Mike Cleronfe81d382009-09-28 14:22:16 -070010804 /**
10805 * Define whether scrollbars will fade when the view is not scrolling.
Joe Malin32736f02011-01-19 16:14:20 -080010806 *
Mike Cleronfe81d382009-09-28 14:22:16 -070010807 * @param fadeScrollbars wheter to enable fading
Joe Malin32736f02011-01-19 16:14:20 -080010808 *
Philip Milne6c8ea062012-04-03 17:38:43 -070010809 * @attr ref android.R.styleable#View_fadeScrollbars
Mike Cleronfe81d382009-09-28 14:22:16 -070010810 */
10811 public void setScrollbarFadingEnabled(boolean fadeScrollbars) {
10812 initScrollCache();
10813 final ScrollabilityCache scrollabilityCache = mScrollCache;
10814 scrollabilityCache.fadeScrollBars = fadeScrollbars;
Mike Cleron52f0a642009-09-28 18:21:37 -070010815 if (fadeScrollbars) {
10816 scrollabilityCache.state = ScrollabilityCache.OFF;
10817 } else {
Mike Cleronfe81d382009-09-28 14:22:16 -070010818 scrollabilityCache.state = ScrollabilityCache.ON;
10819 }
10820 }
Joe Malin32736f02011-01-19 16:14:20 -080010821
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010822 /**
Joe Malin32736f02011-01-19 16:14:20 -080010823 *
Mike Cleron52f0a642009-09-28 18:21:37 -070010824 * Returns true if scrollbars will fade when this view is not scrolling
Joe Malin32736f02011-01-19 16:14:20 -080010825 *
Mike Cleron52f0a642009-09-28 18:21:37 -070010826 * @return true if scrollbar fading is enabled
Philip Milne6c8ea062012-04-03 17:38:43 -070010827 *
10828 * @attr ref android.R.styleable#View_fadeScrollbars
Mike Cleron52f0a642009-09-28 18:21:37 -070010829 */
10830 public boolean isScrollbarFadingEnabled() {
Joe Malin32736f02011-01-19 16:14:20 -080010831 return mScrollCache != null && mScrollCache.fadeScrollBars;
Mike Cleron52f0a642009-09-28 18:21:37 -070010832 }
Joe Malin32736f02011-01-19 16:14:20 -080010833
Mike Cleron52f0a642009-09-28 18:21:37 -070010834 /**
Philip Milne6c8ea062012-04-03 17:38:43 -070010835 *
10836 * Returns the delay before scrollbars fade.
10837 *
10838 * @return the delay before scrollbars fade
10839 *
10840 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10841 */
10842 public int getScrollBarDefaultDelayBeforeFade() {
10843 return mScrollCache == null ? ViewConfiguration.getScrollDefaultDelay() :
10844 mScrollCache.scrollBarDefaultDelayBeforeFade;
10845 }
10846
10847 /**
10848 * Define the delay before scrollbars fade.
10849 *
10850 * @param scrollBarDefaultDelayBeforeFade - the delay before scrollbars fade
10851 *
10852 * @attr ref android.R.styleable#View_scrollbarDefaultDelayBeforeFade
10853 */
10854 public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {
10855 getScrollCache().scrollBarDefaultDelayBeforeFade = scrollBarDefaultDelayBeforeFade;
10856 }
10857
10858 /**
10859 *
10860 * Returns the scrollbar fade duration.
10861 *
10862 * @return the scrollbar fade duration
10863 *
10864 * @attr ref android.R.styleable#View_scrollbarFadeDuration
10865 */
10866 public int getScrollBarFadeDuration() {
10867 return mScrollCache == null ? ViewConfiguration.getScrollBarFadeDuration() :
10868 mScrollCache.scrollBarFadeDuration;
10869 }
10870
10871 /**
10872 * Define the scrollbar fade duration.
10873 *
10874 * @param scrollBarFadeDuration - the scrollbar fade duration
10875 *
10876 * @attr ref android.R.styleable#View_scrollbarFadeDuration
10877 */
10878 public void setScrollBarFadeDuration(int scrollBarFadeDuration) {
10879 getScrollCache().scrollBarFadeDuration = scrollBarFadeDuration;
10880 }
10881
10882 /**
10883 *
10884 * Returns the scrollbar size.
10885 *
10886 * @return the scrollbar size
10887 *
10888 * @attr ref android.R.styleable#View_scrollbarSize
10889 */
10890 public int getScrollBarSize() {
Romain Guyeb378892012-04-12 11:33:14 -070010891 return mScrollCache == null ? ViewConfiguration.get(mContext).getScaledScrollBarSize() :
Philip Milne6c8ea062012-04-03 17:38:43 -070010892 mScrollCache.scrollBarSize;
10893 }
10894
10895 /**
10896 * Define the scrollbar size.
10897 *
10898 * @param scrollBarSize - the scrollbar size
10899 *
10900 * @attr ref android.R.styleable#View_scrollbarSize
10901 */
10902 public void setScrollBarSize(int scrollBarSize) {
10903 getScrollCache().scrollBarSize = scrollBarSize;
10904 }
10905
10906 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010907 * <p>Specify the style of the scrollbars. The scrollbars can be overlaid or
10908 * inset. When inset, they add to the padding of the view. And the scrollbars
10909 * can be drawn inside the padding area or on the edge of the view. For example,
10910 * if a view has a background drawable and you want to draw the scrollbars
10911 * inside the padding specified by the drawable, you can use
10912 * SCROLLBARS_INSIDE_OVERLAY or SCROLLBARS_INSIDE_INSET. If you want them to
10913 * appear at the edge of the view, ignoring the padding, then you can use
10914 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.</p>
10915 * @param style the style of the scrollbars. Should be one of
10916 * SCROLLBARS_INSIDE_OVERLAY, SCROLLBARS_INSIDE_INSET,
10917 * SCROLLBARS_OUTSIDE_OVERLAY or SCROLLBARS_OUTSIDE_INSET.
10918 * @see #SCROLLBARS_INSIDE_OVERLAY
10919 * @see #SCROLLBARS_INSIDE_INSET
10920 * @see #SCROLLBARS_OUTSIDE_OVERLAY
10921 * @see #SCROLLBARS_OUTSIDE_INSET
Philip Milne6c8ea062012-04-03 17:38:43 -070010922 *
10923 * @attr ref android.R.styleable#View_scrollbarStyle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010924 */
10925 public void setScrollBarStyle(int style) {
10926 if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
10927 mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
Romain Guy8f1344f52009-05-15 16:03:59 -070010928 computeOpaqueFlags();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070010929 resolvePadding();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010930 }
10931 }
10932
10933 /**
10934 * <p>Returns the current scrollbar style.</p>
10935 * @return the current scrollbar style
10936 * @see #SCROLLBARS_INSIDE_OVERLAY
10937 * @see #SCROLLBARS_INSIDE_INSET
10938 * @see #SCROLLBARS_OUTSIDE_OVERLAY
10939 * @see #SCROLLBARS_OUTSIDE_INSET
Philip Milne6c8ea062012-04-03 17:38:43 -070010940 *
10941 * @attr ref android.R.styleable#View_scrollbarStyle
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010942 */
Jeff Sharkey010d7e52011-08-08 21:05:02 -070010943 @ViewDebug.ExportedProperty(mapping = {
10944 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_OVERLAY, to = "INSIDE_OVERLAY"),
10945 @ViewDebug.IntToString(from = SCROLLBARS_INSIDE_INSET, to = "INSIDE_INSET"),
10946 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_OVERLAY, to = "OUTSIDE_OVERLAY"),
10947 @ViewDebug.IntToString(from = SCROLLBARS_OUTSIDE_INSET, to = "OUTSIDE_INSET")
10948 })
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080010949 public int getScrollBarStyle() {
10950 return mViewFlags & SCROLLBARS_STYLE_MASK;
10951 }
10952
10953 /**
10954 * <p>Compute the horizontal range that the horizontal scrollbar
10955 * represents.</p>
10956 *
10957 * <p>The range is expressed in arbitrary units that must be the same as the
10958 * units used by {@link #computeHorizontalScrollExtent()} and
10959 * {@link #computeHorizontalScrollOffset()}.</p>
10960 *
10961 * <p>The default range is the drawing width of this view.</p>
10962 *
10963 * @return the total horizontal range represented by the horizontal
10964 * scrollbar
10965 *
10966 * @see #computeHorizontalScrollExtent()
10967 * @see #computeHorizontalScrollOffset()
10968 * @see android.widget.ScrollBarDrawable
10969 */
10970 protected int computeHorizontalScrollRange() {
10971 return getWidth();
10972 }
10973
10974 /**
10975 * <p>Compute the horizontal offset of the horizontal scrollbar's thumb
10976 * within the horizontal range. This value is used to compute the position
10977 * of the thumb within the scrollbar's track.</p>
10978 *
10979 * <p>The range is expressed in arbitrary units that must be the same as the
10980 * units used by {@link #computeHorizontalScrollRange()} and
10981 * {@link #computeHorizontalScrollExtent()}.</p>
10982 *
10983 * <p>The default offset is the scroll offset of this view.</p>
10984 *
10985 * @return the horizontal offset of the scrollbar's thumb
10986 *
10987 * @see #computeHorizontalScrollRange()
10988 * @see #computeHorizontalScrollExtent()
10989 * @see android.widget.ScrollBarDrawable
10990 */
10991 protected int computeHorizontalScrollOffset() {
10992 return mScrollX;
10993 }
10994
10995 /**
10996 * <p>Compute the horizontal extent of the horizontal scrollbar's thumb
10997 * within the horizontal range. This value is used to compute the length
10998 * of the thumb within the scrollbar's track.</p>
10999 *
11000 * <p>The range is expressed in arbitrary units that must be the same as the
11001 * units used by {@link #computeHorizontalScrollRange()} and
11002 * {@link #computeHorizontalScrollOffset()}.</p>
11003 *
11004 * <p>The default extent is the drawing width of this view.</p>
11005 *
11006 * @return the horizontal extent of the scrollbar's thumb
11007 *
11008 * @see #computeHorizontalScrollRange()
11009 * @see #computeHorizontalScrollOffset()
11010 * @see android.widget.ScrollBarDrawable
11011 */
11012 protected int computeHorizontalScrollExtent() {
11013 return getWidth();
11014 }
11015
11016 /**
11017 * <p>Compute the vertical range that the vertical scrollbar represents.</p>
11018 *
11019 * <p>The range is expressed in arbitrary units that must be the same as the
11020 * units used by {@link #computeVerticalScrollExtent()} and
11021 * {@link #computeVerticalScrollOffset()}.</p>
11022 *
11023 * @return the total vertical range represented by the vertical scrollbar
11024 *
11025 * <p>The default range is the drawing height of this view.</p>
11026 *
11027 * @see #computeVerticalScrollExtent()
11028 * @see #computeVerticalScrollOffset()
11029 * @see android.widget.ScrollBarDrawable
11030 */
11031 protected int computeVerticalScrollRange() {
11032 return getHeight();
11033 }
11034
11035 /**
11036 * <p>Compute the vertical offset of the vertical scrollbar's thumb
11037 * within the horizontal range. This value is used to compute the position
11038 * of the thumb within the scrollbar's track.</p>
11039 *
11040 * <p>The range is expressed in arbitrary units that must be the same as the
11041 * units used by {@link #computeVerticalScrollRange()} and
11042 * {@link #computeVerticalScrollExtent()}.</p>
11043 *
11044 * <p>The default offset is the scroll offset of this view.</p>
11045 *
11046 * @return the vertical offset of the scrollbar's thumb
11047 *
11048 * @see #computeVerticalScrollRange()
11049 * @see #computeVerticalScrollExtent()
11050 * @see android.widget.ScrollBarDrawable
11051 */
11052 protected int computeVerticalScrollOffset() {
11053 return mScrollY;
11054 }
11055
11056 /**
11057 * <p>Compute the vertical extent of the horizontal scrollbar's thumb
11058 * within the vertical range. This value is used to compute the length
11059 * of the thumb within the scrollbar's track.</p>
11060 *
11061 * <p>The range is expressed in arbitrary units that must be the same as the
Gilles Debunne52964242010-02-24 11:05:19 -080011062 * units used by {@link #computeVerticalScrollRange()} and
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011063 * {@link #computeVerticalScrollOffset()}.</p>
11064 *
11065 * <p>The default extent is the drawing height of this view.</p>
11066 *
11067 * @return the vertical extent of the scrollbar's thumb
11068 *
11069 * @see #computeVerticalScrollRange()
11070 * @see #computeVerticalScrollOffset()
11071 * @see android.widget.ScrollBarDrawable
11072 */
11073 protected int computeVerticalScrollExtent() {
11074 return getHeight();
11075 }
11076
11077 /**
Adam Powell69159442011-06-13 17:53:06 -070011078 * Check if this view can be scrolled horizontally in a certain direction.
11079 *
11080 * @param direction Negative to check scrolling left, positive to check scrolling right.
11081 * @return true if this view can be scrolled in the specified direction, false otherwise.
11082 */
11083 public boolean canScrollHorizontally(int direction) {
11084 final int offset = computeHorizontalScrollOffset();
11085 final int range = computeHorizontalScrollRange() - computeHorizontalScrollExtent();
11086 if (range == 0) return false;
11087 if (direction < 0) {
11088 return offset > 0;
11089 } else {
11090 return offset < range - 1;
11091 }
11092 }
11093
11094 /**
11095 * Check if this view can be scrolled vertically in a certain direction.
11096 *
11097 * @param direction Negative to check scrolling up, positive to check scrolling down.
11098 * @return true if this view can be scrolled in the specified direction, false otherwise.
11099 */
11100 public boolean canScrollVertically(int direction) {
11101 final int offset = computeVerticalScrollOffset();
11102 final int range = computeVerticalScrollRange() - computeVerticalScrollExtent();
11103 if (range == 0) return false;
11104 if (direction < 0) {
11105 return offset > 0;
11106 } else {
11107 return offset < range - 1;
11108 }
11109 }
11110
11111 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011112 * <p>Request the drawing of the horizontal and the vertical scrollbar. The
11113 * scrollbars are painted only if they have been awakened first.</p>
11114 *
11115 * @param canvas the canvas on which to draw the scrollbars
Joe Malin32736f02011-01-19 16:14:20 -080011116 *
Mike Cleronf116bf82009-09-27 19:14:12 -070011117 * @see #awakenScrollBars(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011118 */
Romain Guy1d5b3a62009-11-05 18:44:12 -080011119 protected final void onDrawScrollBars(Canvas canvas) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011120 // scrollbars are drawn only when the animation is running
11121 final ScrollabilityCache cache = mScrollCache;
11122 if (cache != null) {
Joe Malin32736f02011-01-19 16:14:20 -080011123
Mike Cleronf116bf82009-09-27 19:14:12 -070011124 int state = cache.state;
Joe Malin32736f02011-01-19 16:14:20 -080011125
Mike Cleronf116bf82009-09-27 19:14:12 -070011126 if (state == ScrollabilityCache.OFF) {
11127 return;
11128 }
Joe Malin32736f02011-01-19 16:14:20 -080011129
Mike Cleronf116bf82009-09-27 19:14:12 -070011130 boolean invalidate = false;
Joe Malin32736f02011-01-19 16:14:20 -080011131
Mike Cleronf116bf82009-09-27 19:14:12 -070011132 if (state == ScrollabilityCache.FADING) {
11133 // We're fading -- get our fade interpolation
11134 if (cache.interpolatorValues == null) {
11135 cache.interpolatorValues = new float[1];
11136 }
Joe Malin32736f02011-01-19 16:14:20 -080011137
Mike Cleronf116bf82009-09-27 19:14:12 -070011138 float[] values = cache.interpolatorValues;
Joe Malin32736f02011-01-19 16:14:20 -080011139
Mike Cleronf116bf82009-09-27 19:14:12 -070011140 // Stops the animation if we're done
11141 if (cache.scrollBarInterpolator.timeToValues(values) ==
11142 Interpolator.Result.FREEZE_END) {
11143 cache.state = ScrollabilityCache.OFF;
11144 } else {
11145 cache.scrollBar.setAlpha(Math.round(values[0]));
11146 }
Joe Malin32736f02011-01-19 16:14:20 -080011147
11148 // This will make the scroll bars inval themselves after
Mike Cleronf116bf82009-09-27 19:14:12 -070011149 // drawing. We only want this when we're fading so that
11150 // we prevent excessive redraws
11151 invalidate = true;
11152 } else {
11153 // We're just on -- but we may have been fading before so
11154 // reset alpha
11155 cache.scrollBar.setAlpha(255);
11156 }
11157
Joe Malin32736f02011-01-19 16:14:20 -080011158
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011159 final int viewFlags = mViewFlags;
11160
11161 final boolean drawHorizontalScrollBar =
11162 (viewFlags & SCROLLBARS_HORIZONTAL) == SCROLLBARS_HORIZONTAL;
11163 final boolean drawVerticalScrollBar =
11164 (viewFlags & SCROLLBARS_VERTICAL) == SCROLLBARS_VERTICAL
11165 && !isVerticalScrollBarHidden();
11166
11167 if (drawVerticalScrollBar || drawHorizontalScrollBar) {
11168 final int width = mRight - mLeft;
11169 final int height = mBottom - mTop;
11170
11171 final ScrollBarDrawable scrollBar = cache.scrollBar;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011172
Mike Reede8853fc2009-09-04 14:01:48 -040011173 final int scrollX = mScrollX;
11174 final int scrollY = mScrollY;
11175 final int inside = (viewFlags & SCROLLBARS_OUTSIDE_MASK) == 0 ? ~0 : 0;
11176
Mike Cleronf116bf82009-09-27 19:14:12 -070011177 int left, top, right, bottom;
Joe Malin32736f02011-01-19 16:14:20 -080011178
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011179 if (drawHorizontalScrollBar) {
Adam Powell3ba67742011-01-27 14:16:55 -080011180 int size = scrollBar.getSize(false);
11181 if (size <= 0) {
11182 size = cache.scrollBarSize;
11183 }
11184
Mike Cleronf116bf82009-09-27 19:14:12 -070011185 scrollBar.setParameters(computeHorizontalScrollRange(),
Mike Reede8853fc2009-09-04 14:01:48 -040011186 computeHorizontalScrollOffset(),
11187 computeHorizontalScrollExtent(), false);
Mike Reede8853fc2009-09-04 14:01:48 -040011188 final int verticalScrollBarGap = drawVerticalScrollBar ?
Mike Cleronf116bf82009-09-27 19:14:12 -070011189 getVerticalScrollbarWidth() : 0;
Joe Malin32736f02011-01-19 16:14:20 -080011190 top = scrollY + height - size - (mUserPaddingBottom & inside);
Mike Cleronf116bf82009-09-27 19:14:12 -070011191 left = scrollX + (mPaddingLeft & inside);
11192 right = scrollX + width - (mUserPaddingRight & inside) - verticalScrollBarGap;
11193 bottom = top + size;
11194 onDrawHorizontalScrollBar(canvas, scrollBar, left, top, right, bottom);
11195 if (invalidate) {
11196 invalidate(left, top, right, bottom);
11197 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011198 }
11199
11200 if (drawVerticalScrollBar) {
Adam Powell3ba67742011-01-27 14:16:55 -080011201 int size = scrollBar.getSize(true);
11202 if (size <= 0) {
11203 size = cache.scrollBarSize;
11204 }
11205
Mike Reede8853fc2009-09-04 14:01:48 -040011206 scrollBar.setParameters(computeVerticalScrollRange(),
11207 computeVerticalScrollOffset(),
11208 computeVerticalScrollExtent(), true);
Fabrice Di Meglioc91b6ca2012-06-22 14:51:15 -070011209 int verticalScrollbarPosition = mVerticalScrollbarPosition;
11210 if (verticalScrollbarPosition == SCROLLBAR_POSITION_DEFAULT) {
11211 verticalScrollbarPosition = isLayoutRtl() ?
11212 SCROLLBAR_POSITION_LEFT : SCROLLBAR_POSITION_RIGHT;
11213 }
11214 switch (verticalScrollbarPosition) {
Adam Powell20232d02010-12-08 21:08:53 -080011215 default:
Adam Powell20232d02010-12-08 21:08:53 -080011216 case SCROLLBAR_POSITION_RIGHT:
11217 left = scrollX + width - size - (mUserPaddingRight & inside);
11218 break;
11219 case SCROLLBAR_POSITION_LEFT:
11220 left = scrollX + (mUserPaddingLeft & inside);
11221 break;
11222 }
Mike Cleronf116bf82009-09-27 19:14:12 -070011223 top = scrollY + (mPaddingTop & inside);
11224 right = left + size;
11225 bottom = scrollY + height - (mUserPaddingBottom & inside);
11226 onDrawVerticalScrollBar(canvas, scrollBar, left, top, right, bottom);
11227 if (invalidate) {
11228 invalidate(left, top, right, bottom);
11229 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011230 }
11231 }
11232 }
11233 }
Romain Guy8506ab42009-06-11 17:35:47 -070011234
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011235 /**
Romain Guy8506ab42009-06-11 17:35:47 -070011236 * 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 -080011237 * FastScroller is visible.
11238 * @return whether to temporarily hide the vertical scrollbar
11239 * @hide
11240 */
11241 protected boolean isVerticalScrollBarHidden() {
11242 return false;
11243 }
11244
11245 /**
11246 * <p>Draw the horizontal scrollbar if
11247 * {@link #isHorizontalScrollBarEnabled()} returns true.</p>
11248 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011249 * @param canvas the canvas on which to draw the scrollbar
11250 * @param scrollBar the scrollbar's drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011251 *
11252 * @see #isHorizontalScrollBarEnabled()
11253 * @see #computeHorizontalScrollRange()
11254 * @see #computeHorizontalScrollExtent()
11255 * @see #computeHorizontalScrollOffset()
11256 * @see android.widget.ScrollBarDrawable
Mike Cleronf116bf82009-09-27 19:14:12 -070011257 * @hide
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011258 */
Romain Guy8fb95422010-08-17 18:38:51 -070011259 protected void onDrawHorizontalScrollBar(Canvas canvas, Drawable scrollBar,
11260 int l, int t, int r, int b) {
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011261 scrollBar.setBounds(l, t, r, b);
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011262 scrollBar.draw(canvas);
11263 }
Mike Reede8853fc2009-09-04 14:01:48 -040011264
Mike Reed4d6fe5f2009-09-03 13:29:05 -040011265 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011266 * <p>Draw the vertical scrollbar if {@link #isVerticalScrollBarEnabled()}
11267 * returns true.</p>
11268 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011269 * @param canvas the canvas on which to draw the scrollbar
11270 * @param scrollBar the scrollbar's drawable
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011271 *
11272 * @see #isVerticalScrollBarEnabled()
11273 * @see #computeVerticalScrollRange()
11274 * @see #computeVerticalScrollExtent()
11275 * @see #computeVerticalScrollOffset()
11276 * @see android.widget.ScrollBarDrawable
Mike Reede8853fc2009-09-04 14:01:48 -040011277 * @hide
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011278 */
Romain Guy8fb95422010-08-17 18:38:51 -070011279 protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar,
11280 int l, int t, int r, int b) {
Mike Reede8853fc2009-09-04 14:01:48 -040011281 scrollBar.setBounds(l, t, r, b);
11282 scrollBar.draw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011283 }
11284
11285 /**
11286 * Implement this to do your drawing.
11287 *
11288 * @param canvas the canvas on which the background will be drawn
11289 */
11290 protected void onDraw(Canvas canvas) {
11291 }
11292
11293 /*
11294 * Caller is responsible for calling requestLayout if necessary.
11295 * (This allows addViewInLayout to not request a new layout.)
11296 */
11297 void assignParent(ViewParent parent) {
11298 if (mParent == null) {
11299 mParent = parent;
11300 } else if (parent == null) {
11301 mParent = null;
11302 } else {
11303 throw new RuntimeException("view " + this + " being added, but"
11304 + " it already has a parent");
11305 }
11306 }
11307
11308 /**
11309 * This is called when the view is attached to a window. At this point it
11310 * has a Surface and will start drawing. Note that this function is
Romain Guy5c22a8c2011-05-13 11:48:45 -070011311 * guaranteed to be called before {@link #onDraw(android.graphics.Canvas)},
11312 * however it may be called any time before the first onDraw -- including
11313 * before or after {@link #onMeasure(int, int)}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011314 *
11315 * @see #onDetachedFromWindow()
11316 */
11317 protected void onAttachedToWindow() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011318 if ((mPrivateFlags & PFLAG_REQUEST_TRANSPARENT_REGIONS) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011319 mParent.requestTransparentRegion(this);
11320 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011321
Dianne Hackborn4702a852012-08-17 15:18:29 -070011322 if ((mPrivateFlags & PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH) != 0) {
Adam Powell8568c3a2010-04-19 14:26:11 -070011323 initialAwakenScrollBars();
Dianne Hackborn4702a852012-08-17 15:18:29 -070011324 mPrivateFlags &= ~PFLAG_AWAKEN_SCROLL_BARS_ON_ATTACH;
Adam Powell8568c3a2010-04-19 14:26:11 -070011325 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011326
Chet Haasea9b61ac2010-12-20 07:40:25 -080011327 jumpDrawablesToCurrentState();
Romain Guy2a0f2282012-05-08 14:43:12 -070011328
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011329 resolveRtlProperties();
Romain Guy2a0f2282012-05-08 14:43:12 -070011330
Svetoslav Ganov42138042012-03-20 11:51:39 -070011331 clearAccessibilityFocus();
Amith Yamasani4503c8d2011-06-17 12:36:14 -070011332 if (isFocused()) {
11333 InputMethodManager imm = InputMethodManager.peekInstance();
11334 imm.focusIn(this);
11335 }
Romain Guy2a0f2282012-05-08 14:43:12 -070011336
11337 if (mAttachInfo != null && mDisplayList != null) {
11338 mAttachInfo.mViewRootImpl.dequeueDisplayList(mDisplayList);
11339 }
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011340 }
Cibu Johny86666632010-02-22 13:01:02 -080011341
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011342 void resolveRtlProperties() {
11343 // Order is important here: LayoutDirection MUST be resolved first...
11344 resolveLayoutDirection();
11345 // ... then we can resolve the others properties depending on the resolved LayoutDirection.
11346 resolvePadding();
11347 resolveLayoutParams();
11348 resolveTextDirection();
11349 resolveTextAlignment();
11350 }
11351
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011352 /**
Romain Guybb9908b2012-03-08 11:14:07 -080011353 * @see #onScreenStateChanged(int)
11354 */
11355 void dispatchScreenStateChanged(int screenState) {
11356 onScreenStateChanged(screenState);
11357 }
11358
11359 /**
11360 * This method is called whenever the state of the screen this view is
11361 * attached to changes. A state change will usually occurs when the screen
11362 * turns on or off (whether it happens automatically or the user does it
11363 * manually.)
11364 *
11365 * @param screenState The new state of the screen. Can be either
11366 * {@link #SCREEN_STATE_ON} or {@link #SCREEN_STATE_OFF}
11367 */
11368 public void onScreenStateChanged(int screenState) {
11369 }
11370
11371 /**
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011372 * Return true if the application tag in the AndroidManifest has set "supportRtl" to true
11373 */
11374 private boolean hasRtlSupport() {
11375 return mContext.getApplicationInfo().hasRtlSupport();
11376 }
11377
11378 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011379 * Resolve and cache the layout direction. LTR is set initially. This is implicitly supposing
11380 * that the parent directionality can and will be resolved before its children.
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011381 * Will call {@link View#onResolvedLayoutDirectionChanged} when resolution is done.
Fabrice Di Meglio4f5aa912011-05-31 15:20:50 -070011382 */
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011383 public void resolveLayoutDirection() {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011384 // Clear any previous layout direction resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070011385 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011386
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011387 if (hasRtlSupport()) {
11388 // Set resolved depending on layout direction
11389 switch (getLayoutDirection()) {
11390 case LAYOUT_DIRECTION_INHERIT:
Fabrice Di Megliob93911f2012-06-26 19:43:15 -070011391 // We cannot resolve yet. LTR is by default and let the resolution happen again
11392 // later to get the correct resolved value
11393 if (!canResolveLayoutDirection()) return;
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011394
Fabrice Di Megliob93911f2012-06-26 19:43:15 -070011395 ViewGroup viewGroup = ((ViewGroup) mParent);
11396
11397 // We cannot resolve yet on the parent too. LTR is by default and let the
11398 // resolution happen again later
11399 if (!viewGroup.canResolveLayoutDirection()) return;
11400
11401 if (viewGroup.getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011402 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011403 }
11404 break;
11405 case LAYOUT_DIRECTION_RTL:
Dianne Hackborn4702a852012-08-17 15:18:29 -070011406 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011407 break;
11408 case LAYOUT_DIRECTION_LOCALE:
11409 if(isLayoutDirectionRtl(Locale.getDefault())) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011410 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL;
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011411 }
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011412 break;
11413 default:
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011414 // Nothing to do, LTR by default
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070011415 }
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011416 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011417
11418 // Set to resolved
Dianne Hackborn4702a852012-08-17 15:18:29 -070011419 mPrivateFlags2 |= PFLAG2_LAYOUT_DIRECTION_RESOLVED;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011420 onResolvedLayoutDirectionChanged();
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011421 }
11422
Fabrice Di Meglioaff599b2011-07-20 19:05:01 -070011423 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011424 * Called when layout direction has been resolved.
11425 *
11426 * The default implementation does nothing.
11427 */
11428 public void onResolvedLayoutDirectionChanged() {
11429 }
11430
11431 /**
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011432 * Return if padding has been resolved
11433 */
11434 boolean isPaddingResolved() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011435 return (mPrivateFlags2 & PFLAG2_PADDING_RESOLVED) != 0;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011436 }
11437
11438 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011439 * Resolve padding depending on layout direction.
Fabrice Di Meglioaff599b2011-07-20 19:05:01 -070011440 */
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011441 public void resolvePadding() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070011442 final int targetSdkVersion = getContext().getApplicationInfo().targetSdkVersion;
11443 if (targetSdkVersion < JELLY_BEAN_MR1 || !hasRtlSupport()) {
11444 // Pre Jelly Bean MR1 case (compatibility mode) OR no RTL support case:
11445 // left / right padding are used if defined. If they are not defined and start / end
11446 // padding are defined (e.g. in Frameworks resources), then we use start / end and
11447 // resolve them as left / right (layout direction is not taken into account).
11448 if (!mUserPaddingLeftDefined && mUserPaddingStart != UNDEFINED_PADDING) {
11449 mUserPaddingLeft = mUserPaddingStart;
11450 }
11451 if (!mUserPaddingRightDefined && mUserPaddingEnd != UNDEFINED_PADDING) {
11452 mUserPaddingRight = mUserPaddingEnd;
11453 }
11454
11455 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11456
11457 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11458 mUserPaddingBottom);
11459 } else {
11460 // Post Jelly Bean MR1 case: we need to take the resolved layout direction into account.
11461 // If start / end padding are defined, they will be resolved (hence overriding) to
11462 // left / right or right / left depending on the resolved layout direction.
11463 // If start / end padding are not defined, use the left / right ones.
11464 int resolvedLayoutDirection = getResolvedLayoutDirection();
11465 switch (resolvedLayoutDirection) {
11466 case LAYOUT_DIRECTION_RTL:
11467 if (mUserPaddingStart != UNDEFINED_PADDING) {
11468 mUserPaddingRight = mUserPaddingStart;
11469 }
11470 if (mUserPaddingEnd != UNDEFINED_PADDING) {
11471 mUserPaddingLeft = mUserPaddingEnd;
11472 }
11473 break;
11474 case LAYOUT_DIRECTION_LTR:
11475 default:
11476 if (mUserPaddingStart != UNDEFINED_PADDING) {
11477 mUserPaddingLeft = mUserPaddingStart;
11478 }
11479 if (mUserPaddingEnd != UNDEFINED_PADDING) {
11480 mUserPaddingRight = mUserPaddingEnd;
11481 }
11482 }
11483
11484 mUserPaddingBottom = (mUserPaddingBottom >= 0) ? mUserPaddingBottom : mPaddingBottom;
11485
11486 internalSetPadding(mUserPaddingLeft, mPaddingTop, mUserPaddingRight,
11487 mUserPaddingBottom);
11488 onPaddingChanged(resolvedLayoutDirection);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011489 }
11490
Dianne Hackborn4702a852012-08-17 15:18:29 -070011491 mPrivateFlags2 |= PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011492 }
11493
11494 /**
11495 * Resolve padding depending on the layout direction. Subclasses that care about
11496 * padding resolution should override this method. The default implementation does
11497 * nothing.
11498 *
11499 * @param layoutDirection the direction of the layout
11500 *
Fabrice Di Meglioe8dc07d2012-03-09 17:10:19 -080011501 * @see {@link #LAYOUT_DIRECTION_LTR}
11502 * @see {@link #LAYOUT_DIRECTION_RTL}
Fabrice Di Meglioccb15622012-02-15 15:52:19 -080011503 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011504 public void onPaddingChanged(int layoutDirection) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011505 }
11506
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011507 /**
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011508 * Check if layout direction resolution can be done.
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011509 *
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011510 * @return true if layout direction resolution can be done otherwise return false.
Fabrice Di Meglio2273b1e2011-09-07 15:17:40 -070011511 */
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011512 public boolean canResolveLayoutDirection() {
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011513 switch (getLayoutDirection()) {
11514 case LAYOUT_DIRECTION_INHERIT:
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070011515 return (mParent != null) && (mParent instanceof ViewGroup);
Fabrice Di Megliofe7e40d2011-07-13 12:47:36 -070011516 default:
11517 return true;
11518 }
11519 }
11520
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011521 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011522 * Reset the resolved layout direction. Will call {@link View#onResolvedLayoutDirectionReset}
11523 * when reset is done.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070011524 */
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011525 public void resetResolvedLayoutDirection() {
Fabrice Di Meglioedc1e592012-03-15 17:28:47 -070011526 // Reset the current resolved bits
Dianne Hackborn4702a852012-08-17 15:18:29 -070011527 mPrivateFlags2 &= ~PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011528 onResolvedLayoutDirectionReset();
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080011529 // Reset also the text direction
11530 resetResolvedTextDirection();
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011531 }
11532
11533 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080011534 * Called during reset of resolved layout direction.
11535 *
11536 * Subclasses need to override this method to clear cached information that depends on the
11537 * resolved layout direction, or to inform child views that inherit their layout direction.
11538 *
11539 * The default implementation does nothing.
11540 */
11541 public void onResolvedLayoutDirectionReset() {
11542 }
11543
11544 /**
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011545 * Check if a Locale uses an RTL script.
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011546 *
11547 * @param locale Locale to check
Fabrice Di Meglio98aec1c2012-02-13 16:54:05 -080011548 * @return true if the Locale uses an RTL script.
Fabrice Di Meglio26e432d2011-06-10 14:19:18 -070011549 */
Fabrice Di Meglio22268862011-06-27 18:13:18 -070011550 protected static boolean isLayoutDirectionRtl(Locale locale) {
Fabrice Di Meglio3fb824b2012-02-28 17:58:31 -080011551 return (LAYOUT_DIRECTION_RTL == LocaleUtil.getLayoutDirectionFromLocale(locale));
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011552 }
11553
11554 /**
11555 * This is called when the view is detached from a window. At this point it
11556 * no longer has a surface for drawing.
11557 *
11558 * @see #onAttachedToWindow()
11559 */
11560 protected void onDetachedFromWindow() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011561 mPrivateFlags &= ~PFLAG_CANCEL_NEXT_UP_EVENT;
Romain Guy6c319ca2011-01-11 14:29:25 -080011562
Romain Guya440b002010-02-24 15:57:54 -080011563 removeUnsetPressCallback();
Maryam Garrett1549dd12009-12-15 16:06:36 -050011564 removeLongPressCallback();
Adam Powell3cb8b632011-01-21 15:34:14 -080011565 removePerformClickCallback();
Svetoslav Ganova0156172011-06-26 17:55:44 -070011566 removeSendViewScrolledAccessibilityEventCallback();
Romain Guy6c319ca2011-01-11 14:29:25 -080011567
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011568 destroyDrawingCache();
Romain Guy6c319ca2011-01-11 14:29:25 -080011569
Romain Guya998dff2012-03-23 18:58:36 -070011570 destroyLayer(false);
Romain Guy8dd5b1e2011-01-14 17:28:51 -080011571
11572 if (mAttachInfo != null) {
Romain Guy51e4d4d2012-03-15 18:30:47 -070011573 if (mDisplayList != null) {
Romain Guy2a0f2282012-05-08 14:43:12 -070011574 mAttachInfo.mViewRootImpl.enqueueDisplayList(mDisplayList);
Romain Guy51e4d4d2012-03-15 18:30:47 -070011575 }
Jeff Browna175a5b2012-02-15 19:18:31 -080011576 mAttachInfo.mViewRootImpl.cancelInvalidate(this);
Romain Guy51e4d4d2012-03-15 18:30:47 -070011577 } else {
Romain Guy38c2ece2012-05-24 14:20:56 -070011578 // Should never happen
11579 clearDisplayList();
Romain Guy8dd5b1e2011-01-14 17:28:51 -080011580 }
11581
Patrick Dubroyec84c3a2011-01-13 17:55:37 -080011582 mCurrentAnimation = null;
Fabrice Di Meglio7f86c802011-07-01 15:09:24 -070011583
11584 resetResolvedLayoutDirection();
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070011585 resetResolvedTextAlignment();
Svetoslav Ganov42138042012-03-20 11:51:39 -070011586 resetAccessibilityStateChanged();
Dianne Hackborn4702a852012-08-17 15:18:29 -070011587 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011588 }
11589
11590 /**
11591 * @return The number of times this view has been attached to a window
11592 */
11593 protected int getWindowAttachCount() {
11594 return mWindowAttachCount;
11595 }
11596
11597 /**
11598 * Retrieve a unique token identifying the window this view is attached to.
11599 * @return Return the window's token for use in
11600 * {@link WindowManager.LayoutParams#token WindowManager.LayoutParams.token}.
11601 */
11602 public IBinder getWindowToken() {
11603 return mAttachInfo != null ? mAttachInfo.mWindowToken : null;
11604 }
11605
11606 /**
11607 * Retrieve a unique token identifying the top-level "real" window of
11608 * the window that this view is attached to. That is, this is like
11609 * {@link #getWindowToken}, except if the window this view in is a panel
11610 * window (attached to another containing window), then the token of
11611 * the containing window is returned instead.
11612 *
11613 * @return Returns the associated window token, either
11614 * {@link #getWindowToken()} or the containing window's token.
11615 */
11616 public IBinder getApplicationWindowToken() {
11617 AttachInfo ai = mAttachInfo;
11618 if (ai != null) {
11619 IBinder appWindowToken = ai.mPanelParentWindowToken;
11620 if (appWindowToken == null) {
11621 appWindowToken = ai.mWindowToken;
11622 }
11623 return appWindowToken;
11624 }
11625 return null;
11626 }
11627
11628 /**
Jeff Brown98365d72012-08-19 20:30:52 -070011629 * Gets the logical display to which the view's window has been attached.
11630 *
11631 * @return The logical display, or null if the view is not currently attached to a window.
11632 */
11633 public Display getDisplay() {
11634 return mAttachInfo != null ? mAttachInfo.mDisplay : null;
11635 }
11636
11637 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011638 * Retrieve private session object this view hierarchy is using to
11639 * communicate with the window manager.
11640 * @return the session object to communicate with the window manager
11641 */
11642 /*package*/ IWindowSession getWindowSession() {
11643 return mAttachInfo != null ? mAttachInfo.mSession : null;
11644 }
11645
11646 /**
11647 * @param info the {@link android.view.View.AttachInfo} to associated with
11648 * this view
11649 */
11650 void dispatchAttachedToWindow(AttachInfo info, int visibility) {
11651 //System.out.println("Attached! " + this);
11652 mAttachInfo = info;
11653 mWindowAttachCount++;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080011654 // We will need to evaluate the drawable state at least once.
Dianne Hackborn4702a852012-08-17 15:18:29 -070011655 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011656 if (mFloatingTreeObserver != null) {
11657 info.mTreeObserver.merge(mFloatingTreeObserver);
11658 mFloatingTreeObserver = null;
11659 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070011660 if ((mPrivateFlags&PFLAG_SCROLL_CONTAINER) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011661 mAttachInfo.mScrollContainers.add(this);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011662 mPrivateFlags |= PFLAG_SCROLL_CONTAINER_ADDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011663 }
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070011664 performCollectViewAttributes(mAttachInfo, visibility);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011665 onAttachedToWindow();
Adam Powell4afd62b2011-02-18 15:02:18 -080011666
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011667 ListenerInfo li = mListenerInfo;
Adam Powell4afd62b2011-02-18 15:02:18 -080011668 final CopyOnWriteArrayList<OnAttachStateChangeListener> listeners =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070011669 li != null ? li.mOnAttachStateChangeListeners : null;
Adam Powell4afd62b2011-02-18 15:02:18 -080011670 if (listeners != null && listeners.size() > 0) {
11671 // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
11672 // perform the dispatching. The iterator is a safe guard against listeners that
11673 // could mutate the list by calling the various add/remove methods. This prevents
11674 // the array from being modified while we iterate it.
11675 for (OnAttachStateChangeListener listener : listeners) {
11676 listener.onViewAttachedToWindow(this);
11677 }
11678 }
11679
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011680 int vis = info.mWindowVisibility;
11681 if (vis != GONE) {
11682 onWindowVisibilityChanged(vis);
11683 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070011684 if ((mPrivateFlags&PFLAG_DRAWABLE_STATE_DIRTY) != 0) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080011685 // If nobody has evaluated the drawable state yet, then do it now.
11686 refreshDrawableState();
11687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011688 }
11689
11690 void dispatchDetachedFromWindow() {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011691 AttachInfo info = mAttachInfo;
11692 if (info != null) {
11693 int vis = info.mWindowVisibility;
11694 if (vis != GONE) {
11695 onWindowVisibilityChanged(GONE);
11696 }
11697 }
11698
11699 onDetachedFromWindow();
Romain Guy01d5edc2011-01-28 11:28:53 -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.onViewDetachedFromWindow(this);
11711 }
11712 }
11713
Dianne Hackborn4702a852012-08-17 15:18:29 -070011714 if ((mPrivateFlags & PFLAG_SCROLL_CONTAINER_ADDED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011715 mAttachInfo.mScrollContainers.remove(this);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011716 mPrivateFlags &= ~PFLAG_SCROLL_CONTAINER_ADDED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011717 }
Romain Guy01d5edc2011-01-28 11:28:53 -080011718
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011719 mAttachInfo = null;
11720 }
11721
11722 /**
11723 * Store this view hierarchy's frozen state into the given container.
11724 *
11725 * @param container The SparseArray in which to save the view's state.
11726 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011727 * @see #restoreHierarchyState(android.util.SparseArray)
11728 * @see #dispatchSaveInstanceState(android.util.SparseArray)
11729 * @see #onSaveInstanceState()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011730 */
11731 public void saveHierarchyState(SparseArray<Parcelable> container) {
11732 dispatchSaveInstanceState(container);
11733 }
11734
11735 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070011736 * Called by {@link #saveHierarchyState(android.util.SparseArray)} to store the state for
11737 * this view and its children. May be overridden to modify how freezing happens to a
11738 * 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 -080011739 *
11740 * @param container The SparseArray in which to save the view's state.
11741 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011742 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11743 * @see #saveHierarchyState(android.util.SparseArray)
11744 * @see #onSaveInstanceState()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011745 */
11746 protected void dispatchSaveInstanceState(SparseArray<Parcelable> container) {
11747 if (mID != NO_ID && (mViewFlags & SAVE_DISABLED_MASK) == 0) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011748 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011749 Parcelable state = onSaveInstanceState();
Dianne Hackborn4702a852012-08-17 15:18:29 -070011750 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011751 throw new IllegalStateException(
11752 "Derived class did not call super.onSaveInstanceState()");
11753 }
11754 if (state != null) {
11755 // Log.i("View", "Freezing #" + Integer.toHexString(mID)
11756 // + ": " + state);
11757 container.put(mID, state);
11758 }
11759 }
11760 }
11761
11762 /**
11763 * Hook allowing a view to generate a representation of its internal state
11764 * that can later be used to create a new instance with that same state.
11765 * This state should only contain information that is not persistent or can
11766 * not be reconstructed later. For example, you will never store your
11767 * current position on screen because that will be computed again when a
11768 * new instance of the view is placed in its view hierarchy.
11769 * <p>
11770 * Some examples of things you may store here: the current cursor position
11771 * in a text view (but usually not the text itself since that is stored in a
11772 * content provider or other persistent storage), the currently selected
11773 * item in a list view.
11774 *
11775 * @return Returns a Parcelable object containing the view's current dynamic
11776 * state, or null if there is nothing interesting to save. The
11777 * default implementation returns null.
Philip Milne6c8ea062012-04-03 17:38:43 -070011778 * @see #onRestoreInstanceState(android.os.Parcelable)
11779 * @see #saveHierarchyState(android.util.SparseArray)
11780 * @see #dispatchSaveInstanceState(android.util.SparseArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011781 * @see #setSaveEnabled(boolean)
11782 */
11783 protected Parcelable onSaveInstanceState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011784 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011785 return BaseSavedState.EMPTY_STATE;
11786 }
11787
11788 /**
11789 * Restore this view hierarchy's frozen state from the given container.
11790 *
11791 * @param container The SparseArray which holds previously frozen states.
11792 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011793 * @see #saveHierarchyState(android.util.SparseArray)
11794 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
11795 * @see #onRestoreInstanceState(android.os.Parcelable)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011796 */
11797 public void restoreHierarchyState(SparseArray<Parcelable> container) {
11798 dispatchRestoreInstanceState(container);
11799 }
11800
11801 /**
Romain Guy5c22a8c2011-05-13 11:48:45 -070011802 * Called by {@link #restoreHierarchyState(android.util.SparseArray)} to retrieve the
11803 * state for this view and its children. May be overridden to modify how restoring
11804 * happens to a view's children; for example, some views may want to not store state
11805 * for their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011806 *
11807 * @param container The SparseArray which holds previously saved state.
11808 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011809 * @see #dispatchSaveInstanceState(android.util.SparseArray)
11810 * @see #restoreHierarchyState(android.util.SparseArray)
11811 * @see #onRestoreInstanceState(android.os.Parcelable)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011812 */
11813 protected void dispatchRestoreInstanceState(SparseArray<Parcelable> container) {
11814 if (mID != NO_ID) {
11815 Parcelable state = container.get(mID);
11816 if (state != null) {
11817 // Log.i("View", "Restoreing #" + Integer.toHexString(mID)
11818 // + ": " + state);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011819 mPrivateFlags &= ~PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011820 onRestoreInstanceState(state);
Dianne Hackborn4702a852012-08-17 15:18:29 -070011821 if ((mPrivateFlags & PFLAG_SAVE_STATE_CALLED) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011822 throw new IllegalStateException(
11823 "Derived class did not call super.onRestoreInstanceState()");
11824 }
11825 }
11826 }
11827 }
11828
11829 /**
11830 * Hook allowing a view to re-apply a representation of its internal state that had previously
11831 * been generated by {@link #onSaveInstanceState}. This function will never be called with a
11832 * null state.
11833 *
11834 * @param state The frozen state that had previously been returned by
11835 * {@link #onSaveInstanceState}.
11836 *
Philip Milne6c8ea062012-04-03 17:38:43 -070011837 * @see #onSaveInstanceState()
11838 * @see #restoreHierarchyState(android.util.SparseArray)
11839 * @see #dispatchRestoreInstanceState(android.util.SparseArray)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011840 */
11841 protected void onRestoreInstanceState(Parcelable state) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070011842 mPrivateFlags |= PFLAG_SAVE_STATE_CALLED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011843 if (state != BaseSavedState.EMPTY_STATE && state != null) {
Romain Guy237c1ce2009-12-08 11:30:25 -080011844 throw new IllegalArgumentException("Wrong state class, expecting View State but "
11845 + "received " + state.getClass().toString() + " instead. This usually happens "
Joe Malin32736f02011-01-19 16:14:20 -080011846 + "when two views of different type have the same id in the same hierarchy. "
11847 + "This view's id is " + ViewDebug.resolveId(mContext, getId()) + ". Make sure "
Romain Guy237c1ce2009-12-08 11:30:25 -080011848 + "other views do not use the same id.");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011849 }
11850 }
11851
11852 /**
11853 * <p>Return the time at which the drawing of the view hierarchy started.</p>
11854 *
11855 * @return the drawing start time in milliseconds
11856 */
11857 public long getDrawingTime() {
11858 return mAttachInfo != null ? mAttachInfo.mDrawingTime : 0;
11859 }
11860
11861 /**
11862 * <p>Enables or disables the duplication of the parent's state into this view. When
11863 * duplication is enabled, this view gets its drawable state from its parent rather
11864 * than from its own internal properties.</p>
11865 *
11866 * <p>Note: in the current implementation, setting this property to true after the
11867 * view was added to a ViewGroup might have no effect at all. This property should
11868 * always be used from XML or set to true before adding this view to a ViewGroup.</p>
11869 *
11870 * <p>Note: if this view's parent addStateFromChildren property is enabled and this
11871 * property is enabled, an exception will be thrown.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011872 *
Gilles Debunnefb817032011-01-13 13:52:49 -080011873 * <p>Note: if the child view uses and updates additionnal states which are unknown to the
11874 * parent, these states should not be affected by this method.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080011875 *
11876 * @param enabled True to enable duplication of the parent's drawable state, false
11877 * to disable it.
11878 *
11879 * @see #getDrawableState()
11880 * @see #isDuplicateParentStateEnabled()
11881 */
11882 public void setDuplicateParentStateEnabled(boolean enabled) {
11883 setFlags(enabled ? DUPLICATE_PARENT_STATE : 0, DUPLICATE_PARENT_STATE);
11884 }
11885
11886 /**
11887 * <p>Indicates whether this duplicates its drawable state from its parent.</p>
11888 *
11889 * @return True if this view's drawable state is duplicated from the parent,
11890 * false otherwise
11891 *
11892 * @see #getDrawableState()
11893 * @see #setDuplicateParentStateEnabled(boolean)
11894 */
11895 public boolean isDuplicateParentStateEnabled() {
11896 return (mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE;
11897 }
11898
11899 /**
Romain Guy171c5922011-01-06 10:04:23 -080011900 * <p>Specifies the type of layer backing this view. The layer can be
11901 * {@link #LAYER_TYPE_NONE disabled}, {@link #LAYER_TYPE_SOFTWARE software} or
11902 * {@link #LAYER_TYPE_HARDWARE hardware}.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011903 *
Romain Guy171c5922011-01-06 10:04:23 -080011904 * <p>A layer is associated with an optional {@link android.graphics.Paint}
11905 * instance that controls how the layer is composed on screen. The following
11906 * properties of the paint are taken into account when composing the layer:</p>
11907 * <ul>
11908 * <li>{@link android.graphics.Paint#getAlpha() Translucency (alpha)}</li>
11909 * <li>{@link android.graphics.Paint#getXfermode() Blending mode}</li>
11910 * <li>{@link android.graphics.Paint#getColorFilter() Color filter}</li>
11911 * </ul>
Joe Malin32736f02011-01-19 16:14:20 -080011912 *
Romain Guy171c5922011-01-06 10:04:23 -080011913 * <p>If this view has an alpha value set to < 1.0 by calling
11914 * {@link #setAlpha(float)}, the alpha value of the layer's paint is replaced by
11915 * this view's alpha value. Calling {@link #setAlpha(float)} is therefore
11916 * equivalent to setting a hardware layer on this view and providing a paint with
11917 * the desired alpha value.<p>
Joe Malin32736f02011-01-19 16:14:20 -080011918 *
Romain Guy171c5922011-01-06 10:04:23 -080011919 * <p>Refer to the documentation of {@link #LAYER_TYPE_NONE disabled},
11920 * {@link #LAYER_TYPE_SOFTWARE software} and {@link #LAYER_TYPE_HARDWARE hardware}
11921 * for more information on when and how to use layers.</p>
Joe Malin32736f02011-01-19 16:14:20 -080011922 *
Romain Guy171c5922011-01-06 10:04:23 -080011923 * @param layerType The ype of layer to use with this view, must be one of
11924 * {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
11925 * {@link #LAYER_TYPE_HARDWARE}
11926 * @param paint The paint used to compose the layer. This argument is optional
11927 * and can be null. It is ignored when the layer type is
11928 * {@link #LAYER_TYPE_NONE}
Joe Malin32736f02011-01-19 16:14:20 -080011929 *
11930 * @see #getLayerType()
Romain Guy171c5922011-01-06 10:04:23 -080011931 * @see #LAYER_TYPE_NONE
11932 * @see #LAYER_TYPE_SOFTWARE
11933 * @see #LAYER_TYPE_HARDWARE
Joe Malin32736f02011-01-19 16:14:20 -080011934 * @see #setAlpha(float)
11935 *
Romain Guy171c5922011-01-06 10:04:23 -080011936 * @attr ref android.R.styleable#View_layerType
11937 */
11938 public void setLayerType(int layerType, Paint paint) {
11939 if (layerType < LAYER_TYPE_NONE || layerType > LAYER_TYPE_HARDWARE) {
Joe Malin32736f02011-01-19 16:14:20 -080011940 throw new IllegalArgumentException("Layer type can only be one of: LAYER_TYPE_NONE, "
Romain Guy171c5922011-01-06 10:04:23 -080011941 + "LAYER_TYPE_SOFTWARE or LAYER_TYPE_HARDWARE");
11942 }
Chet Haasedaf98e92011-01-10 14:10:36 -080011943
Romain Guyd6cd5722011-01-17 14:42:41 -080011944 if (layerType == mLayerType) {
11945 if (layerType != LAYER_TYPE_NONE && paint != mLayerPaint) {
11946 mLayerPaint = paint == null ? new Paint() : paint;
Romain Guy0fd89bf2011-01-26 15:41:30 -080011947 invalidateParentCaches();
11948 invalidate(true);
Romain Guyd6cd5722011-01-17 14:42:41 -080011949 }
11950 return;
11951 }
Romain Guy171c5922011-01-06 10:04:23 -080011952
11953 // Destroy any previous software drawing cache if needed
Romain Guy6c319ca2011-01-11 14:29:25 -080011954 switch (mLayerType) {
Chet Haase6f33e812011-05-17 12:42:19 -070011955 case LAYER_TYPE_HARDWARE:
Romain Guya998dff2012-03-23 18:58:36 -070011956 destroyLayer(false);
Romain Guy31f2c2e2011-11-21 10:55:41 -080011957 // fall through - non-accelerated views may use software layer mechanism instead
Romain Guy6c319ca2011-01-11 14:29:25 -080011958 case LAYER_TYPE_SOFTWARE:
Romain Guy6d7475d2011-07-27 16:28:21 -070011959 destroyDrawingCache();
Romain Guy6c319ca2011-01-11 14:29:25 -080011960 break;
Romain Guy6c319ca2011-01-11 14:29:25 -080011961 default:
11962 break;
Romain Guy171c5922011-01-06 10:04:23 -080011963 }
11964
11965 mLayerType = layerType;
Romain Guy3a3133d2011-02-01 22:59:58 -080011966 final boolean layerDisabled = mLayerType == LAYER_TYPE_NONE;
11967 mLayerPaint = layerDisabled ? null : (paint == null ? new Paint() : paint);
11968 mLocalDirtyRect = layerDisabled ? null : new Rect();
Romain Guy171c5922011-01-06 10:04:23 -080011969
Romain Guy0fd89bf2011-01-26 15:41:30 -080011970 invalidateParentCaches();
11971 invalidate(true);
Romain Guy171c5922011-01-06 10:04:23 -080011972 }
11973
11974 /**
Romain Guy59c7f802011-09-29 17:21:45 -070011975 * Indicates whether this view has a static layer. A view with layer type
11976 * {@link #LAYER_TYPE_NONE} is a static layer. Other types of layers are
11977 * dynamic.
11978 */
11979 boolean hasStaticLayer() {
Romain Guy2bf68f02012-03-02 13:37:47 -080011980 return true;
Romain Guy59c7f802011-09-29 17:21:45 -070011981 }
11982
11983 /**
Romain Guy171c5922011-01-06 10:04:23 -080011984 * Indicates what type of layer is currently associated with this view. By default
11985 * a view does not have a layer, and the layer type is {@link #LAYER_TYPE_NONE}.
11986 * Refer to the documentation of {@link #setLayerType(int, android.graphics.Paint)}
11987 * for more information on the different types of layers.
Joe Malin32736f02011-01-19 16:14:20 -080011988 *
Romain Guy171c5922011-01-06 10:04:23 -080011989 * @return {@link #LAYER_TYPE_NONE}, {@link #LAYER_TYPE_SOFTWARE} or
11990 * {@link #LAYER_TYPE_HARDWARE}
Joe Malin32736f02011-01-19 16:14:20 -080011991 *
11992 * @see #setLayerType(int, android.graphics.Paint)
Philip Milne6c8ea062012-04-03 17:38:43 -070011993 * @see #buildLayer()
Romain Guy171c5922011-01-06 10:04:23 -080011994 * @see #LAYER_TYPE_NONE
11995 * @see #LAYER_TYPE_SOFTWARE
11996 * @see #LAYER_TYPE_HARDWARE
11997 */
11998 public int getLayerType() {
11999 return mLayerType;
12000 }
Joe Malin32736f02011-01-19 16:14:20 -080012001
Romain Guy6c319ca2011-01-11 14:29:25 -080012002 /**
Romain Guyf1ae1062011-03-02 18:16:04 -080012003 * Forces this view's layer to be created and this view to be rendered
12004 * into its layer. If this view's layer type is set to {@link #LAYER_TYPE_NONE},
12005 * invoking this method will have no effect.
Philip Milne6c8ea062012-04-03 17:38:43 -070012006 *
Romain Guyf1ae1062011-03-02 18:16:04 -080012007 * This method can for instance be used to render a view into its layer before
12008 * starting an animation. If this view is complex, rendering into the layer
12009 * before starting the animation will avoid skipping frames.
Philip Milne6c8ea062012-04-03 17:38:43 -070012010 *
Romain Guyf1ae1062011-03-02 18:16:04 -080012011 * @throws IllegalStateException If this view is not attached to a window
Philip Milne6c8ea062012-04-03 17:38:43 -070012012 *
12013 * @see #setLayerType(int, android.graphics.Paint)
Romain Guyf1ae1062011-03-02 18:16:04 -080012014 */
12015 public void buildLayer() {
12016 if (mLayerType == LAYER_TYPE_NONE) return;
12017
12018 if (mAttachInfo == null) {
12019 throw new IllegalStateException("This view must be attached to a window first");
12020 }
12021
12022 switch (mLayerType) {
12023 case LAYER_TYPE_HARDWARE:
Romain Guyd0609e42011-11-21 17:21:15 -080012024 if (mAttachInfo.mHardwareRenderer != null &&
12025 mAttachInfo.mHardwareRenderer.isEnabled() &&
12026 mAttachInfo.mHardwareRenderer.validate()) {
Michael Jurka7e52caf2012-03-06 15:57:06 -080012027 getHardwareLayer();
Romain Guyd0609e42011-11-21 17:21:15 -080012028 }
Romain Guyf1ae1062011-03-02 18:16:04 -080012029 break;
12030 case LAYER_TYPE_SOFTWARE:
12031 buildDrawingCache(true);
12032 break;
12033 }
12034 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012035
Romain Guyf1ae1062011-03-02 18:16:04 -080012036 /**
Romain Guy6c319ca2011-01-11 14:29:25 -080012037 * <p>Returns a hardware layer that can be used to draw this view again
12038 * without executing its draw method.</p>
12039 *
12040 * @return A HardwareLayer ready to render, or null if an error occurred.
12041 */
Michael Jurka7e52caf2012-03-06 15:57:06 -080012042 HardwareLayer getHardwareLayer() {
Romain Guyea835032011-07-28 19:24:37 -070012043 if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null ||
12044 !mAttachInfo.mHardwareRenderer.isEnabled()) {
Romain Guy6c319ca2011-01-11 14:29:25 -080012045 return null;
12046 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012047
Romain Guy9c4b79a2011-11-10 19:23:58 -080012048 if (!mAttachInfo.mHardwareRenderer.validate()) return null;
Romain Guy6c319ca2011-01-11 14:29:25 -080012049
12050 final int width = mRight - mLeft;
12051 final int height = mBottom - mTop;
Joe Malin32736f02011-01-19 16:14:20 -080012052
Romain Guy6c319ca2011-01-11 14:29:25 -080012053 if (width == 0 || height == 0) {
12054 return null;
12055 }
12056
Dianne Hackborn4702a852012-08-17 15:18:29 -070012057 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || mHardwareLayer == null) {
Romain Guy6c319ca2011-01-11 14:29:25 -080012058 if (mHardwareLayer == null) {
12059 mHardwareLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(
12060 width, height, isOpaque());
Michael Jurka952e02b2012-03-13 18:34:35 -070012061 mLocalDirtyRect.set(0, 0, width, height);
Romain Guy846a5332012-07-11 17:44:57 -070012062 } else {
12063 if (mHardwareLayer.getWidth() != width || mHardwareLayer.getHeight() != height) {
12064 mHardwareLayer.resize(width, height);
12065 mLocalDirtyRect.set(0, 0, width, height);
12066 }
12067
12068 // This should not be necessary but applications that change
12069 // the parameters of their background drawable without calling
12070 // this.setBackground(Drawable) can leave the view in a bad state
12071 // (for instance isOpaque() returns true, but the background is
12072 // not opaque.)
12073 computeOpaqueFlags();
12074
12075 final boolean opaque = isOpaque();
12076 if (mHardwareLayer.isOpaque() != opaque) {
12077 mHardwareLayer.setOpaque(opaque);
12078 mLocalDirtyRect.set(0, 0, width, height);
12079 }
Romain Guy6c319ca2011-01-11 14:29:25 -080012080 }
12081
Romain Guy5cd5c3f2011-10-17 17:10:02 -070012082 // The layer is not valid if the underlying GPU resources cannot be allocated
12083 if (!mHardwareLayer.isValid()) {
12084 return null;
12085 }
12086
Chet Haasea1cff502012-02-21 13:43:44 -080012087 mHardwareLayer.redraw(getHardwareLayerDisplayList(mHardwareLayer), mLocalDirtyRect);
Michael Jurka7e52caf2012-03-06 15:57:06 -080012088 mLocalDirtyRect.setEmpty();
Romain Guy6c319ca2011-01-11 14:29:25 -080012089 }
12090
12091 return mHardwareLayer;
12092 }
Romain Guy171c5922011-01-06 10:04:23 -080012093
Romain Guy589b0bb2011-10-10 13:57:47 -070012094 /**
12095 * Destroys this View's hardware layer if possible.
Philip Milne6c8ea062012-04-03 17:38:43 -070012096 *
Romain Guy589b0bb2011-10-10 13:57:47 -070012097 * @return True if the layer was destroyed, false otherwise.
Philip Milne6c8ea062012-04-03 17:38:43 -070012098 *
12099 * @see #setLayerType(int, android.graphics.Paint)
Romain Guy589b0bb2011-10-10 13:57:47 -070012100 * @see #LAYER_TYPE_HARDWARE
12101 */
Romain Guya998dff2012-03-23 18:58:36 -070012102 boolean destroyLayer(boolean valid) {
Romain Guy6d7475d2011-07-27 16:28:21 -070012103 if (mHardwareLayer != null) {
Romain Guy9c4b79a2011-11-10 19:23:58 -080012104 AttachInfo info = mAttachInfo;
12105 if (info != null && info.mHardwareRenderer != null &&
Romain Guya998dff2012-03-23 18:58:36 -070012106 info.mHardwareRenderer.isEnabled() &&
12107 (valid || info.mHardwareRenderer.validate())) {
Romain Guy9c4b79a2011-11-10 19:23:58 -080012108 mHardwareLayer.destroy();
12109 mHardwareLayer = null;
Romain Guy31f2c2e2011-11-21 10:55:41 -080012110
Romain Guy9c4b79a2011-11-10 19:23:58 -080012111 invalidate(true);
12112 invalidateParentCaches();
12113 }
Romain Guy65b345f2011-07-27 18:51:50 -070012114 return true;
Romain Guy6d7475d2011-07-27 16:28:21 -070012115 }
Romain Guy65b345f2011-07-27 18:51:50 -070012116 return false;
Romain Guy6d7475d2011-07-27 16:28:21 -070012117 }
12118
Romain Guy171c5922011-01-06 10:04:23 -080012119 /**
Romain Guy31f2c2e2011-11-21 10:55:41 -080012120 * Destroys all hardware rendering resources. This method is invoked
12121 * when the system needs to reclaim resources. Upon execution of this
12122 * method, you should free any OpenGL resources created by the view.
Philip Milne6c8ea062012-04-03 17:38:43 -070012123 *
Romain Guy31f2c2e2011-11-21 10:55:41 -080012124 * Note: you <strong>must</strong> call
12125 * <code>super.destroyHardwareResources()</code> when overriding
12126 * this method.
Philip Milne6c8ea062012-04-03 17:38:43 -070012127 *
Romain Guy31f2c2e2011-11-21 10:55:41 -080012128 * @hide
12129 */
12130 protected void destroyHardwareResources() {
Romain Guya998dff2012-03-23 18:58:36 -070012131 destroyLayer(true);
Romain Guy31f2c2e2011-11-21 10:55:41 -080012132 }
12133
12134 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012135 * <p>Enables or disables the drawing cache. When the drawing cache is enabled, the next call
12136 * to {@link #getDrawingCache()} or {@link #buildDrawingCache()} will draw the view in a
12137 * bitmap. Calling {@link #draw(android.graphics.Canvas)} will not draw from the cache when
12138 * the cache is enabled. To benefit from the cache, you must request the drawing cache by
12139 * calling {@link #getDrawingCache()} and draw it on screen if the returned bitmap is not
12140 * null.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012141 *
Romain Guy171c5922011-01-06 10:04:23 -080012142 * <p>Enabling the drawing cache is similar to
12143 * {@link #setLayerType(int, android.graphics.Paint) setting a layer} when hardware
Chet Haasedaf98e92011-01-10 14:10:36 -080012144 * acceleration is turned off. When hardware acceleration is turned on, enabling the
12145 * drawing cache has no effect on rendering because the system uses a different mechanism
12146 * for acceleration which ignores the flag. If you want to use a Bitmap for the view, even
12147 * when hardware acceleration is enabled, see {@link #setLayerType(int, android.graphics.Paint)}
12148 * for information on how to enable software and hardware layers.</p>
12149 *
12150 * <p>This API can be used to manually generate
12151 * a bitmap copy of this view, by setting the flag to <code>true</code> and calling
12152 * {@link #getDrawingCache()}.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012153 *
12154 * @param enabled true to enable the drawing cache, false otherwise
12155 *
12156 * @see #isDrawingCacheEnabled()
12157 * @see #getDrawingCache()
12158 * @see #buildDrawingCache()
Joe Malin32736f02011-01-19 16:14:20 -080012159 * @see #setLayerType(int, android.graphics.Paint)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012160 */
12161 public void setDrawingCacheEnabled(boolean enabled) {
Romain Guy0211a0a2011-02-14 16:34:59 -080012162 mCachingFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012163 setFlags(enabled ? DRAWING_CACHE_ENABLED : 0, DRAWING_CACHE_ENABLED);
12164 }
12165
12166 /**
12167 * <p>Indicates whether the drawing cache is enabled for this view.</p>
12168 *
12169 * @return true if the drawing cache is enabled
12170 *
12171 * @see #setDrawingCacheEnabled(boolean)
12172 * @see #getDrawingCache()
12173 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070012174 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012175 public boolean isDrawingCacheEnabled() {
12176 return (mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED;
12177 }
12178
12179 /**
Chet Haasedaf98e92011-01-10 14:10:36 -080012180 * Debugging utility which recursively outputs the dirty state of a view and its
12181 * descendants.
Joe Malin32736f02011-01-19 16:14:20 -080012182 *
Chet Haasedaf98e92011-01-10 14:10:36 -080012183 * @hide
12184 */
Romain Guy676b1732011-02-14 14:45:33 -080012185 @SuppressWarnings({"UnusedDeclaration"})
Chet Haasedaf98e92011-01-10 14:10:36 -080012186 public void outputDirtyFlags(String indent, boolean clear, int clearMask) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012187 Log.d("View", indent + this + " DIRTY(" + (mPrivateFlags & View.PFLAG_DIRTY_MASK) +
12188 ") DRAWN(" + (mPrivateFlags & PFLAG_DRAWN) + ")" + " CACHE_VALID(" +
12189 (mPrivateFlags & View.PFLAG_DRAWING_CACHE_VALID) +
12190 ") INVALIDATED(" + (mPrivateFlags & PFLAG_INVALIDATED) + ")");
Chet Haasedaf98e92011-01-10 14:10:36 -080012191 if (clear) {
12192 mPrivateFlags &= clearMask;
12193 }
12194 if (this instanceof ViewGroup) {
12195 ViewGroup parent = (ViewGroup) this;
12196 final int count = parent.getChildCount();
12197 for (int i = 0; i < count; i++) {
Romain Guy7d7b5492011-01-24 16:33:45 -080012198 final View child = parent.getChildAt(i);
Chet Haasedaf98e92011-01-10 14:10:36 -080012199 child.outputDirtyFlags(indent + " ", clear, clearMask);
12200 }
12201 }
12202 }
12203
12204 /**
12205 * This method is used by ViewGroup to cause its children to restore or recreate their
12206 * display lists. It is called by getDisplayList() when the parent ViewGroup does not need
12207 * to recreate its own display list, which would happen if it went through the normal
12208 * draw/dispatchDraw mechanisms.
12209 *
12210 * @hide
12211 */
12212 protected void dispatchGetDisplayList() {}
Chet Haasef4ac5472011-01-27 10:30:25 -080012213
12214 /**
12215 * A view that is not attached or hardware accelerated cannot create a display list.
12216 * This method checks these conditions and returns the appropriate result.
12217 *
12218 * @return true if view has the ability to create a display list, false otherwise.
12219 *
12220 * @hide
12221 */
12222 public boolean canHaveDisplayList() {
Romain Guy676b1732011-02-14 14:45:33 -080012223 return !(mAttachInfo == null || mAttachInfo.mHardwareRenderer == null);
Chet Haasef4ac5472011-01-27 10:30:25 -080012224 }
Joe Malin32736f02011-01-19 16:14:20 -080012225
Chet Haasedaf98e92011-01-10 14:10:36 -080012226 /**
Gilles Debunneb35ab7b2011-12-05 15:54:00 -080012227 * @return The HardwareRenderer associated with that view or null if hardware rendering
12228 * is not supported or this this has not been attached to a window.
12229 *
12230 * @hide
12231 */
12232 public HardwareRenderer getHardwareRenderer() {
12233 if (mAttachInfo != null) {
12234 return mAttachInfo.mHardwareRenderer;
12235 }
12236 return null;
12237 }
12238
12239 /**
Chet Haasea1cff502012-02-21 13:43:44 -080012240 * Returns a DisplayList. If the incoming displayList is null, one will be created.
12241 * Otherwise, the same display list will be returned (after having been rendered into
12242 * along the way, depending on the invalidation state of the view).
12243 *
12244 * @param displayList The previous version of this displayList, could be null.
12245 * @param isLayer Whether the requester of the display list is a layer. If so,
12246 * the view will avoid creating a layer inside the resulting display list.
12247 * @return A new or reused DisplayList object.
12248 */
12249 private DisplayList getDisplayList(DisplayList displayList, boolean isLayer) {
12250 if (!canHaveDisplayList()) {
12251 return null;
12252 }
12253
Dianne Hackborn4702a852012-08-17 15:18:29 -070012254 if (((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 ||
Chet Haasea1cff502012-02-21 13:43:44 -080012255 displayList == null || !displayList.isValid() ||
12256 (!isLayer && mRecreateDisplayList))) {
12257 // Don't need to recreate the display list, just need to tell our
12258 // children to restore/recreate theirs
12259 if (displayList != null && displayList.isValid() &&
12260 !isLayer && !mRecreateDisplayList) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012261 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12262 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haasea1cff502012-02-21 13:43:44 -080012263 dispatchGetDisplayList();
12264
12265 return displayList;
12266 }
12267
12268 if (!isLayer) {
12269 // If we got here, we're recreating it. Mark it as such to ensure that
12270 // we copy in child display lists into ours in drawChild()
12271 mRecreateDisplayList = true;
12272 }
12273 if (displayList == null) {
12274 final String name = getClass().getSimpleName();
12275 displayList = mAttachInfo.mHardwareRenderer.createDisplayList(name);
12276 // If we're creating a new display list, make sure our parent gets invalidated
12277 // since they will need to recreate their display list to account for this
12278 // new child display list.
12279 invalidateParentCaches();
12280 }
12281
12282 boolean caching = false;
12283 final HardwareCanvas canvas = displayList.start();
Chet Haasea1cff502012-02-21 13:43:44 -080012284 int width = mRight - mLeft;
12285 int height = mBottom - mTop;
12286
12287 try {
12288 canvas.setViewport(width, height);
12289 // The dirty rect should always be null for a display list
12290 canvas.onPreDraw(null);
Michael Jurkaba649742012-06-28 19:12:58 -070012291 int layerType = getLayerType();
Chet Haase1271e2c2012-04-20 09:54:27 -070012292 if (!isLayer && layerType != LAYER_TYPE_NONE) {
Chet Haaseb85967b2012-03-26 14:37:51 -070012293 if (layerType == LAYER_TYPE_HARDWARE) {
12294 final HardwareLayer layer = getHardwareLayer();
12295 if (layer != null && layer.isValid()) {
12296 canvas.drawHardwareLayer(layer, 0, 0, mLayerPaint);
12297 } else {
12298 canvas.saveLayer(0, 0, mRight - mLeft, mBottom - mTop, mLayerPaint,
12299 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
12300 Canvas.CLIP_TO_LAYER_SAVE_FLAG);
12301 }
12302 caching = true;
Chet Haasea1cff502012-02-21 13:43:44 -080012303 } else {
Chet Haaseb85967b2012-03-26 14:37:51 -070012304 buildDrawingCache(true);
12305 Bitmap cache = getDrawingCache(true);
12306 if (cache != null) {
12307 canvas.drawBitmap(cache, 0, 0, mLayerPaint);
12308 caching = true;
12309 }
Chet Haasea1cff502012-02-21 13:43:44 -080012310 }
Chet Haasea1cff502012-02-21 13:43:44 -080012311 } else {
12312
12313 computeScroll();
12314
Chet Haasea1cff502012-02-21 13:43:44 -080012315 canvas.translate(-mScrollX, -mScrollY);
12316 if (!isLayer) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012317 mPrivateFlags |= PFLAG_DRAWN | PFLAG_DRAWING_CACHE_VALID;
12318 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haasea1cff502012-02-21 13:43:44 -080012319 }
12320
12321 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070012322 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Chet Haasea1cff502012-02-21 13:43:44 -080012323 dispatchDraw(canvas);
12324 } else {
12325 draw(canvas);
12326 }
12327 }
12328 } finally {
Chet Haasea1cff502012-02-21 13:43:44 -080012329 canvas.onPostDraw();
12330
12331 displayList.end();
Chet Haase1271e2c2012-04-20 09:54:27 -070012332 displayList.setCaching(caching);
12333 if (isLayer) {
Chet Haasea1cff502012-02-21 13:43:44 -080012334 displayList.setLeftTopRightBottom(0, 0, width, height);
12335 } else {
12336 setDisplayListProperties(displayList);
12337 }
12338 }
12339 } else if (!isLayer) {
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 }
12343
12344 return displayList;
12345 }
12346
12347 /**
12348 * Get the DisplayList for the HardwareLayer
12349 *
12350 * @param layer The HardwareLayer whose DisplayList we want
12351 * @return A DisplayList fopr the specified HardwareLayer
12352 */
12353 private DisplayList getHardwareLayerDisplayList(HardwareLayer layer) {
12354 DisplayList displayList = getDisplayList(layer.getDisplayList(), true);
12355 layer.setDisplayList(displayList);
12356 return displayList;
12357 }
12358
12359
12360 /**
Romain Guyb051e892010-09-28 19:09:36 -070012361 * <p>Returns a display list that can be used to draw this view again
12362 * without executing its draw method.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012363 *
Romain Guyb051e892010-09-28 19:09:36 -070012364 * @return A DisplayList ready to replay, or null if caching is not enabled.
Chet Haasedaf98e92011-01-10 14:10:36 -080012365 *
12366 * @hide
Romain Guyb051e892010-09-28 19:09:36 -070012367 */
Chet Haasedaf98e92011-01-10 14:10:36 -080012368 public DisplayList getDisplayList() {
Chet Haasea1cff502012-02-21 13:43:44 -080012369 mDisplayList = getDisplayList(mDisplayList, false);
Romain Guyb051e892010-09-28 19:09:36 -070012370 return mDisplayList;
12371 }
12372
Romain Guy38c2ece2012-05-24 14:20:56 -070012373 private void clearDisplayList() {
12374 if (mDisplayList != null) {
12375 mDisplayList.invalidate();
12376 mDisplayList.clear();
12377 }
12378 }
12379
Romain Guyb051e892010-09-28 19:09:36 -070012380 /**
Romain Guyfbd8f692009-06-26 14:51:58 -070012381 * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012382 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012383 * @return A non-scaled bitmap representing this view or null if cache is disabled.
Joe Malin32736f02011-01-19 16:14:20 -080012384 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012385 * @see #getDrawingCache(boolean)
12386 */
12387 public Bitmap getDrawingCache() {
12388 return getDrawingCache(false);
12389 }
12390
12391 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012392 * <p>Returns the bitmap in which this view drawing is cached. The returned bitmap
12393 * is null when caching is disabled. If caching is enabled and the cache is not ready,
12394 * this method will create it. Calling {@link #draw(android.graphics.Canvas)} will not
12395 * draw from the cache when the cache is enabled. To benefit from the cache, you must
12396 * request the drawing cache by calling this method and draw it on screen if the
12397 * returned bitmap is not null.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012398 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012399 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12400 * this method will create a bitmap of the same size as this view. Because this bitmap
12401 * will be drawn scaled by the parent ViewGroup, the result on screen might show
12402 * scaling artifacts. To avoid such artifacts, you should call this method by setting
12403 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12404 * size than the view. This implies that your application must be able to handle this
12405 * size.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012406 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012407 * @param autoScale Indicates whether the generated bitmap should be scaled based on
12408 * the current density of the screen when the application is in compatibility
12409 * mode.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012410 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012411 * @return A bitmap representing this view or null if cache is disabled.
Joe Malin32736f02011-01-19 16:14:20 -080012412 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012413 * @see #setDrawingCacheEnabled(boolean)
12414 * @see #isDrawingCacheEnabled()
Romain Guyfbd8f692009-06-26 14:51:58 -070012415 * @see #buildDrawingCache(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012416 * @see #destroyDrawingCache()
12417 */
Romain Guyfbd8f692009-06-26 14:51:58 -070012418 public Bitmap getDrawingCache(boolean autoScale) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012419 if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
12420 return null;
12421 }
12422 if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012423 buildDrawingCache(autoScale);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012424 }
Romain Guy02890fd2010-08-06 17:58:44 -070012425 return autoScale ? mDrawingCache : mUnscaledDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012426 }
12427
12428 /**
12429 * <p>Frees the resources used by the drawing cache. If you call
12430 * {@link #buildDrawingCache()} manually without calling
12431 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12432 * should cleanup the cache with this method afterwards.</p>
12433 *
12434 * @see #setDrawingCacheEnabled(boolean)
12435 * @see #buildDrawingCache()
12436 * @see #getDrawingCache()
12437 */
12438 public void destroyDrawingCache() {
12439 if (mDrawingCache != null) {
Romain Guy02890fd2010-08-06 17:58:44 -070012440 mDrawingCache.recycle();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012441 mDrawingCache = null;
12442 }
Romain Guyfbd8f692009-06-26 14:51:58 -070012443 if (mUnscaledDrawingCache != null) {
Romain Guy02890fd2010-08-06 17:58:44 -070012444 mUnscaledDrawingCache.recycle();
Romain Guyfbd8f692009-06-26 14:51:58 -070012445 mUnscaledDrawingCache = null;
12446 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012447 }
12448
12449 /**
12450 * Setting a solid background color for the drawing cache's bitmaps will improve
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070012451 * performance and memory usage. Note, though that this should only be used if this
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012452 * view will always be drawn on top of a solid color.
12453 *
12454 * @param color The background color to use for the drawing cache's bitmap
12455 *
12456 * @see #setDrawingCacheEnabled(boolean)
12457 * @see #buildDrawingCache()
12458 * @see #getDrawingCache()
12459 */
12460 public void setDrawingCacheBackgroundColor(int color) {
Romain Guy52e2ef82010-01-14 12:11:48 -080012461 if (color != mDrawingCacheBackgroundColor) {
12462 mDrawingCacheBackgroundColor = color;
Dianne Hackborn4702a852012-08-17 15:18:29 -070012463 mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;
Romain Guy52e2ef82010-01-14 12:11:48 -080012464 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012465 }
12466
12467 /**
12468 * @see #setDrawingCacheBackgroundColor(int)
12469 *
12470 * @return The background color to used for the drawing cache's bitmap
12471 */
12472 public int getDrawingCacheBackgroundColor() {
12473 return mDrawingCacheBackgroundColor;
12474 }
12475
12476 /**
Romain Guyfbd8f692009-06-26 14:51:58 -070012477 * <p>Calling this method is equivalent to calling <code>buildDrawingCache(false)</code>.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012478 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012479 * @see #buildDrawingCache(boolean)
12480 */
12481 public void buildDrawingCache() {
12482 buildDrawingCache(false);
12483 }
Gilles Debunne2ed2eac2011-02-24 16:29:48 -080012484
Romain Guyfbd8f692009-06-26 14:51:58 -070012485 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012486 * <p>Forces the drawing cache to be built if the drawing cache is invalid.</p>
12487 *
12488 * <p>If you call {@link #buildDrawingCache()} manually without calling
12489 * {@link #setDrawingCacheEnabled(boolean) setDrawingCacheEnabled(true)}, you
12490 * should cleanup the cache by calling {@link #destroyDrawingCache()} afterwards.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012491 *
Romain Guyfbd8f692009-06-26 14:51:58 -070012492 * <p>Note about auto scaling in compatibility mode: When auto scaling is not enabled,
12493 * this method will create a bitmap of the same size as this view. Because this bitmap
12494 * will be drawn scaled by the parent ViewGroup, the result on screen might show
12495 * scaling artifacts. To avoid such artifacts, you should call this method by setting
12496 * the auto scaling to true. Doing so, however, will generate a bitmap of a different
12497 * size than the view. This implies that your application must be able to handle this
12498 * size.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012499 *
Romain Guy0d9275e2010-10-26 14:22:30 -070012500 * <p>You should avoid calling this method when hardware acceleration is enabled. If
12501 * you do not need the drawing cache bitmap, calling this method will increase memory
Joe Malin32736f02011-01-19 16:14:20 -080012502 * usage and cause the view to be rendered in software once, thus negatively impacting
Romain Guy0d9275e2010-10-26 14:22:30 -070012503 * performance.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012504 *
12505 * @see #getDrawingCache()
12506 * @see #destroyDrawingCache()
12507 */
Romain Guyfbd8f692009-06-26 14:51:58 -070012508 public void buildDrawingCache(boolean autoScale) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012509 if ((mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == 0 || (autoScale ?
Romain Guy02890fd2010-08-06 17:58:44 -070012510 mDrawingCache == null : mUnscaledDrawingCache == null)) {
Romain Guy0211a0a2011-02-14 16:34:59 -080012511 mCachingFailed = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012512
Romain Guy8506ab42009-06-11 17:35:47 -070012513 int width = mRight - mLeft;
12514 int height = mBottom - mTop;
12515
12516 final AttachInfo attachInfo = mAttachInfo;
Romain Guye1123222009-06-29 14:24:56 -070012517 final boolean scalingRequired = attachInfo != null && attachInfo.mScalingRequired;
Romain Guyfbd8f692009-06-26 14:51:58 -070012518
Romain Guye1123222009-06-29 14:24:56 -070012519 if (autoScale && scalingRequired) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012520 width = (int) ((width * attachInfo.mApplicationScale) + 0.5f);
12521 height = (int) ((height * attachInfo.mApplicationScale) + 0.5f);
Romain Guy8506ab42009-06-11 17:35:47 -070012522 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012523
12524 final int drawingCacheBackgroundColor = mDrawingCacheBackgroundColor;
Romain Guy35b38ce2009-10-07 13:38:55 -070012525 final boolean opaque = drawingCacheBackgroundColor != 0 || isOpaque();
Adam Powell26153a32010-11-08 15:22:27 -080012526 final boolean use32BitCache = attachInfo != null && attachInfo.mUse32BitDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012527
12528 if (width <= 0 || height <= 0 ||
Romain Guy35b38ce2009-10-07 13:38:55 -070012529 // Projected bitmap size in bytes
Adam Powell26153a32010-11-08 15:22:27 -080012530 (width * height * (opaque && !use32BitCache ? 2 : 4) >
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012531 ViewConfiguration.get(mContext).getScaledMaximumDrawingCacheSize())) {
12532 destroyDrawingCache();
Romain Guy0211a0a2011-02-14 16:34:59 -080012533 mCachingFailed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012534 return;
12535 }
12536
12537 boolean clear = true;
Romain Guy02890fd2010-08-06 17:58:44 -070012538 Bitmap bitmap = autoScale ? mDrawingCache : mUnscaledDrawingCache;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012539
12540 if (bitmap == null || bitmap.getWidth() != width || bitmap.getHeight() != height) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012541 Bitmap.Config quality;
12542 if (!opaque) {
Romain Guy676b1732011-02-14 14:45:33 -080012543 // Never pick ARGB_4444 because it looks awful
12544 // Keep the DRAWING_CACHE_QUALITY_LOW flag just in case
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012545 switch (mViewFlags & DRAWING_CACHE_QUALITY_MASK) {
12546 case DRAWING_CACHE_QUALITY_AUTO:
12547 quality = Bitmap.Config.ARGB_8888;
12548 break;
12549 case DRAWING_CACHE_QUALITY_LOW:
Romain Guy676b1732011-02-14 14:45:33 -080012550 quality = Bitmap.Config.ARGB_8888;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012551 break;
12552 case DRAWING_CACHE_QUALITY_HIGH:
12553 quality = Bitmap.Config.ARGB_8888;
12554 break;
12555 default:
12556 quality = Bitmap.Config.ARGB_8888;
12557 break;
12558 }
12559 } else {
Romain Guy35b38ce2009-10-07 13:38:55 -070012560 // Optimization for translucent windows
12561 // If the window is translucent, use a 32 bits bitmap to benefit from memcpy()
Adam Powell26153a32010-11-08 15:22:27 -080012562 quality = use32BitCache ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012563 }
12564
12565 // Try to cleanup memory
12566 if (bitmap != null) bitmap.recycle();
12567
12568 try {
Dianne Hackborndde331c2012-08-03 14:01:57 -070012569 bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12570 width, height, quality);
Dianne Hackborn11ea3342009-07-22 21:48:55 -070012571 bitmap.setDensity(getResources().getDisplayMetrics().densityDpi);
Romain Guyfbd8f692009-06-26 14:51:58 -070012572 if (autoScale) {
Romain Guy02890fd2010-08-06 17:58:44 -070012573 mDrawingCache = bitmap;
Romain Guyfbd8f692009-06-26 14:51:58 -070012574 } else {
Romain Guy02890fd2010-08-06 17:58:44 -070012575 mUnscaledDrawingCache = bitmap;
Romain Guyfbd8f692009-06-26 14:51:58 -070012576 }
Adam Powell26153a32010-11-08 15:22:27 -080012577 if (opaque && use32BitCache) bitmap.setHasAlpha(false);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012578 } catch (OutOfMemoryError e) {
12579 // If there is not enough memory to create the bitmap cache, just
12580 // ignore the issue as bitmap caches are not required to draw the
12581 // view hierarchy
Romain Guyfbd8f692009-06-26 14:51:58 -070012582 if (autoScale) {
12583 mDrawingCache = null;
12584 } else {
12585 mUnscaledDrawingCache = null;
12586 }
Romain Guy0211a0a2011-02-14 16:34:59 -080012587 mCachingFailed = true;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012588 return;
12589 }
12590
12591 clear = drawingCacheBackgroundColor != 0;
12592 }
12593
12594 Canvas canvas;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012595 if (attachInfo != null) {
12596 canvas = attachInfo.mCanvas;
12597 if (canvas == null) {
12598 canvas = new Canvas();
12599 }
12600 canvas.setBitmap(bitmap);
12601 // Temporarily clobber the cached Canvas in case one of our children
12602 // is also using a drawing cache. Without this, the children would
12603 // steal the canvas by attaching their own bitmap to it and bad, bad
12604 // thing would happen (invisible views, corrupted drawings, etc.)
12605 attachInfo.mCanvas = null;
12606 } else {
12607 // This case should hopefully never or seldom happen
12608 canvas = new Canvas(bitmap);
12609 }
12610
12611 if (clear) {
12612 bitmap.eraseColor(drawingCacheBackgroundColor);
12613 }
12614
12615 computeScroll();
12616 final int restoreCount = canvas.save();
Joe Malin32736f02011-01-19 16:14:20 -080012617
Romain Guye1123222009-06-29 14:24:56 -070012618 if (autoScale && scalingRequired) {
Romain Guyfbd8f692009-06-26 14:51:58 -070012619 final float scale = attachInfo.mApplicationScale;
12620 canvas.scale(scale, scale);
12621 }
Joe Malin32736f02011-01-19 16:14:20 -080012622
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012623 canvas.translate(-mScrollX, -mScrollY);
12624
Dianne Hackborn4702a852012-08-17 15:18:29 -070012625 mPrivateFlags |= PFLAG_DRAWN;
Romain Guy171c5922011-01-06 10:04:23 -080012626 if (mAttachInfo == null || !mAttachInfo.mHardwareAccelerated ||
12627 mLayerType != LAYER_TYPE_NONE) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070012628 mPrivateFlags |= PFLAG_DRAWING_CACHE_VALID;
Romain Guy0d9275e2010-10-26 14:22:30 -070012629 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012630
12631 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070012632 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
12633 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012634 dispatchDraw(canvas);
12635 } else {
12636 draw(canvas);
12637 }
12638
12639 canvas.restoreToCount(restoreCount);
Dianne Hackborn6311d0a2011-08-02 16:37:58 -070012640 canvas.setBitmap(null);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012641
12642 if (attachInfo != null) {
12643 // Restore the cached Canvas for our siblings
12644 attachInfo.mCanvas = canvas;
12645 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012646 }
12647 }
12648
12649 /**
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012650 * Create a snapshot of the view into a bitmap. We should probably make
12651 * some form of this public, but should think about the API.
12652 */
Romain Guy223ff5c2010-03-02 17:07:47 -080012653 Bitmap createSnapshot(Bitmap.Config quality, int backgroundColor, boolean skipChildren) {
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012654 int width = mRight - mLeft;
12655 int height = mBottom - mTop;
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012656
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012657 final AttachInfo attachInfo = mAttachInfo;
Romain Guy8c11e312009-09-14 15:15:30 -070012658 final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012659 width = (int) ((width * scale) + 0.5f);
12660 height = (int) ((height * scale) + 0.5f);
Joe Malin32736f02011-01-19 16:14:20 -080012661
Dianne Hackborndde331c2012-08-03 14:01:57 -070012662 Bitmap bitmap = Bitmap.createBitmap(mResources.getDisplayMetrics(),
12663 width > 0 ? width : 1, height > 0 ? height : 1, quality);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012664 if (bitmap == null) {
12665 throw new OutOfMemoryError();
12666 }
12667
Romain Guyc529d8d2011-09-06 15:01:39 -070012668 Resources resources = getResources();
12669 if (resources != null) {
12670 bitmap.setDensity(resources.getDisplayMetrics().densityDpi);
12671 }
Joe Malin32736f02011-01-19 16:14:20 -080012672
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012673 Canvas canvas;
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012674 if (attachInfo != null) {
12675 canvas = attachInfo.mCanvas;
12676 if (canvas == null) {
12677 canvas = new Canvas();
12678 }
12679 canvas.setBitmap(bitmap);
12680 // Temporarily clobber the cached Canvas in case one of our children
12681 // is also using a drawing cache. Without this, the children would
12682 // steal the canvas by attaching their own bitmap to it and bad, bad
12683 // things would happen (invisible views, corrupted drawings, etc.)
12684 attachInfo.mCanvas = null;
12685 } else {
12686 // This case should hopefully never or seldom happen
12687 canvas = new Canvas(bitmap);
12688 }
12689
Romain Guy5bcdff42009-05-14 21:27:18 -070012690 if ((backgroundColor & 0xff000000) != 0) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012691 bitmap.eraseColor(backgroundColor);
12692 }
12693
12694 computeScroll();
12695 final int restoreCount = canvas.save();
Dianne Hackborn8cae1242009-09-10 14:32:16 -070012696 canvas.scale(scale, scale);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012697 canvas.translate(-mScrollX, -mScrollY);
12698
Romain Guy5bcdff42009-05-14 21:27:18 -070012699 // Temporarily remove the dirty mask
12700 int flags = mPrivateFlags;
Dianne Hackborn4702a852012-08-17 15:18:29 -070012701 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Romain Guy5bcdff42009-05-14 21:27:18 -070012702
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012703 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070012704 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012705 dispatchDraw(canvas);
12706 } else {
12707 draw(canvas);
12708 }
12709
Romain Guy5bcdff42009-05-14 21:27:18 -070012710 mPrivateFlags = flags;
12711
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012712 canvas.restoreToCount(restoreCount);
Dianne Hackborn6311d0a2011-08-02 16:37:58 -070012713 canvas.setBitmap(null);
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012714
12715 if (attachInfo != null) {
12716 // Restore the cached Canvas for our siblings
12717 attachInfo.mCanvas = canvas;
12718 }
Romain Guy8506ab42009-06-11 17:35:47 -070012719
Dianne Hackborn958b9ad2009-03-31 18:00:36 -070012720 return bitmap;
12721 }
12722
12723 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080012724 * Indicates whether this View is currently in edit mode. A View is usually
12725 * in edit mode when displayed within a developer tool. For instance, if
12726 * this View is being drawn by a visual user interface builder, this method
12727 * should return true.
12728 *
12729 * Subclasses should check the return value of this method to provide
12730 * different behaviors if their normal behavior might interfere with the
12731 * host environment. For instance: the class spawns a thread in its
12732 * constructor, the drawing code relies on device-specific features, etc.
12733 *
12734 * This method is usually checked in the drawing code of custom widgets.
12735 *
12736 * @return True if this View is in edit mode, false otherwise.
12737 */
12738 public boolean isInEditMode() {
12739 return false;
12740 }
12741
12742 /**
12743 * If the View draws content inside its padding and enables fading edges,
12744 * it needs to support padding offsets. Padding offsets are added to the
12745 * fading edges to extend the length of the fade so that it covers pixels
12746 * drawn inside the padding.
12747 *
12748 * Subclasses of this class should override this method if they need
12749 * to draw content inside the padding.
12750 *
12751 * @return True if padding offset must be applied, false otherwise.
12752 *
12753 * @see #getLeftPaddingOffset()
12754 * @see #getRightPaddingOffset()
12755 * @see #getTopPaddingOffset()
12756 * @see #getBottomPaddingOffset()
12757 *
12758 * @since CURRENT
12759 */
12760 protected boolean isPaddingOffsetRequired() {
12761 return false;
12762 }
12763
12764 /**
12765 * Amount by which to extend the left fading region. Called only when
12766 * {@link #isPaddingOffsetRequired()} returns true.
12767 *
12768 * @return The left padding offset in pixels.
12769 *
12770 * @see #isPaddingOffsetRequired()
12771 *
12772 * @since CURRENT
12773 */
12774 protected int getLeftPaddingOffset() {
12775 return 0;
12776 }
12777
12778 /**
12779 * Amount by which to extend the right fading region. Called only when
12780 * {@link #isPaddingOffsetRequired()} returns true.
12781 *
12782 * @return The right padding offset in pixels.
12783 *
12784 * @see #isPaddingOffsetRequired()
12785 *
12786 * @since CURRENT
12787 */
12788 protected int getRightPaddingOffset() {
12789 return 0;
12790 }
12791
12792 /**
12793 * Amount by which to extend the top fading region. Called only when
12794 * {@link #isPaddingOffsetRequired()} returns true.
12795 *
12796 * @return The top padding offset in pixels.
12797 *
12798 * @see #isPaddingOffsetRequired()
12799 *
12800 * @since CURRENT
12801 */
12802 protected int getTopPaddingOffset() {
12803 return 0;
12804 }
12805
12806 /**
12807 * Amount by which to extend the bottom fading region. Called only when
12808 * {@link #isPaddingOffsetRequired()} returns true.
12809 *
12810 * @return The bottom padding offset in pixels.
12811 *
12812 * @see #isPaddingOffsetRequired()
12813 *
12814 * @since CURRENT
12815 */
12816 protected int getBottomPaddingOffset() {
12817 return 0;
12818 }
12819
12820 /**
Romain Guyf2fc4602011-07-19 15:20:03 -070012821 * @hide
12822 * @param offsetRequired
12823 */
12824 protected int getFadeTop(boolean offsetRequired) {
12825 int top = mPaddingTop;
12826 if (offsetRequired) top += getTopPaddingOffset();
12827 return top;
12828 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012829
Romain Guyf2fc4602011-07-19 15:20:03 -070012830 /**
12831 * @hide
12832 * @param offsetRequired
12833 */
12834 protected int getFadeHeight(boolean offsetRequired) {
12835 int padding = mPaddingTop;
Philip Milne6c8ea062012-04-03 17:38:43 -070012836 if (offsetRequired) padding += getTopPaddingOffset();
Romain Guyf2fc4602011-07-19 15:20:03 -070012837 return mBottom - mTop - mPaddingBottom - padding;
12838 }
Philip Milne6c8ea062012-04-03 17:38:43 -070012839
Romain Guyf2fc4602011-07-19 15:20:03 -070012840 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090012841 * <p>Indicates whether this view is attached to a hardware accelerated
Romain Guy2bffd262010-09-12 17:40:02 -070012842 * window or not.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012843 *
Romain Guy2bffd262010-09-12 17:40:02 -070012844 * <p>Even if this method returns true, it does not mean that every call
12845 * to {@link #draw(android.graphics.Canvas)} will be made with an hardware
12846 * accelerated {@link android.graphics.Canvas}. For instance, if this view
Ken Wakasaf76a50c2012-03-09 19:56:35 +090012847 * is drawn onto an offscreen {@link android.graphics.Bitmap} and its
Romain Guy2bffd262010-09-12 17:40:02 -070012848 * window is hardware accelerated,
12849 * {@link android.graphics.Canvas#isHardwareAccelerated()} will likely
12850 * return false, and this method will return true.</p>
Joe Malin32736f02011-01-19 16:14:20 -080012851 *
Romain Guy2bffd262010-09-12 17:40:02 -070012852 * @return True if the view is attached to a window and the window is
12853 * hardware accelerated; false in any other case.
12854 */
12855 public boolean isHardwareAccelerated() {
12856 return mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
12857 }
Joe Malin32736f02011-01-19 16:14:20 -080012858
Romain Guy2bffd262010-09-12 17:40:02 -070012859 /**
Chet Haasebcca79a2012-02-14 08:45:14 -080012860 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
12861 * case of an active Animation being run on the view.
12862 */
12863 private boolean drawAnimation(ViewGroup parent, long drawingTime,
12864 Animation a, boolean scalingRequired) {
12865 Transformation invalidationTransform;
12866 final int flags = parent.mGroupFlags;
12867 final boolean initialized = a.isInitialized();
12868 if (!initialized) {
Chet Haase1fb8a9e2012-04-19 09:22:34 -070012869 a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
Chet Haasebcca79a2012-02-14 08:45:14 -080012870 a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
Romain Guy393a52c2012-05-22 20:21:08 -070012871 if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
Chet Haasebcca79a2012-02-14 08:45:14 -080012872 onAnimationStart();
12873 }
12874
12875 boolean more = a.getTransformation(drawingTime, parent.mChildTransformation, 1f);
12876 if (scalingRequired && mAttachInfo.mApplicationScale != 1f) {
12877 if (parent.mInvalidationTransformation == null) {
12878 parent.mInvalidationTransformation = new Transformation();
12879 }
12880 invalidationTransform = parent.mInvalidationTransformation;
12881 a.getTransformation(drawingTime, invalidationTransform, 1f);
12882 } else {
12883 invalidationTransform = parent.mChildTransformation;
12884 }
Romain Guy393a52c2012-05-22 20:21:08 -070012885
Chet Haasebcca79a2012-02-14 08:45:14 -080012886 if (more) {
12887 if (!a.willChangeBounds()) {
Romain Guyf0af1d52012-07-11 18:31:21 -070012888 if ((flags & (ViewGroup.FLAG_OPTIMIZE_INVALIDATE | ViewGroup.FLAG_ANIMATION_DONE)) ==
12889 ViewGroup.FLAG_OPTIMIZE_INVALIDATE) {
12890 parent.mGroupFlags |= ViewGroup.FLAG_INVALIDATE_REQUIRED;
12891 } else if ((flags & ViewGroup.FLAG_INVALIDATE_REQUIRED) == 0) {
Chet Haasebcca79a2012-02-14 08:45:14 -080012892 // The child need to draw an animation, potentially offscreen, so
12893 // make sure we do not cancel invalidate requests
Dianne Hackborn4702a852012-08-17 15:18:29 -070012894 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
Chet Haasebcca79a2012-02-14 08:45:14 -080012895 parent.invalidate(mLeft, mTop, mRight, mBottom);
12896 }
12897 } else {
12898 if (parent.mInvalidateRegion == null) {
12899 parent.mInvalidateRegion = new RectF();
12900 }
12901 final RectF region = parent.mInvalidateRegion;
12902 a.getInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop, region,
12903 invalidationTransform);
12904
12905 // The child need to draw an animation, potentially offscreen, so
12906 // make sure we do not cancel invalidate requests
Dianne Hackborn4702a852012-08-17 15:18:29 -070012907 parent.mPrivateFlags |= PFLAG_DRAW_ANIMATION;
Chet Haasebcca79a2012-02-14 08:45:14 -080012908
12909 final int left = mLeft + (int) region.left;
12910 final int top = mTop + (int) region.top;
12911 parent.invalidate(left, top, left + (int) (region.width() + .5f),
12912 top + (int) (region.height() + .5f));
12913 }
12914 }
12915 return more;
12916 }
12917
Chet Haasea1cff502012-02-21 13:43:44 -080012918 /**
12919 * This method is called by getDisplayList() when a display list is created or re-rendered.
12920 * It sets or resets the current value of all properties on that display list (resetting is
12921 * necessary when a display list is being re-created, because we need to make sure that
12922 * previously-set transform values
12923 */
12924 void setDisplayListProperties(DisplayList displayList) {
Chet Haase1271e2c2012-04-20 09:54:27 -070012925 if (displayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080012926 displayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
Chet Haasedb8c9a62012-03-21 18:54:18 -070012927 displayList.setHasOverlappingRendering(hasOverlappingRendering());
Chet Haasea1cff502012-02-21 13:43:44 -080012928 if (mParent instanceof ViewGroup) {
12929 displayList.setClipChildren(
12930 (((ViewGroup)mParent).mGroupFlags & ViewGroup.FLAG_CLIP_CHILDREN) != 0);
12931 }
Chet Haase9420abd2012-03-29 16:28:32 -070012932 float alpha = 1;
12933 if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
12934 ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
12935 ViewGroup parentVG = (ViewGroup) mParent;
12936 final boolean hasTransform =
12937 parentVG.getChildStaticTransformation(this, parentVG.mChildTransformation);
12938 if (hasTransform) {
12939 Transformation transform = parentVG.mChildTransformation;
12940 final int transformType = parentVG.mChildTransformation.getTransformationType();
12941 if (transformType != Transformation.TYPE_IDENTITY) {
12942 if ((transformType & Transformation.TYPE_ALPHA) != 0) {
12943 alpha = transform.getAlpha();
12944 }
12945 if ((transformType & Transformation.TYPE_MATRIX) != 0) {
12946 displayList.setStaticMatrix(transform.getMatrix());
12947 }
12948 }
12949 }
Chet Haasea1cff502012-02-21 13:43:44 -080012950 }
12951 if (mTransformationInfo != null) {
Chet Haase9420abd2012-03-29 16:28:32 -070012952 alpha *= mTransformationInfo.mAlpha;
12953 if (alpha < 1) {
12954 final int multipliedAlpha = (int) (255 * alpha);
12955 if (onSetAlpha(multipliedAlpha)) {
12956 alpha = 1;
12957 }
12958 }
12959 displayList.setTransformationInfo(alpha,
Chet Haasea1cff502012-02-21 13:43:44 -080012960 mTransformationInfo.mTranslationX, mTransformationInfo.mTranslationY,
12961 mTransformationInfo.mRotation, mTransformationInfo.mRotationX,
12962 mTransformationInfo.mRotationY, mTransformationInfo.mScaleX,
12963 mTransformationInfo.mScaleY);
Chet Haaseb85967b2012-03-26 14:37:51 -070012964 if (mTransformationInfo.mCamera == null) {
12965 mTransformationInfo.mCamera = new Camera();
12966 mTransformationInfo.matrix3D = new Matrix();
12967 }
12968 displayList.setCameraDistance(mTransformationInfo.mCamera.getLocationZ());
Dianne Hackborn4702a852012-08-17 15:18:29 -070012969 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == PFLAG_PIVOT_EXPLICITLY_SET) {
Chet Haasea1cff502012-02-21 13:43:44 -080012970 displayList.setPivotX(getPivotX());
12971 displayList.setPivotY(getPivotY());
12972 }
Chet Haase9420abd2012-03-29 16:28:32 -070012973 } else if (alpha < 1) {
12974 displayList.setAlpha(alpha);
Chet Haasea1cff502012-02-21 13:43:44 -080012975 }
12976 }
12977 }
12978
Chet Haasebcca79a2012-02-14 08:45:14 -080012979 /**
Chet Haase64a48c12012-02-13 16:33:29 -080012980 * This method is called by ViewGroup.drawChild() to have each child view draw itself.
12981 * This draw() method is an implementation detail and is not intended to be overridden or
12982 * to be called from anywhere else other than ViewGroup.drawChild().
12983 */
12984 boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
Chet Haase1271e2c2012-04-20 09:54:27 -070012985 boolean useDisplayListProperties = mAttachInfo != null && mAttachInfo.mHardwareAccelerated;
Chet Haase64a48c12012-02-13 16:33:29 -080012986 boolean more = false;
Chet Haase64a48c12012-02-13 16:33:29 -080012987 final boolean childHasIdentityMatrix = hasIdentityMatrix();
Chet Haase64a48c12012-02-13 16:33:29 -080012988 final int flags = parent.mGroupFlags;
12989
Chet Haasea1cff502012-02-21 13:43:44 -080012990 if ((flags & ViewGroup.FLAG_CLEAR_TRANSFORMATION) == ViewGroup.FLAG_CLEAR_TRANSFORMATION) {
Chet Haase64a48c12012-02-13 16:33:29 -080012991 parent.mChildTransformation.clear();
Chet Haasea1cff502012-02-21 13:43:44 -080012992 parent.mGroupFlags &= ~ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080012993 }
12994
12995 Transformation transformToApply = null;
Chet Haase64a48c12012-02-13 16:33:29 -080012996 boolean concatMatrix = false;
12997
12998 boolean scalingRequired = false;
12999 boolean caching;
Michael Jurkaba649742012-06-28 19:12:58 -070013000 int layerType = getLayerType();
Chet Haase64a48c12012-02-13 16:33:29 -080013001
13002 final boolean hardwareAccelerated = canvas.isHardwareAccelerated();
Chet Haasea1cff502012-02-21 13:43:44 -080013003 if ((flags & ViewGroup.FLAG_CHILDREN_DRAWN_WITH_CACHE) != 0 ||
13004 (flags & ViewGroup.FLAG_ALWAYS_DRAWN_WITH_CACHE) != 0) {
Chet Haase64a48c12012-02-13 16:33:29 -080013005 caching = true;
Chet Haase9420abd2012-03-29 16:28:32 -070013006 // Auto-scaled apps are not hw-accelerated, no need to set scaling flag on DisplayList
Chet Haase64a48c12012-02-13 16:33:29 -080013007 if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
13008 } else {
13009 caching = (layerType != LAYER_TYPE_NONE) || hardwareAccelerated;
13010 }
13011
Chet Haasebcca79a2012-02-14 08:45:14 -080013012 final Animation a = getAnimation();
Chet Haase64a48c12012-02-13 16:33:29 -080013013 if (a != null) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013014 more = drawAnimation(parent, drawingTime, a, scalingRequired);
Chet Haase64a48c12012-02-13 16:33:29 -080013015 concatMatrix = a.willChangeTransformationMatrix();
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013016 if (concatMatrix) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013017 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013018 }
Chet Haasebcca79a2012-02-14 08:45:14 -080013019 transformToApply = parent.mChildTransformation;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013020 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013021 if ((mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_TRANSFORM) == PFLAG3_VIEW_IS_ANIMATING_TRANSFORM &&
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013022 mDisplayList != null) {
13023 // No longer animating: clear out old animation matrix
13024 mDisplayList.setAnimationMatrix(null);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013025 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_TRANSFORM;
Chet Haaseafd5c3e2012-05-10 13:21:10 -070013026 }
13027 if (!useDisplayListProperties &&
13028 (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
13029 final boolean hasTransform =
13030 parent.getChildStaticTransformation(this, parent.mChildTransformation);
13031 if (hasTransform) {
13032 final int transformType = parent.mChildTransformation.getTransformationType();
13033 transformToApply = transformType != Transformation.TYPE_IDENTITY ?
13034 parent.mChildTransformation : null;
13035 concatMatrix = (transformType & Transformation.TYPE_MATRIX) != 0;
13036 }
Chet Haase64a48c12012-02-13 16:33:29 -080013037 }
13038 }
13039
13040 concatMatrix |= !childHasIdentityMatrix;
13041
13042 // Sets the flag as early as possible to allow draw() implementations
13043 // to call invalidate() successfully when doing animations
Dianne Hackborn4702a852012-08-17 15:18:29 -070013044 mPrivateFlags |= PFLAG_DRAWN;
Chet Haase64a48c12012-02-13 16:33:29 -080013045
Chet Haase599913d2012-07-23 16:22:05 -070013046 if (!concatMatrix && (flags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == 0 &&
13047 canvas.quickReject(mLeft, mTop, mRight, mBottom, Canvas.EdgeType.BW) &&
Dianne Hackborn4702a852012-08-17 15:18:29 -070013048 (mPrivateFlags & PFLAG_DRAW_ANIMATION) == 0) {
13049 mPrivateFlags2 |= PFLAG2_VIEW_QUICK_REJECTED;
Chet Haase64a48c12012-02-13 16:33:29 -080013050 return more;
13051 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070013052 mPrivateFlags2 &= ~PFLAG2_VIEW_QUICK_REJECTED;
Chet Haase64a48c12012-02-13 16:33:29 -080013053
13054 if (hardwareAccelerated) {
13055 // Clear INVALIDATED flag to allow invalidation to occur during rendering, but
13056 // retain the flag's value temporarily in the mRecreateDisplayList flag
Dianne Hackborn4702a852012-08-17 15:18:29 -070013057 mRecreateDisplayList = (mPrivateFlags & PFLAG_INVALIDATED) == PFLAG_INVALIDATED;
13058 mPrivateFlags &= ~PFLAG_INVALIDATED;
Chet Haase64a48c12012-02-13 16:33:29 -080013059 }
13060
Chet Haase64a48c12012-02-13 16:33:29 -080013061 DisplayList displayList = null;
13062 Bitmap cache = null;
13063 boolean hasDisplayList = false;
13064 if (caching) {
13065 if (!hardwareAccelerated) {
13066 if (layerType != LAYER_TYPE_NONE) {
13067 layerType = LAYER_TYPE_SOFTWARE;
13068 buildDrawingCache(true);
13069 }
13070 cache = getDrawingCache(true);
13071 } else {
13072 switch (layerType) {
13073 case LAYER_TYPE_SOFTWARE:
Chet Haaseb85967b2012-03-26 14:37:51 -070013074 if (useDisplayListProperties) {
13075 hasDisplayList = canHaveDisplayList();
13076 } else {
13077 buildDrawingCache(true);
13078 cache = getDrawingCache(true);
13079 }
Chet Haase64a48c12012-02-13 16:33:29 -080013080 break;
Chet Haasea1cff502012-02-21 13:43:44 -080013081 case LAYER_TYPE_HARDWARE:
13082 if (useDisplayListProperties) {
13083 hasDisplayList = canHaveDisplayList();
13084 }
13085 break;
Chet Haase64a48c12012-02-13 16:33:29 -080013086 case LAYER_TYPE_NONE:
13087 // Delay getting the display list until animation-driven alpha values are
13088 // set up and possibly passed on to the view
13089 hasDisplayList = canHaveDisplayList();
13090 break;
13091 }
13092 }
13093 }
Chet Haasea1cff502012-02-21 13:43:44 -080013094 useDisplayListProperties &= hasDisplayList;
Chet Haase9420abd2012-03-29 16:28:32 -070013095 if (useDisplayListProperties) {
13096 displayList = getDisplayList();
13097 if (!displayList.isValid()) {
13098 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13099 // to getDisplayList(), the display list will be marked invalid and we should not
13100 // try to use it again.
13101 displayList = null;
13102 hasDisplayList = false;
13103 useDisplayListProperties = false;
13104 }
13105 }
Chet Haase64a48c12012-02-13 16:33:29 -080013106
Chet Haase526057b2012-07-12 17:50:41 -070013107 int sx = 0;
13108 int sy = 0;
13109 if (!hasDisplayList) {
13110 computeScroll();
13111 sx = mScrollX;
13112 sy = mScrollY;
13113 }
13114
Chet Haase64a48c12012-02-13 16:33:29 -080013115 final boolean hasNoCache = cache == null || hasDisplayList;
13116 final boolean offsetForScroll = cache == null && !hasDisplayList &&
13117 layerType != LAYER_TYPE_HARDWARE;
13118
Chet Haasea1cff502012-02-21 13:43:44 -080013119 int restoreTo = -1;
Chet Haase89b7f2e2012-03-21 11:15:37 -070013120 if (!useDisplayListProperties || transformToApply != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013121 restoreTo = canvas.save();
13122 }
Chet Haase64a48c12012-02-13 16:33:29 -080013123 if (offsetForScroll) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013124 canvas.translate(mLeft - sx, mTop - sy);
Chet Haase64a48c12012-02-13 16:33:29 -080013125 } else {
Chet Haasea1cff502012-02-21 13:43:44 -080013126 if (!useDisplayListProperties) {
13127 canvas.translate(mLeft, mTop);
13128 }
Chet Haase64a48c12012-02-13 16:33:29 -080013129 if (scalingRequired) {
Chet Haasea1cff502012-02-21 13:43:44 -080013130 if (useDisplayListProperties) {
Chet Haase9420abd2012-03-29 16:28:32 -070013131 // TODO: Might not need this if we put everything inside the DL
Chet Haasea1cff502012-02-21 13:43:44 -080013132 restoreTo = canvas.save();
13133 }
Chet Haase64a48c12012-02-13 16:33:29 -080013134 // mAttachInfo cannot be null, otherwise scalingRequired == false
13135 final float scale = 1.0f / mAttachInfo.mApplicationScale;
13136 canvas.scale(scale, scale);
13137 }
13138 }
13139
Chet Haasea1cff502012-02-21 13:43:44 -080013140 float alpha = useDisplayListProperties ? 1 : getAlpha();
Chet Haase21433372012-06-05 07:54:09 -070013141 if (transformToApply != null || alpha < 1 || !hasIdentityMatrix() ||
Dianne Hackborn4702a852012-08-17 15:18:29 -070013142 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
Chet Haase64a48c12012-02-13 16:33:29 -080013143 if (transformToApply != null || !childHasIdentityMatrix) {
13144 int transX = 0;
13145 int transY = 0;
13146
13147 if (offsetForScroll) {
13148 transX = -sx;
13149 transY = -sy;
13150 }
13151
13152 if (transformToApply != null) {
13153 if (concatMatrix) {
Chet Haase9420abd2012-03-29 16:28:32 -070013154 if (useDisplayListProperties) {
13155 displayList.setAnimationMatrix(transformToApply.getMatrix());
13156 } else {
13157 // Undo the scroll translation, apply the transformation matrix,
13158 // then redo the scroll translate to get the correct result.
13159 canvas.translate(-transX, -transY);
13160 canvas.concat(transformToApply.getMatrix());
13161 canvas.translate(transX, transY);
13162 }
Chet Haasea1cff502012-02-21 13:43:44 -080013163 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013164 }
13165
13166 float transformAlpha = transformToApply.getAlpha();
Chet Haase9420abd2012-03-29 16:28:32 -070013167 if (transformAlpha < 1) {
Chet Haase21433372012-06-05 07:54:09 -070013168 alpha *= transformAlpha;
Chet Haasea1cff502012-02-21 13:43:44 -080013169 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013170 }
13171 }
13172
Chet Haasea1cff502012-02-21 13:43:44 -080013173 if (!childHasIdentityMatrix && !useDisplayListProperties) {
Chet Haase64a48c12012-02-13 16:33:29 -080013174 canvas.translate(-transX, -transY);
13175 canvas.concat(getMatrix());
13176 canvas.translate(transX, transY);
13177 }
13178 }
13179
Chet Haase21433372012-06-05 07:54:09 -070013180 // Deal with alpha if it is or used to be <1
13181 if (alpha < 1 ||
Dianne Hackborn4702a852012-08-17 15:18:29 -070013182 (mPrivateFlags3 & PFLAG3_VIEW_IS_ANIMATING_ALPHA) == PFLAG3_VIEW_IS_ANIMATING_ALPHA) {
Chet Haase21433372012-06-05 07:54:09 -070013183 if (alpha < 1) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013184 mPrivateFlags3 |= PFLAG3_VIEW_IS_ANIMATING_ALPHA;
Chet Haase21433372012-06-05 07:54:09 -070013185 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013186 mPrivateFlags3 &= ~PFLAG3_VIEW_IS_ANIMATING_ALPHA;
Chet Haase21433372012-06-05 07:54:09 -070013187 }
Chet Haasea1cff502012-02-21 13:43:44 -080013188 parent.mGroupFlags |= ViewGroup.FLAG_CLEAR_TRANSFORMATION;
Chet Haase64a48c12012-02-13 16:33:29 -080013189 if (hasNoCache) {
13190 final int multipliedAlpha = (int) (255 * alpha);
13191 if (!onSetAlpha(multipliedAlpha)) {
13192 int layerFlags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
Chet Haasea1cff502012-02-21 13:43:44 -080013193 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) != 0 ||
Chet Haase64a48c12012-02-13 16:33:29 -080013194 layerType != LAYER_TYPE_NONE) {
13195 layerFlags |= Canvas.CLIP_TO_LAYER_SAVE_FLAG;
13196 }
Chet Haase9420abd2012-03-29 16:28:32 -070013197 if (useDisplayListProperties) {
13198 displayList.setAlpha(alpha * getAlpha());
13199 } else if (layerType == LAYER_TYPE_NONE) {
Chet Haase89b7f2e2012-03-21 11:15:37 -070013200 final int scrollX = hasDisplayList ? 0 : sx;
13201 final int scrollY = hasDisplayList ? 0 : sy;
13202 canvas.saveLayerAlpha(scrollX, scrollY, scrollX + mRight - mLeft,
13203 scrollY + mBottom - mTop, multipliedAlpha, layerFlags);
Chet Haase64a48c12012-02-13 16:33:29 -080013204 }
13205 } else {
13206 // Alpha is handled by the child directly, clobber the layer's alpha
Dianne Hackborn4702a852012-08-17 15:18:29 -070013207 mPrivateFlags |= PFLAG_ALPHA_SET;
Chet Haase64a48c12012-02-13 16:33:29 -080013208 }
13209 }
13210 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070013211 } else if ((mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
Chet Haase64a48c12012-02-13 16:33:29 -080013212 onSetAlpha(255);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013213 mPrivateFlags &= ~PFLAG_ALPHA_SET;
Chet Haase64a48c12012-02-13 16:33:29 -080013214 }
13215
Chet Haasea1cff502012-02-21 13:43:44 -080013216 if ((flags & ViewGroup.FLAG_CLIP_CHILDREN) == ViewGroup.FLAG_CLIP_CHILDREN &&
13217 !useDisplayListProperties) {
Chet Haase64a48c12012-02-13 16:33:29 -080013218 if (offsetForScroll) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013219 canvas.clipRect(sx, sy, sx + (mRight - mLeft), sy + (mBottom - mTop));
Chet Haase64a48c12012-02-13 16:33:29 -080013220 } else {
13221 if (!scalingRequired || cache == null) {
Chet Haasebcca79a2012-02-14 08:45:14 -080013222 canvas.clipRect(0, 0, mRight - mLeft, mBottom - mTop);
Chet Haase64a48c12012-02-13 16:33:29 -080013223 } else {
13224 canvas.clipRect(0, 0, cache.getWidth(), cache.getHeight());
13225 }
13226 }
13227 }
13228
Chet Haase9420abd2012-03-29 16:28:32 -070013229 if (!useDisplayListProperties && hasDisplayList) {
Chet Haase64a48c12012-02-13 16:33:29 -080013230 displayList = getDisplayList();
13231 if (!displayList.isValid()) {
13232 // Uncommon, but possible. If a view is removed from the hierarchy during the call
13233 // to getDisplayList(), the display list will be marked invalid and we should not
13234 // try to use it again.
13235 displayList = null;
13236 hasDisplayList = false;
13237 }
13238 }
13239
13240 if (hasNoCache) {
13241 boolean layerRendered = false;
Chet Haasea1cff502012-02-21 13:43:44 -080013242 if (layerType == LAYER_TYPE_HARDWARE && !useDisplayListProperties) {
Michael Jurka7e52caf2012-03-06 15:57:06 -080013243 final HardwareLayer layer = getHardwareLayer();
Chet Haase64a48c12012-02-13 16:33:29 -080013244 if (layer != null && layer.isValid()) {
13245 mLayerPaint.setAlpha((int) (alpha * 255));
13246 ((HardwareCanvas) canvas).drawHardwareLayer(layer, 0, 0, mLayerPaint);
13247 layerRendered = true;
13248 } else {
13249 final int scrollX = hasDisplayList ? 0 : sx;
13250 final int scrollY = hasDisplayList ? 0 : sy;
13251 canvas.saveLayer(scrollX, scrollY,
Chet Haasebcca79a2012-02-14 08:45:14 -080013252 scrollX + mRight - mLeft, scrollY + mBottom - mTop, mLayerPaint,
Chet Haase64a48c12012-02-13 16:33:29 -080013253 Canvas.HAS_ALPHA_LAYER_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
13254 }
13255 }
13256
13257 if (!layerRendered) {
13258 if (!hasDisplayList) {
13259 // Fast path for layouts with no backgrounds
Dianne Hackborn4702a852012-08-17 15:18:29 -070013260 if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
13261 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haase64a48c12012-02-13 16:33:29 -080013262 dispatchDraw(canvas);
13263 } else {
13264 draw(canvas);
13265 }
13266 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013267 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haase1271e2c2012-04-20 09:54:27 -070013268 ((HardwareCanvas) canvas).drawDisplayList(displayList, null, flags);
Chet Haase64a48c12012-02-13 16:33:29 -080013269 }
13270 }
13271 } else if (cache != null) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013272 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
Chet Haase64a48c12012-02-13 16:33:29 -080013273 Paint cachePaint;
13274
13275 if (layerType == LAYER_TYPE_NONE) {
13276 cachePaint = parent.mCachePaint;
13277 if (cachePaint == null) {
13278 cachePaint = new Paint();
13279 cachePaint.setDither(false);
13280 parent.mCachePaint = cachePaint;
13281 }
Chet Haase9420abd2012-03-29 16:28:32 -070013282 if (alpha < 1) {
Chet Haase64a48c12012-02-13 16:33:29 -080013283 cachePaint.setAlpha((int) (alpha * 255));
Chet Haasea1cff502012-02-21 13:43:44 -080013284 parent.mGroupFlags |= ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
13285 } else if ((flags & ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE) != 0) {
Chet Haase64a48c12012-02-13 16:33:29 -080013286 cachePaint.setAlpha(255);
Chet Haasea1cff502012-02-21 13:43:44 -080013287 parent.mGroupFlags &= ~ViewGroup.FLAG_ALPHA_LOWER_THAN_ONE;
Chet Haase64a48c12012-02-13 16:33:29 -080013288 }
13289 } else {
13290 cachePaint = mLayerPaint;
13291 cachePaint.setAlpha((int) (alpha * 255));
13292 }
13293 canvas.drawBitmap(cache, 0.0f, 0.0f, cachePaint);
13294 }
13295
Chet Haasea1cff502012-02-21 13:43:44 -080013296 if (restoreTo >= 0) {
13297 canvas.restoreToCount(restoreTo);
13298 }
Chet Haase64a48c12012-02-13 16:33:29 -080013299
13300 if (a != null && !more) {
13301 if (!hardwareAccelerated && !a.getFillAfter()) {
13302 onSetAlpha(255);
13303 }
13304 parent.finishAnimatingView(this, a);
13305 }
13306
13307 if (more && hardwareAccelerated) {
13308 // invalidation is the trigger to recreate display lists, so if we're using
13309 // display lists to render, force an invalidate to allow the animation to
13310 // continue drawing another frame
13311 parent.invalidate(true);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013312 if (a.hasAlpha() && (mPrivateFlags & PFLAG_ALPHA_SET) == PFLAG_ALPHA_SET) {
Chet Haase64a48c12012-02-13 16:33:29 -080013313 // alpha animations should cause the child to recreate its display list
13314 invalidate(true);
13315 }
13316 }
13317
13318 mRecreateDisplayList = false;
13319
13320 return more;
13321 }
13322
13323 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013324 * Manually render this view (and all of its children) to the given Canvas.
13325 * The view must have already done a full layout before this function is
Romain Guy5c22a8c2011-05-13 11:48:45 -070013326 * called. When implementing a view, implement
13327 * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
13328 * If you do need to override this method, call the superclass version.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013329 *
13330 * @param canvas The Canvas to which the View is rendered.
13331 */
13332 public void draw(Canvas canvas) {
Romain Guy5bcdff42009-05-14 21:27:18 -070013333 final int privateFlags = mPrivateFlags;
Dianne Hackborn4702a852012-08-17 15:18:29 -070013334 final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&
Romain Guy5bcdff42009-05-14 21:27:18 -070013335 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013336 mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
Romain Guy24443ea2009-05-11 11:56:30 -070013337
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013338 /*
13339 * Draw traversal performs several drawing steps which must be executed
13340 * in the appropriate order:
13341 *
13342 * 1. Draw the background
13343 * 2. If necessary, save the canvas' layers to prepare for fading
13344 * 3. Draw view's content
13345 * 4. Draw children
13346 * 5. If necessary, draw the fading edges and restore layers
13347 * 6. Draw decorations (scrollbars for instance)
13348 */
13349
13350 // Step 1, draw the background, if needed
13351 int saveCount;
13352
Romain Guy24443ea2009-05-11 11:56:30 -070013353 if (!dirtyOpaque) {
Philip Milne6c8ea062012-04-03 17:38:43 -070013354 final Drawable background = mBackground;
Romain Guy24443ea2009-05-11 11:56:30 -070013355 if (background != null) {
13356 final int scrollX = mScrollX;
13357 final int scrollY = mScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013358
Romain Guy24443ea2009-05-11 11:56:30 -070013359 if (mBackgroundSizeChanged) {
13360 background.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
13361 mBackgroundSizeChanged = false;
13362 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013363
Romain Guy24443ea2009-05-11 11:56:30 -070013364 if ((scrollX | scrollY) == 0) {
13365 background.draw(canvas);
13366 } else {
13367 canvas.translate(scrollX, scrollY);
13368 background.draw(canvas);
13369 canvas.translate(-scrollX, -scrollY);
13370 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013371 }
13372 }
13373
13374 // skip step 2 & 5 if possible (common case)
13375 final int viewFlags = mViewFlags;
13376 boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;
13377 boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;
13378 if (!verticalEdges && !horizontalEdges) {
13379 // Step 3, draw the content
Romain Guy24443ea2009-05-11 11:56:30 -070013380 if (!dirtyOpaque) onDraw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013381
13382 // Step 4, draw the children
13383 dispatchDraw(canvas);
13384
13385 // Step 6, draw decorations (scrollbars)
13386 onDrawScrollBars(canvas);
13387
13388 // we're done...
13389 return;
13390 }
13391
13392 /*
13393 * Here we do the full fledged routine...
13394 * (this is an uncommon case where speed matters less,
13395 * this is why we repeat some of the tests that have been
13396 * done above)
13397 */
13398
13399 boolean drawTop = false;
13400 boolean drawBottom = false;
13401 boolean drawLeft = false;
13402 boolean drawRight = false;
13403
13404 float topFadeStrength = 0.0f;
13405 float bottomFadeStrength = 0.0f;
13406 float leftFadeStrength = 0.0f;
13407 float rightFadeStrength = 0.0f;
13408
13409 // Step 2, save the canvas' layers
13410 int paddingLeft = mPaddingLeft;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013411
13412 final boolean offsetRequired = isPaddingOffsetRequired();
13413 if (offsetRequired) {
13414 paddingLeft += getLeftPaddingOffset();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013415 }
13416
13417 int left = mScrollX + paddingLeft;
13418 int right = left + mRight - mLeft - mPaddingRight - paddingLeft;
Romain Guyf2fc4602011-07-19 15:20:03 -070013419 int top = mScrollY + getFadeTop(offsetRequired);
13420 int bottom = top + getFadeHeight(offsetRequired);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013421
13422 if (offsetRequired) {
13423 right += getRightPaddingOffset();
13424 bottom += getBottomPaddingOffset();
13425 }
13426
13427 final ScrollabilityCache scrollabilityCache = mScrollCache;
Philip Milne6c8ea062012-04-03 17:38:43 -070013428 final float fadeHeight = scrollabilityCache.fadingEdgeLength;
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013429 int length = (int) fadeHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013430
13431 // clip the fade length if top and bottom fades overlap
13432 // overlapping fades produce odd-looking artifacts
13433 if (verticalEdges && (top + length > bottom - length)) {
13434 length = (bottom - top) / 2;
13435 }
13436
13437 // also clip horizontal fades if necessary
13438 if (horizontalEdges && (left + length > right - length)) {
13439 length = (right - left) / 2;
13440 }
13441
13442 if (verticalEdges) {
13443 topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013444 drawTop = topFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013445 bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013446 drawBottom = bottomFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013447 }
13448
13449 if (horizontalEdges) {
13450 leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013451 drawLeft = leftFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013452 rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013453 drawRight = rightFadeStrength * fadeHeight > 1.0f;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013454 }
13455
13456 saveCount = canvas.getSaveCount();
13457
13458 int solidColor = getSolidColor();
Romain Guyf607bdc2010-09-10 19:20:06 -070013459 if (solidColor == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013460 final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;
13461
13462 if (drawTop) {
13463 canvas.saveLayer(left, top, right, top + length, null, flags);
13464 }
13465
13466 if (drawBottom) {
13467 canvas.saveLayer(left, bottom - length, right, bottom, null, flags);
13468 }
13469
13470 if (drawLeft) {
13471 canvas.saveLayer(left, top, left + length, bottom, null, flags);
13472 }
13473
13474 if (drawRight) {
13475 canvas.saveLayer(right - length, top, right, bottom, null, flags);
13476 }
13477 } else {
13478 scrollabilityCache.setFadeColor(solidColor);
13479 }
13480
13481 // Step 3, draw the content
Romain Guy24443ea2009-05-11 11:56:30 -070013482 if (!dirtyOpaque) onDraw(canvas);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013483
13484 // Step 4, draw the children
13485 dispatchDraw(canvas);
13486
13487 // Step 5, draw the fade effect and restore layers
13488 final Paint p = scrollabilityCache.paint;
13489 final Matrix matrix = scrollabilityCache.matrix;
13490 final Shader fade = scrollabilityCache.shader;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013491
13492 if (drawTop) {
13493 matrix.setScale(1, fadeHeight * topFadeStrength);
13494 matrix.postTranslate(left, top);
13495 fade.setLocalMatrix(matrix);
13496 canvas.drawRect(left, top, right, top + length, p);
13497 }
13498
13499 if (drawBottom) {
13500 matrix.setScale(1, fadeHeight * bottomFadeStrength);
13501 matrix.postRotate(180);
13502 matrix.postTranslate(left, bottom);
13503 fade.setLocalMatrix(matrix);
13504 canvas.drawRect(left, bottom - length, right, bottom, p);
13505 }
13506
13507 if (drawLeft) {
13508 matrix.setScale(1, fadeHeight * leftFadeStrength);
13509 matrix.postRotate(-90);
13510 matrix.postTranslate(left, top);
13511 fade.setLocalMatrix(matrix);
13512 canvas.drawRect(left, top, left + length, bottom, p);
13513 }
13514
13515 if (drawRight) {
13516 matrix.setScale(1, fadeHeight * rightFadeStrength);
13517 matrix.postRotate(90);
13518 matrix.postTranslate(right, top);
13519 fade.setLocalMatrix(matrix);
13520 canvas.drawRect(right - length, top, right, bottom, p);
13521 }
13522
13523 canvas.restoreToCount(saveCount);
13524
13525 // Step 6, draw decorations (scrollbars)
13526 onDrawScrollBars(canvas);
13527 }
13528
13529 /**
13530 * Override this if your view is known to always be drawn on top of a solid color background,
13531 * and needs to draw fading edges. Returning a non-zero color enables the view system to
13532 * optimize the drawing of the fading edges. If you do return a non-zero color, the alpha
13533 * should be set to 0xFF.
13534 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013535 * @see #setVerticalFadingEdgeEnabled(boolean)
13536 * @see #setHorizontalFadingEdgeEnabled(boolean)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013537 *
13538 * @return The known solid color background for this view, or 0 if the color may vary
13539 */
Romain Guy7b5b6ab2011-03-14 18:05:08 -070013540 @ViewDebug.ExportedProperty(category = "drawing")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013541 public int getSolidColor() {
13542 return 0;
13543 }
13544
13545 /**
13546 * Build a human readable string representation of the specified view flags.
13547 *
13548 * @param flags the view flags to convert to a string
13549 * @return a String representing the supplied flags
13550 */
13551 private static String printFlags(int flags) {
13552 String output = "";
13553 int numFlags = 0;
13554 if ((flags & FOCUSABLE_MASK) == FOCUSABLE) {
13555 output += "TAKES_FOCUS";
13556 numFlags++;
13557 }
13558
13559 switch (flags & VISIBILITY_MASK) {
13560 case INVISIBLE:
13561 if (numFlags > 0) {
13562 output += " ";
13563 }
13564 output += "INVISIBLE";
13565 // USELESS HERE numFlags++;
13566 break;
13567 case GONE:
13568 if (numFlags > 0) {
13569 output += " ";
13570 }
13571 output += "GONE";
13572 // USELESS HERE numFlags++;
13573 break;
13574 default:
13575 break;
13576 }
13577 return output;
13578 }
13579
13580 /**
13581 * Build a human readable string representation of the specified private
13582 * view flags.
13583 *
13584 * @param privateFlags the private view flags to convert to a string
13585 * @return a String representing the supplied flags
13586 */
13587 private static String printPrivateFlags(int privateFlags) {
13588 String output = "";
13589 int numFlags = 0;
13590
Dianne Hackborn4702a852012-08-17 15:18:29 -070013591 if ((privateFlags & PFLAG_WANTS_FOCUS) == PFLAG_WANTS_FOCUS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013592 output += "WANTS_FOCUS";
13593 numFlags++;
13594 }
13595
Dianne Hackborn4702a852012-08-17 15:18:29 -070013596 if ((privateFlags & PFLAG_FOCUSED) == PFLAG_FOCUSED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013597 if (numFlags > 0) {
13598 output += " ";
13599 }
13600 output += "FOCUSED";
13601 numFlags++;
13602 }
13603
Dianne Hackborn4702a852012-08-17 15:18:29 -070013604 if ((privateFlags & PFLAG_SELECTED) == PFLAG_SELECTED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013605 if (numFlags > 0) {
13606 output += " ";
13607 }
13608 output += "SELECTED";
13609 numFlags++;
13610 }
13611
Dianne Hackborn4702a852012-08-17 15:18:29 -070013612 if ((privateFlags & PFLAG_IS_ROOT_NAMESPACE) == PFLAG_IS_ROOT_NAMESPACE) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013613 if (numFlags > 0) {
13614 output += " ";
13615 }
13616 output += "IS_ROOT_NAMESPACE";
13617 numFlags++;
13618 }
13619
Dianne Hackborn4702a852012-08-17 15:18:29 -070013620 if ((privateFlags & PFLAG_HAS_BOUNDS) == PFLAG_HAS_BOUNDS) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013621 if (numFlags > 0) {
13622 output += " ";
13623 }
13624 output += "HAS_BOUNDS";
13625 numFlags++;
13626 }
13627
Dianne Hackborn4702a852012-08-17 15:18:29 -070013628 if ((privateFlags & PFLAG_DRAWN) == PFLAG_DRAWN) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013629 if (numFlags > 0) {
13630 output += " ";
13631 }
13632 output += "DRAWN";
13633 // USELESS HERE numFlags++;
13634 }
13635 return output;
13636 }
13637
13638 /**
13639 * <p>Indicates whether or not this view's layout will be requested during
13640 * the next hierarchy layout pass.</p>
13641 *
13642 * @return true if the layout will be forced during next layout pass
13643 */
13644 public boolean isLayoutRequested() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013645 return (mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013646 }
13647
13648 /**
13649 * Assign a size and position to a view and all of its
13650 * descendants
13651 *
13652 * <p>This is the second phase of the layout mechanism.
13653 * (The first is measuring). In this phase, each parent calls
13654 * layout on all of its children to position them.
13655 * This is typically done using the child measurements
Chet Haase9c087442011-01-12 16:20:16 -080013656 * that were stored in the measure pass().</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013657 *
Chet Haase9c087442011-01-12 16:20:16 -080013658 * <p>Derived classes should not override this method.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013659 * Derived classes with children should override
13660 * onLayout. In that method, they should
Chet Haase9c087442011-01-12 16:20:16 -080013661 * call layout on each of their children.</p>
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013662 *
13663 * @param l Left position, relative to parent
13664 * @param t Top position, relative to parent
13665 * @param r Right position, relative to parent
13666 * @param b Bottom position, relative to parent
13667 */
Romain Guy5429e1d2010-09-07 12:38:00 -070013668 @SuppressWarnings({"unchecked"})
Chet Haase9c087442011-01-12 16:20:16 -080013669 public void layout(int l, int t, int r, int b) {
Chet Haase21cd1382010-09-01 17:42:29 -070013670 int oldL = mLeft;
13671 int oldT = mTop;
13672 int oldB = mBottom;
13673 int oldR = mRight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013674 boolean changed = setFrame(l, t, r, b);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013675 if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013676 onLayout(changed, l, t, r, b);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013677 mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
Chet Haase21cd1382010-09-01 17:42:29 -070013678
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070013679 ListenerInfo li = mListenerInfo;
13680 if (li != null && li.mOnLayoutChangeListeners != null) {
Chet Haase21cd1382010-09-01 17:42:29 -070013681 ArrayList<OnLayoutChangeListener> listenersCopy =
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070013682 (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
Chet Haase21cd1382010-09-01 17:42:29 -070013683 int numListeners = listenersCopy.size();
13684 for (int i = 0; i < numListeners; ++i) {
Chet Haase7c608f22010-10-22 17:54:04 -070013685 listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
Chet Haase21cd1382010-09-01 17:42:29 -070013686 }
13687 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013688 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070013689 mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013690 }
13691
13692 /**
13693 * Called from layout when this view should
13694 * assign a size and position to each of its children.
13695 *
13696 * Derived classes with children should override
13697 * this method and call layout on each of
Chet Haase21cd1382010-09-01 17:42:29 -070013698 * their children.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013699 * @param changed This is a new size or position for this view
13700 * @param left Left position, relative to parent
13701 * @param top Top position, relative to parent
13702 * @param right Right position, relative to parent
13703 * @param bottom Bottom position, relative to parent
13704 */
13705 protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
13706 }
13707
13708 /**
13709 * Assign a size and position to this view.
13710 *
13711 * This is called from layout.
13712 *
13713 * @param left Left position, relative to parent
13714 * @param top Top position, relative to parent
13715 * @param right Right position, relative to parent
13716 * @param bottom Bottom position, relative to parent
13717 * @return true if the new size and position are different than the
13718 * previous ones
13719 * {@hide}
13720 */
13721 protected boolean setFrame(int left, int top, int right, int bottom) {
13722 boolean changed = false;
13723
13724 if (DBG) {
Mitsuru Oshima64f59342009-06-21 00:03:11 -070013725 Log.d("View", this + " View.setFrame(" + left + "," + top + ","
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013726 + right + "," + bottom + ")");
13727 }
13728
13729 if (mLeft != left || mRight != right || mTop != top || mBottom != bottom) {
13730 changed = true;
13731
13732 // Remember our drawn bit
Dianne Hackborn4702a852012-08-17 15:18:29 -070013733 int drawn = mPrivateFlags & PFLAG_DRAWN;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013734
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013735 int oldWidth = mRight - mLeft;
13736 int oldHeight = mBottom - mTop;
Chet Haase75755e22011-07-18 17:48:25 -070013737 int newWidth = right - left;
13738 int newHeight = bottom - top;
13739 boolean sizeChanged = (newWidth != oldWidth) || (newHeight != oldHeight);
13740
13741 // Invalidate our old position
13742 invalidate(sizeChanged);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013743
13744 mLeft = left;
13745 mTop = top;
13746 mRight = right;
13747 mBottom = bottom;
Chet Haase1271e2c2012-04-20 09:54:27 -070013748 if (mDisplayList != null) {
Chet Haasea1cff502012-02-21 13:43:44 -080013749 mDisplayList.setLeftTopRightBottom(mLeft, mTop, mRight, mBottom);
13750 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013751
Dianne Hackborn4702a852012-08-17 15:18:29 -070013752 mPrivateFlags |= PFLAG_HAS_BOUNDS;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013753
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013754
Chet Haase75755e22011-07-18 17:48:25 -070013755 if (sizeChanged) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013756 if ((mPrivateFlags & PFLAG_PIVOT_EXPLICITLY_SET) == 0) {
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013757 // A change in dimension means an auto-centered pivot point changes, too
Dianne Hackbornddb715b2011-09-09 14:43:39 -070013758 if (mTransformationInfo != null) {
13759 mTransformationInfo.mMatrixDirty = true;
13760 }
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013761 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013762 onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
13763 }
13764
13765 if ((mViewFlags & VISIBILITY_MASK) == VISIBLE) {
13766 // If we are visible, force the DRAWN bit to on so that
13767 // this invalidate will go through (at least to our parent).
13768 // This is because someone may have invalidated this view
Chet Haase6c7ad5d2010-12-28 08:40:00 -080013769 // before this call to setFrame came in, thereby clearing
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013770 // the DRAWN bit.
Dianne Hackborn4702a852012-08-17 15:18:29 -070013771 mPrivateFlags |= PFLAG_DRAWN;
Chet Haase75755e22011-07-18 17:48:25 -070013772 invalidate(sizeChanged);
Chet Haasef28595e2011-01-31 18:52:12 -080013773 // parent display list may need to be recreated based on a change in the bounds
13774 // of any child
13775 invalidateParentCaches();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013776 }
13777
13778 // Reset drawn bit to original value (invalidate turns it off)
13779 mPrivateFlags |= drawn;
13780
13781 mBackgroundSizeChanged = true;
13782 }
13783 return changed;
13784 }
13785
13786 /**
13787 * Finalize inflating a view from XML. This is called as the last phase
13788 * of inflation, after all child views have been added.
13789 *
13790 * <p>Even if the subclass overrides onFinishInflate, they should always be
13791 * sure to call the super method, so that we get called.
13792 */
13793 protected void onFinishInflate() {
13794 }
13795
13796 /**
13797 * Returns the resources associated with this view.
13798 *
13799 * @return Resources object.
13800 */
13801 public Resources getResources() {
13802 return mResources;
13803 }
13804
13805 /**
13806 * Invalidates the specified Drawable.
13807 *
13808 * @param drawable the drawable to invalidate
13809 */
13810 public void invalidateDrawable(Drawable drawable) {
13811 if (verifyDrawable(drawable)) {
13812 final Rect dirty = drawable.getBounds();
13813 final int scrollX = mScrollX;
13814 final int scrollY = mScrollY;
13815
13816 invalidate(dirty.left + scrollX, dirty.top + scrollY,
13817 dirty.right + scrollX, dirty.bottom + scrollY);
13818 }
13819 }
13820
13821 /**
13822 * Schedules an action on a drawable to occur at a specified time.
13823 *
13824 * @param who the recipient of the action
13825 * @param what the action to run on the drawable
13826 * @param when the time at which the action must occur. Uses the
13827 * {@link SystemClock#uptimeMillis} timebase.
13828 */
13829 public void scheduleDrawable(Drawable who, Runnable what, long when) {
Adam Powell37419d72011-11-10 11:32:09 -080013830 if (verifyDrawable(who) && what != null) {
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080013831 final long delay = when - SystemClock.uptimeMillis();
Adam Powell37419d72011-11-10 11:32:09 -080013832 if (mAttachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013833 mAttachInfo.mViewRootImpl.mChoreographer.postCallbackDelayed(
13834 Choreographer.CALLBACK_ANIMATION, what, who,
13835 Choreographer.subtractFrameDelay(delay));
Adam Powell37419d72011-11-10 11:32:09 -080013836 } else {
Jeff Brown7ae9d5f2012-03-05 19:33:49 -080013837 ViewRootImpl.getRunQueue().postDelayed(what, delay);
Adam Powell37419d72011-11-10 11:32:09 -080013838 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013839 }
13840 }
13841
13842 /**
13843 * Cancels a scheduled action on a drawable.
13844 *
13845 * @param who the recipient of the action
13846 * @param what the action to cancel
13847 */
13848 public void unscheduleDrawable(Drawable who, Runnable what) {
Adam Powell37419d72011-11-10 11:32:09 -080013849 if (verifyDrawable(who) && what != null) {
13850 if (mAttachInfo != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013851 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13852 Choreographer.CALLBACK_ANIMATION, what, who);
Adam Powell37419d72011-11-10 11:32:09 -080013853 } else {
13854 ViewRootImpl.getRunQueue().removeCallbacks(what);
13855 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013856 }
13857 }
13858
13859 /**
13860 * Unschedule any events associated with the given Drawable. This can be
13861 * used when selecting a new Drawable into a view, so that the previous
13862 * one is completely unscheduled.
13863 *
13864 * @param who The Drawable to unschedule.
13865 *
13866 * @see #drawableStateChanged
13867 */
13868 public void unscheduleDrawable(Drawable who) {
Jeff Brown43ea54b2012-03-09 14:37:48 -080013869 if (mAttachInfo != null && who != null) {
Jeff Brownebb2d8d2012-03-23 17:14:34 -070013870 mAttachInfo.mViewRootImpl.mChoreographer.removeCallbacks(
13871 Choreographer.CALLBACK_ANIMATION, null, who);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013872 }
13873 }
13874
Fabrice Di Meglioc0053222011-06-13 12:16:51 -070013875 /**
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070013876 * Resolve the Drawables depending on the layout direction. This is implicitly supposing
13877 * that the View directionality can and will be resolved before its Drawables.
13878 *
13879 * Will call {@link View#onResolveDrawables} when resolution is done.
13880 */
13881 public void resolveDrawables() {
13882 if (mBackground != null) {
13883 mBackground.setLayoutDirection(getResolvedLayoutDirection());
13884 }
13885 onResolveDrawables(getResolvedLayoutDirection());
13886 }
13887
13888 /**
13889 * Called when layout direction has been resolved.
13890 *
13891 * The default implementation does nothing.
13892 *
13893 * @param layoutDirection The resolved layout direction.
13894 *
13895 * @see {@link #LAYOUT_DIRECTION_LTR}
13896 * @see {@link #LAYOUT_DIRECTION_RTL}
13897 */
13898 public void onResolveDrawables(int layoutDirection) {
Fabrice Di Meglio6a036402011-05-23 14:43:23 -070013899 }
13900
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013901 /**
13902 * If your view subclass is displaying its own Drawable objects, it should
13903 * override this function and return true for any Drawable it is
13904 * displaying. This allows animations for those drawables to be
13905 * scheduled.
13906 *
13907 * <p>Be sure to call through to the super class when overriding this
13908 * function.
13909 *
13910 * @param who The Drawable to verify. Return true if it is one you are
13911 * displaying, else return the result of calling through to the
13912 * super class.
13913 *
13914 * @return boolean If true than the Drawable is being displayed in the
13915 * view; else false and it is not allowed to animate.
13916 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013917 * @see #unscheduleDrawable(android.graphics.drawable.Drawable)
13918 * @see #drawableStateChanged()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013919 */
13920 protected boolean verifyDrawable(Drawable who) {
Philip Milne6c8ea062012-04-03 17:38:43 -070013921 return who == mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013922 }
13923
13924 /**
13925 * This function is called whenever the state of the view changes in such
13926 * a way that it impacts the state of drawables being shown.
13927 *
13928 * <p>Be sure to call through to the superclass when overriding this
13929 * function.
13930 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013931 * @see Drawable#setState(int[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013932 */
13933 protected void drawableStateChanged() {
Philip Milne6c8ea062012-04-03 17:38:43 -070013934 Drawable d = mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013935 if (d != null && d.isStateful()) {
13936 d.setState(getDrawableState());
13937 }
13938 }
13939
13940 /**
13941 * Call this to force a view to update its drawable state. This will cause
13942 * drawableStateChanged to be called on this view. Views that are interested
13943 * in the new state should call getDrawableState.
13944 *
13945 * @see #drawableStateChanged
13946 * @see #getDrawableState
13947 */
13948 public void refreshDrawableState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013949 mPrivateFlags |= PFLAG_DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013950 drawableStateChanged();
13951
13952 ViewParent parent = mParent;
13953 if (parent != null) {
13954 parent.childDrawableStateChanged(this);
13955 }
13956 }
13957
13958 /**
13959 * Return an array of resource IDs of the drawable states representing the
13960 * current state of the view.
13961 *
13962 * @return The current drawable state
13963 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013964 * @see Drawable#setState(int[])
13965 * @see #drawableStateChanged()
13966 * @see #onCreateDrawableState(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013967 */
13968 public final int[] getDrawableState() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070013969 if ((mDrawableState != null) && ((mPrivateFlags & PFLAG_DRAWABLE_STATE_DIRTY) == 0)) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013970 return mDrawableState;
13971 } else {
13972 mDrawableState = onCreateDrawableState(0);
Dianne Hackborn4702a852012-08-17 15:18:29 -070013973 mPrivateFlags &= ~PFLAG_DRAWABLE_STATE_DIRTY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013974 return mDrawableState;
13975 }
13976 }
13977
13978 /**
13979 * Generate the new {@link android.graphics.drawable.Drawable} state for
13980 * this view. This is called by the view
13981 * system when the cached Drawable state is determined to be invalid. To
13982 * retrieve the current state, you should use {@link #getDrawableState}.
13983 *
13984 * @param extraSpace if non-zero, this is the number of extra entries you
13985 * would like in the returned array in which you can place your own
13986 * states.
13987 *
13988 * @return Returns an array holding the current {@link Drawable} state of
13989 * the view.
13990 *
Philip Milne6c8ea062012-04-03 17:38:43 -070013991 * @see #mergeDrawableStates(int[], int[])
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080013992 */
13993 protected int[] onCreateDrawableState(int extraSpace) {
13994 if ((mViewFlags & DUPLICATE_PARENT_STATE) == DUPLICATE_PARENT_STATE &&
13995 mParent instanceof View) {
13996 return ((View) mParent).onCreateDrawableState(extraSpace);
13997 }
13998
13999 int[] drawableState;
14000
14001 int privateFlags = mPrivateFlags;
14002
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014003 int viewStateIndex = 0;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014004 if ((privateFlags & PFLAG_PRESSED) != 0) viewStateIndex |= VIEW_STATE_PRESSED;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014005 if ((mViewFlags & ENABLED_MASK) == ENABLED) viewStateIndex |= VIEW_STATE_ENABLED;
14006 if (isFocused()) viewStateIndex |= VIEW_STATE_FOCUSED;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014007 if ((privateFlags & PFLAG_SELECTED) != 0) viewStateIndex |= VIEW_STATE_SELECTED;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014008 if (hasWindowFocus()) viewStateIndex |= VIEW_STATE_WINDOW_FOCUSED;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014009 if ((privateFlags & PFLAG_ACTIVATED) != 0) viewStateIndex |= VIEW_STATE_ACTIVATED;
Adam Powell5a7e94e2011-04-25 15:30:43 -070014010 if (mAttachInfo != null && mAttachInfo.mHardwareAccelerationRequested &&
14011 HardwareRenderer.isAvailable()) {
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080014012 // This is set if HW acceleration is requested, even if the current
14013 // process doesn't allow it. This is just to allow app preview
14014 // windows to better match their app.
14015 viewStateIndex |= VIEW_STATE_ACCELERATED;
14016 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070014017 if ((privateFlags & PFLAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_HOVERED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014018
Christopher Tate3d4bf172011-03-28 16:16:46 -070014019 final int privateFlags2 = mPrivateFlags2;
Dianne Hackborn4702a852012-08-17 15:18:29 -070014020 if ((privateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0) viewStateIndex |= VIEW_STATE_DRAG_CAN_ACCEPT;
14021 if ((privateFlags2 & PFLAG2_DRAG_HOVERED) != 0) viewStateIndex |= VIEW_STATE_DRAG_HOVERED;
Christopher Tate3d4bf172011-03-28 16:16:46 -070014022
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014023 drawableState = VIEW_STATE_SETS[viewStateIndex];
14024
14025 //noinspection ConstantIfStatement
14026 if (false) {
14027 Log.i("View", "drawableStateIndex=" + viewStateIndex);
14028 Log.i("View", toString()
Dianne Hackborn4702a852012-08-17 15:18:29 -070014029 + " pressed=" + ((privateFlags & PFLAG_PRESSED) != 0)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014030 + " en=" + ((mViewFlags & ENABLED_MASK) == ENABLED)
14031 + " fo=" + hasFocus()
Dianne Hackborn4702a852012-08-17 15:18:29 -070014032 + " sl=" + ((privateFlags & PFLAG_SELECTED) != 0)
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014033 + " wf=" + hasWindowFocus()
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014034 + ": " + Arrays.toString(drawableState));
14035 }
14036
14037 if (extraSpace == 0) {
14038 return drawableState;
14039 }
14040
14041 final int[] fullState;
14042 if (drawableState != null) {
14043 fullState = new int[drawableState.length + extraSpace];
14044 System.arraycopy(drawableState, 0, fullState, 0, drawableState.length);
14045 } else {
14046 fullState = new int[extraSpace];
14047 }
14048
14049 return fullState;
14050 }
14051
14052 /**
14053 * Merge your own state values in <var>additionalState</var> into the base
14054 * state values <var>baseState</var> that were returned by
Romain Guy5c22a8c2011-05-13 11:48:45 -070014055 * {@link #onCreateDrawableState(int)}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014056 *
14057 * @param baseState The base state values returned by
Romain Guy5c22a8c2011-05-13 11:48:45 -070014058 * {@link #onCreateDrawableState(int)}, which will be modified to also hold your
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014059 * own additional state values.
14060 *
14061 * @param additionalState The additional state values you would like
14062 * added to <var>baseState</var>; this array is not modified.
14063 *
14064 * @return As a convenience, the <var>baseState</var> array you originally
14065 * passed into the function is returned.
14066 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014067 * @see #onCreateDrawableState(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014068 */
14069 protected static int[] mergeDrawableStates(int[] baseState, int[] additionalState) {
14070 final int N = baseState.length;
14071 int i = N - 1;
14072 while (i >= 0 && baseState[i] == 0) {
14073 i--;
14074 }
14075 System.arraycopy(additionalState, 0, baseState, i + 1, additionalState.length);
14076 return baseState;
14077 }
14078
14079 /**
Dianne Hackborn079e2352010-10-18 17:02:43 -070014080 * Call {@link Drawable#jumpToCurrentState() Drawable.jumpToCurrentState()}
14081 * on all Drawable objects associated with this view.
14082 */
14083 public void jumpDrawablesToCurrentState() {
Philip Milne6c8ea062012-04-03 17:38:43 -070014084 if (mBackground != null) {
14085 mBackground.jumpToCurrentState();
Dianne Hackborn079e2352010-10-18 17:02:43 -070014086 }
14087 }
14088
14089 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014090 * Sets the background color for this view.
14091 * @param color the color of the background
14092 */
Bjorn Bringert8354fa62010-02-24 23:54:29 +000014093 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014094 public void setBackgroundColor(int color) {
Philip Milne6c8ea062012-04-03 17:38:43 -070014095 if (mBackground instanceof ColorDrawable) {
14096 ((ColorDrawable) mBackground).setColor(color);
Romain Guy7d3082a2012-07-11 17:52:54 -070014097 computeOpaqueFlags();
Chet Haase70d4ba12010-10-06 09:46:45 -070014098 } else {
Philip Milne6c8ea062012-04-03 17:38:43 -070014099 setBackground(new ColorDrawable(color));
Chet Haase70d4ba12010-10-06 09:46:45 -070014100 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014101 }
14102
14103 /**
14104 * Set the background to a given resource. The resource should refer to
Wink Saville7cd88e12009-08-04 14:45:10 -070014105 * a Drawable object or 0 to remove the background.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014106 * @param resid The identifier of the resource.
Philip Milne6c8ea062012-04-03 17:38:43 -070014107 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014108 * @attr ref android.R.styleable#View_background
14109 */
Bjorn Bringert8354fa62010-02-24 23:54:29 +000014110 @RemotableViewMethod
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014111 public void setBackgroundResource(int resid) {
14112 if (resid != 0 && resid == mBackgroundResource) {
14113 return;
14114 }
14115
14116 Drawable d= null;
14117 if (resid != 0) {
14118 d = mResources.getDrawable(resid);
14119 }
Philip Milne6c8ea062012-04-03 17:38:43 -070014120 setBackground(d);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014121
14122 mBackgroundResource = resid;
14123 }
14124
14125 /**
14126 * Set the background to a given Drawable, or remove the background. If the
14127 * background has padding, this View's padding is set to the background's
14128 * padding. However, when a background is removed, this View's padding isn't
14129 * touched. If setting the padding is desired, please use
14130 * {@link #setPadding(int, int, int, int)}.
14131 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014132 * @param background The Drawable to use as the background, or null to remove the
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014133 * background
14134 */
Philip Milne6c8ea062012-04-03 17:38:43 -070014135 public void setBackground(Drawable background) {
Romain Guyeb378892012-04-12 11:33:14 -070014136 //noinspection deprecation
Philip Milne6c8ea062012-04-03 17:38:43 -070014137 setBackgroundDrawable(background);
14138 }
14139
14140 /**
14141 * @deprecated use {@link #setBackground(Drawable)} instead
14142 */
14143 @Deprecated
14144 public void setBackgroundDrawable(Drawable background) {
Romain Guy846a5332012-07-11 17:44:57 -070014145 computeOpaqueFlags();
14146
Philip Milne6c8ea062012-04-03 17:38:43 -070014147 if (background == mBackground) {
Adam Powell4d36ec12011-07-17 16:44:16 -070014148 return;
14149 }
14150
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014151 boolean requestLayout = false;
14152
14153 mBackgroundResource = 0;
14154
14155 /*
14156 * Regardless of whether we're setting a new background or not, we want
14157 * to clear the previous drawable.
14158 */
Philip Milne6c8ea062012-04-03 17:38:43 -070014159 if (mBackground != null) {
14160 mBackground.setCallback(null);
14161 unscheduleDrawable(mBackground);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014162 }
14163
Philip Milne6c8ea062012-04-03 17:38:43 -070014164 if (background != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014165 Rect padding = sThreadLocal.get();
14166 if (padding == null) {
14167 padding = new Rect();
14168 sThreadLocal.set(padding);
14169 }
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070014170 background.setLayoutDirection(getResolvedLayoutDirection());
Philip Milne6c8ea062012-04-03 17:38:43 -070014171 if (background.getPadding(padding)) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014172 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070014173 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Megliob03b4342012-06-04 12:55:30 -070014174 switch (background.getLayoutDirection()) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014175 case LAYOUT_DIRECTION_RTL:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014176 internalSetPadding(padding.right, padding.top, padding.left, padding.bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014177 break;
14178 case LAYOUT_DIRECTION_LTR:
14179 default:
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014180 internalSetPadding(padding.left, padding.top, padding.right, padding.bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014181 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014182 }
14183
14184 // Compare the minimum sizes of the old Drawable and the new. If there isn't an old or
14185 // if it has a different minimum size, we should layout again
Philip Milne6c8ea062012-04-03 17:38:43 -070014186 if (mBackground == null || mBackground.getMinimumHeight() != background.getMinimumHeight() ||
14187 mBackground.getMinimumWidth() != background.getMinimumWidth()) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014188 requestLayout = true;
14189 }
14190
Philip Milne6c8ea062012-04-03 17:38:43 -070014191 background.setCallback(this);
14192 if (background.isStateful()) {
14193 background.setState(getDrawableState());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014194 }
Philip Milne6c8ea062012-04-03 17:38:43 -070014195 background.setVisible(getVisibility() == VISIBLE, false);
14196 mBackground = background;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014197
Dianne Hackborn4702a852012-08-17 15:18:29 -070014198 if ((mPrivateFlags & PFLAG_SKIP_DRAW) != 0) {
14199 mPrivateFlags &= ~PFLAG_SKIP_DRAW;
14200 mPrivateFlags |= PFLAG_ONLY_DRAWS_BACKGROUND;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014201 requestLayout = true;
14202 }
14203 } else {
14204 /* Remove the background */
Philip Milne6c8ea062012-04-03 17:38:43 -070014205 mBackground = null;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014206
Dianne Hackborn4702a852012-08-17 15:18:29 -070014207 if ((mPrivateFlags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014208 /*
14209 * This view ONLY drew the background before and we're removing
14210 * the background, so now it won't draw anything
14211 * (hence we SKIP_DRAW)
14212 */
Dianne Hackborn4702a852012-08-17 15:18:29 -070014213 mPrivateFlags &= ~PFLAG_ONLY_DRAWS_BACKGROUND;
14214 mPrivateFlags |= PFLAG_SKIP_DRAW;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014215 }
14216
14217 /*
14218 * When the background is set, we try to apply its padding to this
14219 * View. When the background is removed, we don't touch this View's
14220 * padding. This is noted in the Javadocs. Hence, we don't need to
14221 * requestLayout(), the invalidate() below is sufficient.
14222 */
14223
14224 // The old background's minimum size could have affected this
14225 // View's layout, so let's requestLayout
14226 requestLayout = true;
14227 }
14228
Romain Guy8f1344f52009-05-15 16:03:59 -070014229 computeOpaqueFlags();
14230
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014231 if (requestLayout) {
14232 requestLayout();
14233 }
14234
14235 mBackgroundSizeChanged = true;
Romain Guy0fd89bf2011-01-26 15:41:30 -080014236 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014237 }
14238
14239 /**
14240 * Gets the background drawable
Philip Milne6c8ea062012-04-03 17:38:43 -070014241 *
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014242 * @return The drawable used as the background for this view, if any.
Philip Milne6c8ea062012-04-03 17:38:43 -070014243 *
14244 * @see #setBackground(Drawable)
14245 *
14246 * @attr ref android.R.styleable#View_background
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014247 */
14248 public Drawable getBackground() {
Philip Milne6c8ea062012-04-03 17:38:43 -070014249 return mBackground;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014250 }
14251
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014252 /**
14253 * Sets the padding. The view may add on the space required to display
14254 * the scrollbars, depending on the style and visibility of the scrollbars.
14255 * So the values returned from {@link #getPaddingLeft}, {@link #getPaddingTop},
14256 * {@link #getPaddingRight} and {@link #getPaddingBottom} may be different
14257 * from the values set in this call.
14258 *
14259 * @attr ref android.R.styleable#View_padding
14260 * @attr ref android.R.styleable#View_paddingBottom
14261 * @attr ref android.R.styleable#View_paddingLeft
14262 * @attr ref android.R.styleable#View_paddingRight
14263 * @attr ref android.R.styleable#View_paddingTop
14264 * @param left the left padding in pixels
14265 * @param top the top padding in pixels
14266 * @param right the right padding in pixels
14267 * @param bottom the bottom padding in pixels
14268 */
14269 public void setPadding(int left, int top, int right, int bottom) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014270 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070014271 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014272
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014273 mUserPaddingStart = UNDEFINED_PADDING;
14274 mUserPaddingEnd = UNDEFINED_PADDING;
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014275
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014276 internalSetPadding(left, top, right, bottom);
14277 }
14278
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014279 /**
14280 * @hide
14281 */
14282 protected void internalSetPadding(int left, int top, int right, int bottom) {
Adam Powell20232d02010-12-08 21:08:53 -080014283 mUserPaddingLeft = left;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014284 mUserPaddingRight = right;
14285 mUserPaddingBottom = bottom;
14286
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014287 final int viewFlags = mViewFlags;
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014288 boolean changed = false;
Romain Guy8506ab42009-06-11 17:35:47 -070014289
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014290 // Common case is there are no scroll bars.
14291 if ((viewFlags & (SCROLLBARS_VERTICAL|SCROLLBARS_HORIZONTAL)) != 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014292 if ((viewFlags & SCROLLBARS_VERTICAL) != 0) {
Adam Powell20232d02010-12-08 21:08:53 -080014293 final int offset = (viewFlags & SCROLLBARS_INSET_MASK) == 0
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014294 ? 0 : getVerticalScrollbarWidth();
Adam Powell20232d02010-12-08 21:08:53 -080014295 switch (mVerticalScrollbarPosition) {
14296 case SCROLLBAR_POSITION_DEFAULT:
Fabrice Di Meglioc91b6ca2012-06-22 14:51:15 -070014297 if (isLayoutRtl()) {
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014298 left += offset;
14299 } else {
14300 right += offset;
14301 }
14302 break;
Adam Powell20232d02010-12-08 21:08:53 -080014303 case SCROLLBAR_POSITION_RIGHT:
14304 right += offset;
14305 break;
14306 case SCROLLBAR_POSITION_LEFT:
14307 left += offset;
14308 break;
14309 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014310 }
Adam Powell20232d02010-12-08 21:08:53 -080014311 if ((viewFlags & SCROLLBARS_HORIZONTAL) != 0) {
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014312 bottom += (viewFlags & SCROLLBARS_INSET_MASK) == 0
14313 ? 0 : getHorizontalScrollbarHeight();
14314 }
14315 }
Romain Guy8506ab42009-06-11 17:35:47 -070014316
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014317 if (mPaddingLeft != left) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014318 changed = true;
14319 mPaddingLeft = left;
14320 }
14321 if (mPaddingTop != top) {
14322 changed = true;
14323 mPaddingTop = top;
14324 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014325 if (mPaddingRight != right) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014326 changed = true;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014327 mPaddingRight = right;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014328 }
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014329 if (mPaddingBottom != bottom) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014330 changed = true;
The Android Open Source Projectb2a3dd82009-03-09 11:52:12 -070014331 mPaddingBottom = bottom;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014332 }
14333
14334 if (changed) {
14335 requestLayout();
14336 }
14337 }
14338
14339 /**
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014340 * Sets the relative padding. The view may add on the space required to display
14341 * the scrollbars, depending on the style and visibility of the scrollbars.
14342 * So the values returned from {@link #getPaddingStart}, {@link #getPaddingTop},
14343 * {@link #getPaddingEnd} and {@link #getPaddingBottom} may be different
14344 * from the values set in this call.
14345 *
14346 * @attr ref android.R.styleable#View_padding
14347 * @attr ref android.R.styleable#View_paddingBottom
14348 * @attr ref android.R.styleable#View_paddingStart
14349 * @attr ref android.R.styleable#View_paddingEnd
14350 * @attr ref android.R.styleable#View_paddingTop
14351 * @param start the start padding in pixels
14352 * @param top the top padding in pixels
14353 * @param end the end padding in pixels
14354 * @param bottom the bottom padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014355 */
14356 public void setPaddingRelative(int start, int top, int end, int bottom) {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014357 // Reset padding resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070014358 mPrivateFlags2 &= ~PFLAG2_PADDING_RESOLVED;
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014359
Fabrice Di Megliof9e36502011-06-21 18:41:48 -070014360 mUserPaddingStart = start;
14361 mUserPaddingEnd = end;
14362
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014363 switch(getResolvedLayoutDirection()) {
14364 case LAYOUT_DIRECTION_RTL:
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014365 internalSetPadding(end, top, start, bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014366 break;
14367 case LAYOUT_DIRECTION_LTR:
14368 default:
Fabrice Di Meglio509708d2012-03-06 15:41:11 -080014369 internalSetPadding(start, top, end, bottom);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014370 }
14371 }
14372
14373 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014374 * Returns the top padding of this view.
14375 *
14376 * @return the top padding in pixels
14377 */
14378 public int getPaddingTop() {
14379 return mPaddingTop;
14380 }
14381
14382 /**
14383 * Returns the bottom padding of this view. If there are inset and enabled
14384 * scrollbars, this value may include the space required to display the
14385 * scrollbars as well.
14386 *
14387 * @return the bottom padding in pixels
14388 */
14389 public int getPaddingBottom() {
14390 return mPaddingBottom;
14391 }
14392
14393 /**
14394 * Returns the left padding of this view. If there are inset and enabled
14395 * scrollbars, this value may include the space required to display the
14396 * scrollbars as well.
14397 *
14398 * @return the left padding in pixels
14399 */
14400 public int getPaddingLeft() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014401 if (!isPaddingResolved()) {
14402 resolvePadding();
14403 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014404 return mPaddingLeft;
14405 }
14406
14407 /**
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -070014408 * Returns the start padding of this view depending on its resolved layout direction.
14409 * If there are inset and enabled scrollbars, this value may include the space
14410 * required to display the scrollbars as well.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014411 *
14412 * @return the start padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014413 */
14414 public int getPaddingStart() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014415 if (!isPaddingResolved()) {
14416 resolvePadding();
14417 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014418 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14419 mPaddingRight : mPaddingLeft;
14420 }
14421
14422 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014423 * Returns the right padding of this view. If there are inset and enabled
14424 * scrollbars, this value may include the space required to display the
14425 * scrollbars as well.
14426 *
14427 * @return the right padding in pixels
14428 */
14429 public int getPaddingRight() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014430 if (!isPaddingResolved()) {
14431 resolvePadding();
14432 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014433 return mPaddingRight;
14434 }
14435
14436 /**
Fabrice Di Meglio30a21e12012-03-12 13:12:19 -070014437 * Returns the end padding of this view depending on its resolved layout direction.
14438 * If there are inset and enabled scrollbars, this value may include the space
14439 * required to display the scrollbars as well.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014440 *
14441 * @return the end padding in pixels
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014442 */
14443 public int getPaddingEnd() {
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070014444 if (!isPaddingResolved()) {
14445 resolvePadding();
14446 }
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014447 return (getResolvedLayoutDirection() == LAYOUT_DIRECTION_RTL) ?
14448 mPaddingLeft : mPaddingRight;
14449 }
14450
14451 /**
14452 * Return if the padding as been set thru relative values
14453 * {@link #setPaddingRelative(int, int, int, int)} or thru
14454 * @attr ref android.R.styleable#View_paddingStart or
14455 * @attr ref android.R.styleable#View_paddingEnd
14456 *
14457 * @return true if the padding is relative or false if it is not.
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014458 */
14459 public boolean isPaddingRelative() {
Fabrice Di Meglio016456e2012-07-17 20:35:48 -070014460 return (mUserPaddingStart != UNDEFINED_PADDING || mUserPaddingEnd != UNDEFINED_PADDING);
Fabrice Di Megliod8703a92011-06-16 18:54:08 -070014461 }
14462
14463 /**
Philip Milne1557fd72012-04-04 23:41:34 -070014464 * @hide
14465 */
Philip Milne7a23b492012-04-24 22:12:36 -070014466 public Insets getOpticalInsets() {
Philip Milne1557fd72012-04-04 23:41:34 -070014467 if (mLayoutInsets == null) {
Philip Milnebbd51f12012-04-18 15:09:05 -070014468 mLayoutInsets = (mBackground == null) ? Insets.NONE : mBackground.getLayoutInsets();
Philip Milne1557fd72012-04-04 23:41:34 -070014469 }
14470 return mLayoutInsets;
14471 }
14472
14473 /**
14474 * @hide
14475 */
14476 public void setLayoutInsets(Insets layoutInsets) {
14477 mLayoutInsets = layoutInsets;
14478 }
14479
14480 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014481 * Changes the selection state of this view. A view can be selected or not.
14482 * Note that selection is not the same as focus. Views are typically
14483 * selected in the context of an AdapterView like ListView or GridView;
14484 * the selected view is the view that is highlighted.
14485 *
14486 * @param selected true if the view must be selected, false otherwise
14487 */
14488 public void setSelected(boolean selected) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014489 if (((mPrivateFlags & PFLAG_SELECTED) != 0) != selected) {
14490 mPrivateFlags = (mPrivateFlags & ~PFLAG_SELECTED) | (selected ? PFLAG_SELECTED : 0);
Romain Guya2431d02009-04-30 16:30:00 -070014491 if (!selected) resetPressedState();
Romain Guy0fd89bf2011-01-26 15:41:30 -080014492 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014493 refreshDrawableState();
14494 dispatchSetSelected(selected);
Svetoslav Ganov42138042012-03-20 11:51:39 -070014495 if (AccessibilityManager.getInstance(mContext).isEnabled()) {
14496 notifyAccessibilityStateChanged();
14497 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014498 }
14499 }
14500
14501 /**
14502 * Dispatch setSelected to all of this View's children.
14503 *
14504 * @see #setSelected(boolean)
14505 *
14506 * @param selected The new selected state
14507 */
14508 protected void dispatchSetSelected(boolean selected) {
14509 }
14510
14511 /**
14512 * Indicates the selection state of this view.
14513 *
14514 * @return true if the view is selected, false otherwise
14515 */
14516 @ViewDebug.ExportedProperty
14517 public boolean isSelected() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014518 return (mPrivateFlags & PFLAG_SELECTED) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014519 }
14520
14521 /**
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014522 * Changes the activated state of this view. A view can be activated or not.
14523 * Note that activation is not the same as selection. Selection is
14524 * a transient property, representing the view (hierarchy) the user is
14525 * currently interacting with. Activation is a longer-term state that the
14526 * user can move views in and out of. For example, in a list view with
14527 * single or multiple selection enabled, the views in the current selection
14528 * set are activated. (Um, yeah, we are deeply sorry about the terminology
14529 * here.) The activated state is propagated down to children of the view it
14530 * is set on.
14531 *
14532 * @param activated true if the view must be activated, false otherwise
14533 */
14534 public void setActivated(boolean activated) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014535 if (((mPrivateFlags & PFLAG_ACTIVATED) != 0) != activated) {
14536 mPrivateFlags = (mPrivateFlags & ~PFLAG_ACTIVATED) | (activated ? PFLAG_ACTIVATED : 0);
Romain Guy0fd89bf2011-01-26 15:41:30 -080014537 invalidate(true);
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014538 refreshDrawableState();
Dianne Hackbornc6669ca2010-09-16 01:33:24 -070014539 dispatchSetActivated(activated);
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014540 }
14541 }
14542
14543 /**
14544 * Dispatch setActivated to all of this View's children.
14545 *
14546 * @see #setActivated(boolean)
14547 *
14548 * @param activated The new activated state
14549 */
14550 protected void dispatchSetActivated(boolean activated) {
14551 }
14552
14553 /**
14554 * Indicates the activation state of this view.
14555 *
14556 * @return true if the view is activated, false otherwise
14557 */
14558 @ViewDebug.ExportedProperty
14559 public boolean isActivated() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014560 return (mPrivateFlags & PFLAG_ACTIVATED) != 0;
Dianne Hackbornd0fa3712010-09-14 18:57:14 -070014561 }
14562
14563 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014564 * Returns the ViewTreeObserver for this view's hierarchy. The view tree
14565 * observer can be used to get notifications when global events, like
14566 * layout, happen.
14567 *
14568 * The returned ViewTreeObserver observer is not guaranteed to remain
14569 * valid for the lifetime of this View. If the caller of this method keeps
14570 * a long-lived reference to ViewTreeObserver, it should always check for
14571 * the return value of {@link ViewTreeObserver#isAlive()}.
14572 *
14573 * @return The ViewTreeObserver for this view's hierarchy.
14574 */
14575 public ViewTreeObserver getViewTreeObserver() {
14576 if (mAttachInfo != null) {
14577 return mAttachInfo.mTreeObserver;
14578 }
14579 if (mFloatingTreeObserver == null) {
14580 mFloatingTreeObserver = new ViewTreeObserver();
14581 }
14582 return mFloatingTreeObserver;
14583 }
14584
14585 /**
14586 * <p>Finds the topmost view in the current view hierarchy.</p>
14587 *
14588 * @return the topmost view containing this view
14589 */
14590 public View getRootView() {
14591 if (mAttachInfo != null) {
14592 final View v = mAttachInfo.mRootView;
14593 if (v != null) {
14594 return v;
14595 }
14596 }
Romain Guy8506ab42009-06-11 17:35:47 -070014597
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014598 View parent = this;
14599
14600 while (parent.mParent != null && parent.mParent instanceof View) {
14601 parent = (View) parent.mParent;
14602 }
14603
14604 return parent;
14605 }
14606
14607 /**
14608 * <p>Computes the coordinates of this view on the screen. The argument
14609 * must be an array of two integers. After the method returns, the array
14610 * contains the x and y location in that order.</p>
14611 *
14612 * @param location an array of two integers in which to hold the coordinates
14613 */
14614 public void getLocationOnScreen(int[] location) {
14615 getLocationInWindow(location);
14616
14617 final AttachInfo info = mAttachInfo;
Romain Guy779398e2009-06-16 13:17:50 -070014618 if (info != null) {
14619 location[0] += info.mWindowLeft;
14620 location[1] += info.mWindowTop;
14621 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014622 }
14623
14624 /**
14625 * <p>Computes the coordinates of this view in its window. The argument
14626 * must be an array of two integers. After the method returns, the array
14627 * contains the x and y location in that order.</p>
14628 *
14629 * @param location an array of two integers in which to hold the coordinates
14630 */
14631 public void getLocationInWindow(int[] location) {
14632 if (location == null || location.length < 2) {
Gilles Debunnecea45132011-11-24 02:19:27 +010014633 throw new IllegalArgumentException("location must be an array of two integers");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014634 }
14635
Gilles Debunne6583ce52011-12-06 18:09:02 -080014636 if (mAttachInfo == null) {
14637 // When the view is not attached to a window, this method does not make sense
14638 location[0] = location[1] = 0;
14639 return;
14640 }
14641
Gilles Debunnecea45132011-11-24 02:19:27 +010014642 float[] position = mAttachInfo.mTmpTransformLocation;
14643 position[0] = position[1] = 0.0f;
14644
14645 if (!hasIdentityMatrix()) {
14646 getMatrix().mapPoints(position);
Dianne Hackbornddb715b2011-09-09 14:43:39 -070014647 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014648
Gilles Debunnecea45132011-11-24 02:19:27 +010014649 position[0] += mLeft;
14650 position[1] += mTop;
14651
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014652 ViewParent viewParent = mParent;
14653 while (viewParent instanceof View) {
Gilles Debunnecea45132011-11-24 02:19:27 +010014654 final View view = (View) viewParent;
14655
14656 position[0] -= view.mScrollX;
14657 position[1] -= view.mScrollY;
14658
14659 if (!view.hasIdentityMatrix()) {
14660 view.getMatrix().mapPoints(position);
Dianne Hackbornddb715b2011-09-09 14:43:39 -070014661 }
Gilles Debunnecea45132011-11-24 02:19:27 +010014662
14663 position[0] += view.mLeft;
14664 position[1] += view.mTop;
14665
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014666 viewParent = view.mParent;
Svetoslav Ganov42138042012-03-20 11:51:39 -070014667 }
Romain Guy8506ab42009-06-11 17:35:47 -070014668
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070014669 if (viewParent instanceof ViewRootImpl) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014670 // *cough*
Gilles Debunnecea45132011-11-24 02:19:27 +010014671 final ViewRootImpl vr = (ViewRootImpl) viewParent;
14672 position[1] -= vr.mCurScrollY;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014673 }
Gilles Debunnecea45132011-11-24 02:19:27 +010014674
14675 location[0] = (int) (position[0] + 0.5f);
14676 location[1] = (int) (position[1] + 0.5f);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014677 }
14678
14679 /**
14680 * {@hide}
14681 * @param id the id of the view to be found
14682 * @return the view of the specified id, null if cannot be found
14683 */
14684 protected View findViewTraversal(int id) {
14685 if (id == mID) {
14686 return this;
14687 }
14688 return null;
14689 }
14690
14691 /**
14692 * {@hide}
14693 * @param tag the tag of the view to be found
14694 * @return the view of specified tag, null if cannot be found
14695 */
14696 protected View findViewWithTagTraversal(Object tag) {
14697 if (tag != null && tag.equals(mTag)) {
14698 return this;
14699 }
14700 return null;
14701 }
14702
14703 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -080014704 * {@hide}
14705 * @param predicate The predicate to evaluate.
Jeff Brown4dfbec22011-08-15 14:55:37 -070014706 * @param childToSkip If not null, ignores this child during the recursive traversal.
Jeff Brown4e6319b2010-12-13 10:36:51 -080014707 * @return The first view that matches the predicate or null.
14708 */
Jeff Brown4dfbec22011-08-15 14:55:37 -070014709 protected View findViewByPredicateTraversal(Predicate<View> predicate, View childToSkip) {
Jeff Brown4e6319b2010-12-13 10:36:51 -080014710 if (predicate.apply(this)) {
14711 return this;
14712 }
14713 return null;
14714 }
14715
14716 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014717 * Look for a child view with the given id. If this view has the given
14718 * id, return this view.
14719 *
14720 * @param id The id to search for.
14721 * @return The view that has the given id in the hierarchy or null
14722 */
14723 public final View findViewById(int id) {
14724 if (id < 0) {
14725 return null;
14726 }
14727 return findViewTraversal(id);
14728 }
14729
14730 /**
Svetoslav Ganov2cdedff2011-10-03 14:18:42 -070014731 * Finds a view by its unuque and stable accessibility id.
14732 *
14733 * @param accessibilityId The searched accessibility id.
14734 * @return The found view.
14735 */
14736 final View findViewByAccessibilityId(int accessibilityId) {
14737 if (accessibilityId < 0) {
14738 return null;
14739 }
14740 return findViewByAccessibilityIdTraversal(accessibilityId);
14741 }
14742
14743 /**
14744 * Performs the traversal to find a view by its unuque and stable accessibility id.
14745 *
14746 * <strong>Note:</strong>This method does not stop at the root namespace
14747 * boundary since the user can touch the screen at an arbitrary location
14748 * potentially crossing the root namespace bounday which will send an
14749 * accessibility event to accessibility services and they should be able
14750 * to obtain the event source. Also accessibility ids are guaranteed to be
14751 * unique in the window.
14752 *
14753 * @param accessibilityId The accessibility id.
14754 * @return The found view.
14755 */
14756 View findViewByAccessibilityIdTraversal(int accessibilityId) {
14757 if (getAccessibilityViewId() == accessibilityId) {
14758 return this;
14759 }
14760 return null;
14761 }
14762
14763 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014764 * Look for a child view with the given tag. If this view has the given
14765 * tag, return this view.
14766 *
14767 * @param tag The tag to search for, using "tag.equals(getTag())".
14768 * @return The View that has the given tag in the hierarchy or null
14769 */
14770 public final View findViewWithTag(Object tag) {
14771 if (tag == null) {
14772 return null;
14773 }
14774 return findViewWithTagTraversal(tag);
14775 }
14776
14777 /**
Jeff Brown4e6319b2010-12-13 10:36:51 -080014778 * {@hide}
14779 * Look for a child view that matches the specified predicate.
14780 * If this view matches the predicate, return this view.
14781 *
14782 * @param predicate The predicate to evaluate.
14783 * @return The first view that matches the predicate or null.
14784 */
14785 public final View findViewByPredicate(Predicate<View> predicate) {
Jeff Brown4dfbec22011-08-15 14:55:37 -070014786 return findViewByPredicateTraversal(predicate, null);
14787 }
14788
14789 /**
14790 * {@hide}
14791 * Look for a child view that matches the specified predicate,
14792 * starting with the specified view and its descendents and then
14793 * recusively searching the ancestors and siblings of that view
14794 * until this view is reached.
14795 *
14796 * This method is useful in cases where the predicate does not match
14797 * a single unique view (perhaps multiple views use the same id)
14798 * and we are trying to find the view that is "closest" in scope to the
14799 * starting view.
14800 *
14801 * @param start The view to start from.
14802 * @param predicate The predicate to evaluate.
14803 * @return The first view that matches the predicate or null.
14804 */
14805 public final View findViewByPredicateInsideOut(View start, Predicate<View> predicate) {
14806 View childToSkip = null;
14807 for (;;) {
14808 View view = start.findViewByPredicateTraversal(predicate, childToSkip);
14809 if (view != null || start == this) {
14810 return view;
14811 }
14812
14813 ViewParent parent = start.getParent();
14814 if (parent == null || !(parent instanceof View)) {
14815 return null;
14816 }
14817
14818 childToSkip = start;
14819 start = (View) parent;
14820 }
Jeff Brown4e6319b2010-12-13 10:36:51 -080014821 }
14822
14823 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014824 * Sets the identifier for this view. The identifier does not have to be
14825 * unique in this view's hierarchy. The identifier should be a positive
14826 * number.
14827 *
14828 * @see #NO_ID
Philip Milne6c8ea062012-04-03 17:38:43 -070014829 * @see #getId()
14830 * @see #findViewById(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014831 *
14832 * @param id a number used to identify the view
14833 *
14834 * @attr ref android.R.styleable#View_id
14835 */
14836 public void setId(int id) {
14837 mID = id;
14838 }
14839
14840 /**
14841 * {@hide}
14842 *
14843 * @param isRoot true if the view belongs to the root namespace, false
14844 * otherwise
14845 */
14846 public void setIsRootNamespace(boolean isRoot) {
14847 if (isRoot) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014848 mPrivateFlags |= PFLAG_IS_ROOT_NAMESPACE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014849 } else {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014850 mPrivateFlags &= ~PFLAG_IS_ROOT_NAMESPACE;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014851 }
14852 }
14853
14854 /**
14855 * {@hide}
14856 *
14857 * @return true if the view belongs to the root namespace, false otherwise
14858 */
14859 public boolean isRootNamespace() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070014860 return (mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014861 }
14862
14863 /**
14864 * Returns this view's identifier.
14865 *
14866 * @return a positive integer used to identify the view or {@link #NO_ID}
14867 * if the view has no ID
14868 *
Philip Milne6c8ea062012-04-03 17:38:43 -070014869 * @see #setId(int)
14870 * @see #findViewById(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014871 * @attr ref android.R.styleable#View_id
14872 */
14873 @ViewDebug.CapturedViewProperty
14874 public int getId() {
14875 return mID;
14876 }
14877
14878 /**
14879 * Returns this view's tag.
14880 *
14881 * @return the Object stored in this view as a tag
Romain Guyd90a3312009-05-06 14:54:28 -070014882 *
14883 * @see #setTag(Object)
14884 * @see #getTag(int)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014885 */
14886 @ViewDebug.ExportedProperty
14887 public Object getTag() {
14888 return mTag;
14889 }
14890
14891 /**
14892 * Sets the tag associated with this view. A tag can be used to mark
14893 * a view in its hierarchy and does not have to be unique within the
14894 * hierarchy. Tags can also be used to store data within a view without
14895 * resorting to another data structure.
14896 *
14897 * @param tag an Object to tag the view with
Romain Guyd90a3312009-05-06 14:54:28 -070014898 *
14899 * @see #getTag()
14900 * @see #setTag(int, Object)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014901 */
14902 public void setTag(final Object tag) {
14903 mTag = tag;
14904 }
14905
14906 /**
Romain Guyd90a3312009-05-06 14:54:28 -070014907 * Returns the tag associated with this view and the specified key.
14908 *
14909 * @param key The key identifying the tag
14910 *
14911 * @return the Object stored in this view as a tag
14912 *
14913 * @see #setTag(int, Object)
Romain Guy8506ab42009-06-11 17:35:47 -070014914 * @see #getTag()
Romain Guyd90a3312009-05-06 14:54:28 -070014915 */
14916 public Object getTag(int key) {
Adam Powell7db82ac2011-09-22 19:44:04 -070014917 if (mKeyedTags != null) return mKeyedTags.get(key);
Romain Guyd90a3312009-05-06 14:54:28 -070014918 return null;
14919 }
14920
14921 /**
14922 * Sets a tag associated with this view and a key. A tag can be used
14923 * to mark a view in its hierarchy and does not have to be unique within
14924 * the hierarchy. Tags can also be used to store data within a view
14925 * without resorting to another data structure.
14926 *
14927 * The specified key should be an id declared in the resources of the
Scott Maindfe5c202010-06-08 15:54:52 -070014928 * application to ensure it is unique (see the <a
14929 * href={@docRoot}guide/topics/resources/more-resources.html#Id">ID resource type</a>).
14930 * Keys identified as belonging to
Romain Guyd90a3312009-05-06 14:54:28 -070014931 * the Android framework or not associated with any package will cause
14932 * an {@link IllegalArgumentException} to be thrown.
14933 *
14934 * @param key The key identifying the tag
14935 * @param tag An Object to tag the view with
14936 *
14937 * @throws IllegalArgumentException If they specified key is not valid
14938 *
14939 * @see #setTag(Object)
14940 * @see #getTag(int)
14941 */
14942 public void setTag(int key, final Object tag) {
14943 // If the package id is 0x00 or 0x01, it's either an undefined package
14944 // or a framework id
14945 if ((key >>> 24) < 2) {
14946 throw new IllegalArgumentException("The key must be an application-specific "
14947 + "resource id.");
14948 }
14949
Adam Powell2b2f6d62011-09-23 11:15:39 -070014950 setKeyedTag(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070014951 }
14952
14953 /**
14954 * Variation of {@link #setTag(int, Object)} that enforces the key to be a
14955 * framework id.
14956 *
14957 * @hide
14958 */
14959 public void setTagInternal(int key, Object tag) {
14960 if ((key >>> 24) != 0x1) {
14961 throw new IllegalArgumentException("The key must be a framework-specific "
14962 + "resource id.");
14963 }
14964
Adam Powell2b2f6d62011-09-23 11:15:39 -070014965 setKeyedTag(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070014966 }
14967
Adam Powell2b2f6d62011-09-23 11:15:39 -070014968 private void setKeyedTag(int key, Object tag) {
Adam Powell7db82ac2011-09-22 19:44:04 -070014969 if (mKeyedTags == null) {
14970 mKeyedTags = new SparseArray<Object>();
Romain Guyd90a3312009-05-06 14:54:28 -070014971 }
14972
Adam Powell7db82ac2011-09-22 19:44:04 -070014973 mKeyedTags.put(key, tag);
Romain Guyd90a3312009-05-06 14:54:28 -070014974 }
14975
14976 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080014977 * Prints information about this view in the log output, with the tag
14978 * {@link #VIEW_LOG_TAG}.
14979 *
14980 * @hide
14981 */
14982 public void debug() {
14983 debug(0);
14984 }
14985
14986 /**
14987 * Prints information about this view in the log output, with the tag
14988 * {@link #VIEW_LOG_TAG}. Each line in the output is preceded with an
14989 * indentation defined by the <code>depth</code>.
14990 *
14991 * @param depth the indentation level
14992 *
14993 * @hide
14994 */
14995 protected void debug(int depth) {
14996 String output = debugIndent(depth - 1);
14997
14998 output += "+ " + this;
14999 int id = getId();
15000 if (id != -1) {
15001 output += " (id=" + id + ")";
15002 }
15003 Object tag = getTag();
15004 if (tag != null) {
15005 output += " (tag=" + tag + ")";
15006 }
15007 Log.d(VIEW_LOG_TAG, output);
15008
Dianne Hackborn4702a852012-08-17 15:18:29 -070015009 if ((mPrivateFlags & PFLAG_FOCUSED) != 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015010 output = debugIndent(depth) + " FOCUSED";
15011 Log.d(VIEW_LOG_TAG, output);
15012 }
15013
15014 output = debugIndent(depth);
15015 output += "frame={" + mLeft + ", " + mTop + ", " + mRight
15016 + ", " + mBottom + "} scroll={" + mScrollX + ", " + mScrollY
15017 + "} ";
15018 Log.d(VIEW_LOG_TAG, output);
15019
15020 if (mPaddingLeft != 0 || mPaddingTop != 0 || mPaddingRight != 0
15021 || mPaddingBottom != 0) {
15022 output = debugIndent(depth);
15023 output += "padding={" + mPaddingLeft + ", " + mPaddingTop
15024 + ", " + mPaddingRight + ", " + mPaddingBottom + "}";
15025 Log.d(VIEW_LOG_TAG, output);
15026 }
15027
15028 output = debugIndent(depth);
15029 output += "mMeasureWidth=" + mMeasuredWidth +
15030 " mMeasureHeight=" + mMeasuredHeight;
15031 Log.d(VIEW_LOG_TAG, output);
15032
15033 output = debugIndent(depth);
15034 if (mLayoutParams == null) {
15035 output += "BAD! no layout params";
15036 } else {
15037 output = mLayoutParams.debug(output);
15038 }
15039 Log.d(VIEW_LOG_TAG, output);
15040
15041 output = debugIndent(depth);
15042 output += "flags={";
15043 output += View.printFlags(mViewFlags);
15044 output += "}";
15045 Log.d(VIEW_LOG_TAG, output);
15046
15047 output = debugIndent(depth);
15048 output += "privateFlags={";
15049 output += View.printPrivateFlags(mPrivateFlags);
15050 output += "}";
15051 Log.d(VIEW_LOG_TAG, output);
15052 }
15053
15054 /**
Ken Wakasaf76a50c2012-03-09 19:56:35 +090015055 * Creates a string of whitespaces used for indentation.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015056 *
15057 * @param depth the indentation level
15058 * @return a String containing (depth * 2 + 3) * 2 white spaces
15059 *
15060 * @hide
15061 */
15062 protected static String debugIndent(int depth) {
15063 StringBuilder spaces = new StringBuilder((depth * 2 + 3) * 2);
15064 for (int i = 0; i < (depth * 2) + 3; i++) {
15065 spaces.append(' ').append(' ');
15066 }
15067 return spaces.toString();
15068 }
15069
15070 /**
15071 * <p>Return the offset of the widget's text baseline from the widget's top
15072 * boundary. If this widget does not support baseline alignment, this
15073 * method returns -1. </p>
15074 *
15075 * @return the offset of the baseline within the widget's bounds or -1
15076 * if baseline alignment is not supported
15077 */
Konstantin Lopyrevbea95162010-08-10 17:02:18 -070015078 @ViewDebug.ExportedProperty(category = "layout")
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015079 public int getBaseline() {
15080 return -1;
15081 }
15082
15083 /**
15084 * Call this when something has changed which has invalidated the
15085 * layout of this view. This will schedule a layout pass of the view
15086 * tree.
15087 */
15088 public void requestLayout() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015089 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15090 mPrivateFlags |= PFLAG_INVALIDATED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015091
Fabrice Di Meglio4a5268852012-03-30 15:56:48 -070015092 if (mParent != null && !mParent.isLayoutRequested()) {
15093 mParent.requestLayout();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015094 }
15095 }
15096
15097 /**
15098 * Forces this view to be laid out during the next layout pass.
15099 * This method does not call requestLayout() or forceLayout()
15100 * on the parent.
15101 */
15102 public void forceLayout() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015103 mPrivateFlags |= PFLAG_FORCE_LAYOUT;
15104 mPrivateFlags |= PFLAG_INVALIDATED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015105 }
15106
15107 /**
15108 * <p>
15109 * This is called to find out how big a view should be. The parent
15110 * supplies constraint information in the width and height parameters.
15111 * </p>
15112 *
15113 * <p>
Romain Guy967e2bf2012-02-07 17:04:34 -080015114 * The actual measurement work of a view is performed in
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015115 * {@link #onMeasure(int, int)}, called by this method. Therefore, only
Romain Guy967e2bf2012-02-07 17:04:34 -080015116 * {@link #onMeasure(int, int)} can and must be overridden by subclasses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015117 * </p>
15118 *
15119 *
15120 * @param widthMeasureSpec Horizontal space requirements as imposed by the
15121 * parent
15122 * @param heightMeasureSpec Vertical space requirements as imposed by the
15123 * parent
15124 *
15125 * @see #onMeasure(int, int)
15126 */
15127 public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015128 if ((mPrivateFlags & PFLAG_FORCE_LAYOUT) == PFLAG_FORCE_LAYOUT ||
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015129 widthMeasureSpec != mOldWidthMeasureSpec ||
15130 heightMeasureSpec != mOldHeightMeasureSpec) {
15131
15132 // first clears the measured dimension flag
Dianne Hackborn4702a852012-08-17 15:18:29 -070015133 mPrivateFlags &= ~PFLAG_MEASURED_DIMENSION_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015134
Fabrice Di Meglio23c89fd2012-08-13 12:17:42 -070015135 if (!isPaddingResolved()) {
Adam Powell0090f202012-08-07 17:15:30 -070015136 resolvePadding();
15137 }
15138
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015139 // measure ourselves, this should set the measured dimension flag back
15140 onMeasure(widthMeasureSpec, heightMeasureSpec);
15141
15142 // flag not set, setMeasuredDimension() was not invoked, we raise
15143 // an exception to warn the developer
Dianne Hackborn4702a852012-08-17 15:18:29 -070015144 if ((mPrivateFlags & PFLAG_MEASURED_DIMENSION_SET) != PFLAG_MEASURED_DIMENSION_SET) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015145 throw new IllegalStateException("onMeasure() did not set the"
15146 + " measured dimension by calling"
15147 + " setMeasuredDimension()");
15148 }
15149
Dianne Hackborn4702a852012-08-17 15:18:29 -070015150 mPrivateFlags |= PFLAG_LAYOUT_REQUIRED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015151 }
15152
15153 mOldWidthMeasureSpec = widthMeasureSpec;
15154 mOldHeightMeasureSpec = heightMeasureSpec;
15155 }
15156
15157 /**
15158 * <p>
15159 * Measure the view and its content to determine the measured width and the
15160 * measured height. This method is invoked by {@link #measure(int, int)} and
15161 * should be overriden by subclasses to provide accurate and efficient
15162 * measurement of their contents.
15163 * </p>
15164 *
15165 * <p>
15166 * <strong>CONTRACT:</strong> When overriding this method, you
15167 * <em>must</em> call {@link #setMeasuredDimension(int, int)} to store the
15168 * measured width and height of this view. Failure to do so will trigger an
15169 * <code>IllegalStateException</code>, thrown by
15170 * {@link #measure(int, int)}. Calling the superclass'
15171 * {@link #onMeasure(int, int)} is a valid use.
15172 * </p>
15173 *
15174 * <p>
15175 * The base class implementation of measure defaults to the background size,
15176 * unless a larger size is allowed by the MeasureSpec. Subclasses should
15177 * override {@link #onMeasure(int, int)} to provide better measurements of
15178 * their content.
15179 * </p>
15180 *
15181 * <p>
15182 * If this method is overridden, it is the subclass's responsibility to make
15183 * sure the measured height and width are at least the view's minimum height
15184 * and width ({@link #getSuggestedMinimumHeight()} and
15185 * {@link #getSuggestedMinimumWidth()}).
15186 * </p>
15187 *
15188 * @param widthMeasureSpec horizontal space requirements as imposed by the parent.
15189 * The requirements are encoded with
15190 * {@link android.view.View.MeasureSpec}.
15191 * @param heightMeasureSpec vertical space requirements as imposed by the parent.
15192 * The requirements are encoded with
15193 * {@link android.view.View.MeasureSpec}.
15194 *
15195 * @see #getMeasuredWidth()
15196 * @see #getMeasuredHeight()
15197 * @see #setMeasuredDimension(int, int)
15198 * @see #getSuggestedMinimumHeight()
15199 * @see #getSuggestedMinimumWidth()
15200 * @see android.view.View.MeasureSpec#getMode(int)
15201 * @see android.view.View.MeasureSpec#getSize(int)
15202 */
15203 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
15204 setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
15205 getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
15206 }
15207
15208 /**
15209 * <p>This mehod must be called by {@link #onMeasure(int, int)} to store the
15210 * measured width and measured height. Failing to do so will trigger an
15211 * exception at measurement time.</p>
15212 *
Dianne Hackborn189ee182010-12-02 21:48:53 -080015213 * @param measuredWidth The measured width of this view. May be a complex
15214 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15215 * {@link #MEASURED_STATE_TOO_SMALL}.
15216 * @param measuredHeight The measured height of this view. May be a complex
15217 * bit mask as defined by {@link #MEASURED_SIZE_MASK} and
15218 * {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015219 */
15220 protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
15221 mMeasuredWidth = measuredWidth;
15222 mMeasuredHeight = measuredHeight;
15223
Dianne Hackborn4702a852012-08-17 15:18:29 -070015224 mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015225 }
15226
15227 /**
Dianne Hackborn189ee182010-12-02 21:48:53 -080015228 * Merge two states as returned by {@link #getMeasuredState()}.
15229 * @param curState The current state as returned from a view or the result
15230 * of combining multiple views.
15231 * @param newState The new view state to combine.
15232 * @return Returns a new integer reflecting the combination of the two
15233 * states.
15234 */
15235 public static int combineMeasuredStates(int curState, int newState) {
15236 return curState | newState;
15237 }
15238
15239 /**
15240 * Version of {@link #resolveSizeAndState(int, int, int)}
15241 * returning only the {@link #MEASURED_SIZE_MASK} bits of the result.
15242 */
15243 public static int resolveSize(int size, int measureSpec) {
15244 return resolveSizeAndState(size, measureSpec, 0) & MEASURED_SIZE_MASK;
15245 }
15246
15247 /**
15248 * Utility to reconcile a desired size and state, with constraints imposed
15249 * by a MeasureSpec. Will take the desired size, unless a different size
15250 * is imposed by the constraints. The returned value is a compound integer,
15251 * with the resolved size in the {@link #MEASURED_SIZE_MASK} bits and
15252 * optionally the bit {@link #MEASURED_STATE_TOO_SMALL} set if the resulting
15253 * size is smaller than the size the view wants to be.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015254 *
15255 * @param size How big the view wants to be
15256 * @param measureSpec Constraints imposed by the parent
Dianne Hackborn189ee182010-12-02 21:48:53 -080015257 * @return Size information bit mask as defined by
15258 * {@link #MEASURED_SIZE_MASK} and {@link #MEASURED_STATE_TOO_SMALL}.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015259 */
Dianne Hackborn189ee182010-12-02 21:48:53 -080015260 public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015261 int result = size;
15262 int specMode = MeasureSpec.getMode(measureSpec);
15263 int specSize = MeasureSpec.getSize(measureSpec);
15264 switch (specMode) {
15265 case MeasureSpec.UNSPECIFIED:
15266 result = size;
15267 break;
15268 case MeasureSpec.AT_MOST:
Dianne Hackborn189ee182010-12-02 21:48:53 -080015269 if (specSize < size) {
15270 result = specSize | MEASURED_STATE_TOO_SMALL;
15271 } else {
15272 result = size;
15273 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015274 break;
15275 case MeasureSpec.EXACTLY:
15276 result = specSize;
15277 break;
15278 }
Dianne Hackborn189ee182010-12-02 21:48:53 -080015279 return result | (childMeasuredState&MEASURED_STATE_MASK);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015280 }
15281
15282 /**
15283 * Utility to return a default size. Uses the supplied size if the
Romain Guy98029c82011-06-17 15:47:07 -070015284 * MeasureSpec imposed no constraints. Will get larger if allowed
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015285 * by the MeasureSpec.
15286 *
15287 * @param size Default size for this view
15288 * @param measureSpec Constraints imposed by the parent
15289 * @return The size this view should be.
15290 */
15291 public static int getDefaultSize(int size, int measureSpec) {
15292 int result = size;
15293 int specMode = MeasureSpec.getMode(measureSpec);
Romain Guy98029c82011-06-17 15:47:07 -070015294 int specSize = MeasureSpec.getSize(measureSpec);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015295
15296 switch (specMode) {
15297 case MeasureSpec.UNSPECIFIED:
15298 result = size;
15299 break;
15300 case MeasureSpec.AT_MOST:
15301 case MeasureSpec.EXACTLY:
15302 result = specSize;
15303 break;
15304 }
15305 return result;
15306 }
15307
15308 /**
15309 * Returns the suggested minimum height that the view should use. This
15310 * returns the maximum of the view's minimum height
15311 * and the background's minimum height
15312 * ({@link android.graphics.drawable.Drawable#getMinimumHeight()}).
15313 * <p>
15314 * When being used in {@link #onMeasure(int, int)}, the caller should still
15315 * ensure the returned height is within the requirements of the parent.
15316 *
15317 * @return The suggested minimum height of the view.
15318 */
15319 protected int getSuggestedMinimumHeight() {
Philip Milne6c8ea062012-04-03 17:38:43 -070015320 return (mBackground == null) ? mMinHeight : max(mMinHeight, mBackground.getMinimumHeight());
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015321
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015322 }
15323
15324 /**
15325 * Returns the suggested minimum width that the view should use. This
15326 * returns the maximum of the view's minimum width)
15327 * and the background's minimum width
15328 * ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
15329 * <p>
15330 * When being used in {@link #onMeasure(int, int)}, the caller should still
15331 * ensure the returned width is within the requirements of the parent.
15332 *
15333 * @return The suggested minimum width of the view.
15334 */
15335 protected int getSuggestedMinimumWidth() {
Philip Milne6c8ea062012-04-03 17:38:43 -070015336 return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
15337 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015338
Philip Milne6c8ea062012-04-03 17:38:43 -070015339 /**
15340 * Returns the minimum height of the view.
15341 *
15342 * @return the minimum height the view will try to be.
15343 *
15344 * @see #setMinimumHeight(int)
15345 *
15346 * @attr ref android.R.styleable#View_minHeight
15347 */
15348 public int getMinimumHeight() {
15349 return mMinHeight;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015350 }
15351
15352 /**
15353 * Sets the minimum height of the view. It is not guaranteed the view will
15354 * be able to achieve this minimum height (for example, if its parent layout
15355 * constrains it with less available height).
15356 *
15357 * @param minHeight The minimum height the view will try to be.
Philip Milne6c8ea062012-04-03 17:38:43 -070015358 *
15359 * @see #getMinimumHeight()
15360 *
15361 * @attr ref android.R.styleable#View_minHeight
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015362 */
15363 public void setMinimumHeight(int minHeight) {
15364 mMinHeight = minHeight;
Philip Milne6c8ea062012-04-03 17:38:43 -070015365 requestLayout();
15366 }
15367
15368 /**
15369 * Returns the minimum width of the view.
15370 *
15371 * @return the minimum width the view will try to be.
15372 *
15373 * @see #setMinimumWidth(int)
15374 *
15375 * @attr ref android.R.styleable#View_minWidth
15376 */
15377 public int getMinimumWidth() {
15378 return mMinWidth;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015379 }
15380
15381 /**
15382 * Sets the minimum width of the view. It is not guaranteed the view will
15383 * be able to achieve this minimum width (for example, if its parent layout
15384 * constrains it with less available width).
15385 *
15386 * @param minWidth The minimum width the view will try to be.
Philip Milne6c8ea062012-04-03 17:38:43 -070015387 *
15388 * @see #getMinimumWidth()
15389 *
15390 * @attr ref android.R.styleable#View_minWidth
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015391 */
15392 public void setMinimumWidth(int minWidth) {
15393 mMinWidth = minWidth;
Philip Milne6c8ea062012-04-03 17:38:43 -070015394 requestLayout();
15395
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015396 }
15397
15398 /**
15399 * Get the animation currently associated with this view.
15400 *
15401 * @return The animation that is currently playing or
15402 * scheduled to play for this view.
15403 */
15404 public Animation getAnimation() {
15405 return mCurrentAnimation;
15406 }
15407
15408 /**
15409 * Start the specified animation now.
15410 *
15411 * @param animation the animation to start now
15412 */
15413 public void startAnimation(Animation animation) {
15414 animation.setStartTime(Animation.START_ON_FIRST_FRAME);
15415 setAnimation(animation);
Romain Guy0fd89bf2011-01-26 15:41:30 -080015416 invalidateParentCaches();
15417 invalidate(true);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015418 }
15419
15420 /**
15421 * Cancels any animations for this view.
15422 */
15423 public void clearAnimation() {
Romain Guy305a2eb2010-02-09 11:30:44 -080015424 if (mCurrentAnimation != null) {
Romain Guyb4a107d2010-02-09 18:50:08 -080015425 mCurrentAnimation.detach();
Romain Guy305a2eb2010-02-09 11:30:44 -080015426 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015427 mCurrentAnimation = null;
Romain Guy0fd89bf2011-01-26 15:41:30 -080015428 invalidateParentIfNeeded();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015429 }
15430
15431 /**
15432 * Sets the next animation to play for this view.
15433 * If you want the animation to play immediately, use
Chet Haase42428932012-05-11 15:39:07 -070015434 * {@link #startAnimation(android.view.animation.Animation)} instead.
15435 * This method provides allows fine-grained
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015436 * control over the start time and invalidation, but you
15437 * must make sure that 1) the animation has a start time set, and
Chet Haase42428932012-05-11 15:39:07 -070015438 * 2) the view's parent (which controls animations on its children)
15439 * will be invalidated when the animation is supposed to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015440 * start.
15441 *
15442 * @param animation The next animation, or null.
15443 */
15444 public void setAnimation(Animation animation) {
15445 mCurrentAnimation = animation;
Romain Guyeb378892012-04-12 11:33:14 -070015446
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015447 if (animation != null) {
Romain Guyeb378892012-04-12 11:33:14 -070015448 // If the screen is off assume the animation start time is now instead of
15449 // the next frame we draw. Keeping the START_ON_FIRST_FRAME start time
15450 // would cause the animation to start when the screen turns back on
15451 if (mAttachInfo != null && !mAttachInfo.mScreenOn &&
15452 animation.getStartTime() == Animation.START_ON_FIRST_FRAME) {
15453 animation.setStartTime(AnimationUtils.currentAnimationTimeMillis());
15454 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015455 animation.reset();
15456 }
15457 }
15458
15459 /**
15460 * Invoked by a parent ViewGroup to notify the start of the animation
15461 * currently associated with this view. If you override this method,
15462 * always call super.onAnimationStart();
15463 *
15464 * @see #setAnimation(android.view.animation.Animation)
15465 * @see #getAnimation()
15466 */
15467 protected void onAnimationStart() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015468 mPrivateFlags |= PFLAG_ANIMATION_STARTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015469 }
15470
15471 /**
15472 * Invoked by a parent ViewGroup to notify the end of the animation
15473 * currently associated with this view. If you override this method,
15474 * always call super.onAnimationEnd();
15475 *
15476 * @see #setAnimation(android.view.animation.Animation)
15477 * @see #getAnimation()
15478 */
15479 protected void onAnimationEnd() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070015480 mPrivateFlags &= ~PFLAG_ANIMATION_STARTED;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015481 }
15482
15483 /**
15484 * Invoked if there is a Transform that involves alpha. Subclass that can
15485 * draw themselves with the specified alpha should return true, and then
15486 * respect that alpha when their onDraw() is called. If this returns false
15487 * then the view may be redirected to draw into an offscreen buffer to
15488 * fulfill the request, which will look fine, but may be slower than if the
15489 * subclass handles it internally. The default implementation returns false.
15490 *
15491 * @param alpha The alpha (0..255) to apply to the view's drawing
15492 * @return true if the view can draw with the specified alpha.
15493 */
15494 protected boolean onSetAlpha(int alpha) {
15495 return false;
15496 }
15497
15498 /**
15499 * This is used by the RootView to perform an optimization when
15500 * the view hierarchy contains one or several SurfaceView.
15501 * SurfaceView is always considered transparent, but its children are not,
15502 * therefore all View objects remove themselves from the global transparent
15503 * region (passed as a parameter to this function).
15504 *
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070015505 * @param region The transparent region for this ViewAncestor (window).
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015506 *
15507 * @return Returns true if the effective visibility of the view at this
15508 * point is opaque, regardless of the transparent region; returns false
15509 * if it is possible for underlying windows to be seen behind the view.
15510 *
15511 * {@hide}
15512 */
15513 public boolean gatherTransparentRegion(Region region) {
15514 final AttachInfo attachInfo = mAttachInfo;
15515 if (region != null && attachInfo != null) {
15516 final int pflags = mPrivateFlags;
Dianne Hackborn4702a852012-08-17 15:18:29 -070015517 if ((pflags & PFLAG_SKIP_DRAW) == 0) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015518 // The SKIP_DRAW flag IS NOT set, so this view draws. We need to
15519 // remove it from the transparent region.
15520 final int[] location = attachInfo.mTransparentLocation;
15521 getLocationInWindow(location);
15522 region.op(location[0], location[1], location[0] + mRight - mLeft,
15523 location[1] + mBottom - mTop, Region.Op.DIFFERENCE);
Dianne Hackborn4702a852012-08-17 15:18:29 -070015524 } else if ((pflags & PFLAG_ONLY_DRAWS_BACKGROUND) != 0 && mBackground != null) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015525 // The ONLY_DRAWS_BACKGROUND flag IS set and the background drawable
15526 // exists, so we remove the background drawable's non-transparent
15527 // parts from this transparent region.
Philip Milne6c8ea062012-04-03 17:38:43 -070015528 applyDrawableToTransparentRegion(mBackground, region);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015529 }
15530 }
15531 return true;
15532 }
15533
15534 /**
15535 * Play a sound effect for this view.
15536 *
15537 * <p>The framework will play sound effects for some built in actions, such as
15538 * clicking, but you may wish to play these effects in your widget,
15539 * for instance, for internal navigation.
15540 *
15541 * <p>The sound effect will only be played if sound effects are enabled by the user, and
15542 * {@link #isSoundEffectsEnabled()} is true.
15543 *
15544 * @param soundConstant One of the constants defined in {@link SoundEffectConstants}
15545 */
15546 public void playSoundEffect(int soundConstant) {
15547 if (mAttachInfo == null || mAttachInfo.mRootCallbacks == null || !isSoundEffectsEnabled()) {
15548 return;
15549 }
15550 mAttachInfo.mRootCallbacks.playSoundEffect(soundConstant);
15551 }
15552
15553 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015554 * BZZZTT!!1!
Romain Guy8506ab42009-06-11 17:35:47 -070015555 *
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015556 * <p>Provide haptic feedback to the user for this view.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015557 *
15558 * <p>The framework will provide haptic feedback for some built in actions,
15559 * such as long presses, but you may wish to provide feedback for your
15560 * own widget.
15561 *
15562 * <p>The feedback will only be performed if
15563 * {@link #isHapticFeedbackEnabled()} is true.
15564 *
15565 * @param feedbackConstant One of the constants defined in
15566 * {@link HapticFeedbackConstants}
15567 */
15568 public boolean performHapticFeedback(int feedbackConstant) {
15569 return performHapticFeedback(feedbackConstant, 0);
15570 }
15571
15572 /**
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015573 * BZZZTT!!1!
Romain Guy8506ab42009-06-11 17:35:47 -070015574 *
Andy Stadlerf8a7cea2009-04-10 16:24:47 -070015575 * <p>Like {@link #performHapticFeedback(int)}, with additional options.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015576 *
15577 * @param feedbackConstant One of the constants defined in
15578 * {@link HapticFeedbackConstants}
15579 * @param flags Additional flags as per {@link HapticFeedbackConstants}.
15580 */
15581 public boolean performHapticFeedback(int feedbackConstant, int flags) {
15582 if (mAttachInfo == null) {
15583 return false;
15584 }
Romain Guyf607bdc2010-09-10 19:20:06 -070015585 //noinspection SimplifiableIfStatement
Romain Guy812ccbe2010-06-01 14:07:24 -070015586 if ((flags & HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING) == 0
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015587 && !isHapticFeedbackEnabled()) {
15588 return false;
15589 }
Romain Guy812ccbe2010-06-01 14:07:24 -070015590 return mAttachInfo.mRootCallbacks.performHapticFeedback(feedbackConstant,
15591 (flags & HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING) != 0);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080015592 }
15593
15594 /**
Dianne Hackborn98014352012-04-05 18:31:41 -070015595 * Request that the visibility of the status bar or other screen/window
15596 * decorations be changed.
15597 *
15598 * <p>This method is used to put the over device UI into temporary modes
15599 * where the user's attention is focused more on the application content,
15600 * by dimming or hiding surrounding system affordances. This is typically
15601 * used in conjunction with {@link Window#FEATURE_ACTION_BAR_OVERLAY
15602 * Window.FEATURE_ACTION_BAR_OVERLAY}, allowing the applications content
15603 * to be placed behind the action bar (and with these flags other system
15604 * affordances) so that smooth transitions between hiding and showing them
15605 * can be done.
15606 *
15607 * <p>Two representative examples of the use of system UI visibility is
15608 * implementing a content browsing application (like a magazine reader)
15609 * and a video playing application.
15610 *
15611 * <p>The first code shows a typical implementation of a View in a content
15612 * browsing application. In this implementation, the application goes
15613 * into a content-oriented mode by hiding the status bar and action bar,
15614 * and putting the navigation elements into lights out mode. The user can
15615 * then interact with content while in this mode. Such an application should
15616 * provide an easy way for the user to toggle out of the mode (such as to
15617 * check information in the status bar or access notifications). In the
15618 * implementation here, this is done simply by tapping on the content.
15619 *
15620 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/ContentBrowserActivity.java
15621 * content}
15622 *
15623 * <p>This second code sample shows a typical implementation of a View
15624 * in a video playing application. In this situation, while the video is
15625 * playing the application would like to go into a complete full-screen mode,
15626 * to use as much of the display as possible for the video. When in this state
15627 * the user can not interact with the application; the system intercepts
Dianne Hackborncf675782012-05-10 15:07:24 -070015628 * touching on the screen to pop the UI out of full screen mode. See
15629 * {@link #fitSystemWindows(Rect)} for a sample layout that goes with this code.
Dianne Hackborn98014352012-04-05 18:31:41 -070015630 *
15631 * {@sample development/samples/ApiDemos/src/com/example/android/apis/view/VideoPlayerActivity.java
15632 * content}
15633 *
15634 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15635 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15636 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15637 * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
Joe Onorato664644d2011-01-23 17:53:23 -080015638 */
15639 public void setSystemUiVisibility(int visibility) {
Daniel Sandler70524062011-09-21 00:30:47 -040015640 if (visibility != mSystemUiVisibility) {
15641 mSystemUiVisibility = visibility;
15642 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15643 mParent.recomputeViewAttributes(this);
15644 }
Joe Onorato664644d2011-01-23 17:53:23 -080015645 }
15646 }
15647
15648 /**
Dianne Hackborn98014352012-04-05 18:31:41 -070015649 * Returns the last {@link #setSystemUiVisibility(int) that this view has requested.
15650 * @return Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
15651 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, {@link #SYSTEM_UI_FLAG_FULLSCREEN},
15652 * {@link #SYSTEM_UI_FLAG_LAYOUT_STABLE}, {@link #SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION},
15653 * and {@link #SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN}.
Joe Onorato664644d2011-01-23 17:53:23 -080015654 */
Joe Onoratoe595cad2011-01-24 09:22:12 -080015655 public int getSystemUiVisibility() {
Joe Onorato664644d2011-01-23 17:53:23 -080015656 return mSystemUiVisibility;
15657 }
15658
Scott Mainec6331b2011-05-24 16:55:56 -070015659 /**
Dianne Hackborn3a3a6cf2012-03-26 10:24:04 -070015660 * Returns the current system UI visibility that is currently set for
15661 * the entire window. This is the combination of the
15662 * {@link #setSystemUiVisibility(int)} values supplied by all of the
15663 * views in the window.
15664 */
15665 public int getWindowSystemUiVisibility() {
15666 return mAttachInfo != null ? mAttachInfo.mSystemUiVisibility : 0;
15667 }
15668
15669 /**
15670 * Override to find out when the window's requested system UI visibility
15671 * has changed, that is the value returned by {@link #getWindowSystemUiVisibility()}.
15672 * This is different from the callbacks recieved through
15673 * {@link #setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener)}
15674 * in that this is only telling you about the local request of the window,
15675 * not the actual values applied by the system.
15676 */
15677 public void onWindowSystemUiVisibilityChanged(int visible) {
15678 }
15679
15680 /**
15681 * Dispatch callbacks to {@link #onWindowSystemUiVisibilityChanged(int)} down
15682 * the view hierarchy.
15683 */
15684 public void dispatchWindowSystemUiVisiblityChanged(int visible) {
15685 onWindowSystemUiVisibilityChanged(visible);
15686 }
15687
15688 /**
Scott Mainec6331b2011-05-24 16:55:56 -070015689 * Set a listener to receive callbacks when the visibility of the system bar changes.
15690 * @param l The {@link OnSystemUiVisibilityChangeListener} to receive callbacks.
15691 */
Joe Onorato664644d2011-01-23 17:53:23 -080015692 public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015693 getListenerInfo().mOnSystemUiVisibilityChangeListener = l;
Joe Onorato664644d2011-01-23 17:53:23 -080015694 if (mParent != null && mAttachInfo != null && !mAttachInfo.mRecomputeGlobalAttributes) {
15695 mParent.recomputeViewAttributes(this);
15696 }
15697 }
15698
15699 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015700 * Dispatch callbacks to {@link #setOnSystemUiVisibilityChangeListener} down
15701 * the view hierarchy.
Joe Onorato664644d2011-01-23 17:53:23 -080015702 */
15703 public void dispatchSystemUiVisibilityChanged(int visibility) {
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015704 ListenerInfo li = mListenerInfo;
15705 if (li != null && li.mOnSystemUiVisibilityChangeListener != null) {
15706 li.mOnSystemUiVisibilityChangeListener.onSystemUiVisibilityChange(
Joe Onorato6ab77bd2011-01-31 11:21:10 -080015707 visibility & PUBLIC_STATUS_BAR_VISIBILITY_MASK);
Joe Onorato664644d2011-01-23 17:53:23 -080015708 }
15709 }
15710
Dianne Hackborncf675782012-05-10 15:07:24 -070015711 boolean updateLocalSystemUiVisibility(int localValue, int localChanges) {
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015712 int val = (mSystemUiVisibility&~localChanges) | (localValue&localChanges);
15713 if (val != mSystemUiVisibility) {
15714 setSystemUiVisibility(val);
Dianne Hackborncf675782012-05-10 15:07:24 -070015715 return true;
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015716 }
Dianne Hackborncf675782012-05-10 15:07:24 -070015717 return false;
Dianne Hackborn9a230e02011-10-06 11:51:27 -070015718 }
15719
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070015720 /** @hide */
15721 public void setDisabledSystemUiVisibility(int flags) {
15722 if (mAttachInfo != null) {
15723 if (mAttachInfo.mDisabledSystemUiVisibility != flags) {
15724 mAttachInfo.mDisabledSystemUiVisibility = flags;
15725 if (mParent != null) {
15726 mParent.recomputeViewAttributes(this);
15727 }
15728 }
15729 }
15730 }
15731
Joe Onorato664644d2011-01-23 17:53:23 -080015732 /**
Joe Malin32736f02011-01-19 16:14:20 -080015733 * Creates an image that the system displays during the drag and drop
15734 * operation. This is called a &quot;drag shadow&quot;. The default implementation
15735 * for a DragShadowBuilder based on a View returns an image that has exactly the same
15736 * appearance as the given View. The default also positions the center of the drag shadow
15737 * directly under the touch point. If no View is provided (the constructor with no parameters
15738 * is used), and {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} and
15739 * {@link #onDrawShadow(Canvas) onDrawShadow()} are not overriden, then the
15740 * default is an invisible drag shadow.
15741 * <p>
15742 * You are not required to use the View you provide to the constructor as the basis of the
15743 * drag shadow. The {@link #onDrawShadow(Canvas) onDrawShadow()} method allows you to draw
15744 * anything you want as the drag shadow.
15745 * </p>
15746 * <p>
15747 * You pass a DragShadowBuilder object to the system when you start the drag. The system
15748 * calls {@link #onProvideShadowMetrics(Point,Point) onProvideShadowMetrics()} to get the
15749 * size and position of the drag shadow. It uses this data to construct a
15750 * {@link android.graphics.Canvas} object, then it calls {@link #onDrawShadow(Canvas) onDrawShadow()}
15751 * so that your application can draw the shadow image in the Canvas.
15752 * </p>
Joe Fernandez558459f2011-10-13 16:47:36 -070015753 *
15754 * <div class="special reference">
15755 * <h3>Developer Guides</h3>
15756 * <p>For a guide to implementing drag and drop features, read the
15757 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
15758 * </div>
Christopher Tate2c095f32010-10-04 14:13:40 -070015759 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015760 public static class DragShadowBuilder {
Christopher Tatea0374192010-10-05 13:06:41 -070015761 private final WeakReference<View> mView;
Christopher Tate2c095f32010-10-04 14:13:40 -070015762
15763 /**
Joe Malin32736f02011-01-19 16:14:20 -080015764 * Constructs a shadow image builder based on a View. By default, the resulting drag
15765 * shadow will have the same appearance and dimensions as the View, with the touch point
15766 * over the center of the View.
15767 * @param view A View. Any View in scope can be used.
Christopher Tate2c095f32010-10-04 14:13:40 -070015768 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015769 public DragShadowBuilder(View view) {
Christopher Tatea0374192010-10-05 13:06:41 -070015770 mView = new WeakReference<View>(view);
Christopher Tate2c095f32010-10-04 14:13:40 -070015771 }
15772
Christopher Tate17ed60c2011-01-18 12:50:26 -080015773 /**
15774 * Construct a shadow builder object with no associated View. This
15775 * constructor variant is only useful when the {@link #onProvideShadowMetrics(Point, Point)}
15776 * and {@link #onDrawShadow(Canvas)} methods are also overridden in order
15777 * to supply the drag shadow's dimensions and appearance without
Joe Malin32736f02011-01-19 16:14:20 -080015778 * reference to any View object. If they are not overridden, then the result is an
15779 * invisible drag shadow.
Christopher Tate17ed60c2011-01-18 12:50:26 -080015780 */
15781 public DragShadowBuilder() {
15782 mView = new WeakReference<View>(null);
15783 }
15784
15785 /**
15786 * Returns the View object that had been passed to the
15787 * {@link #View.DragShadowBuilder(View)}
15788 * constructor. If that View parameter was {@code null} or if the
15789 * {@link #View.DragShadowBuilder()}
15790 * constructor was used to instantiate the builder object, this method will return
15791 * null.
15792 *
15793 * @return The View object associate with this builder object.
15794 */
Romain Guy5c22a8c2011-05-13 11:48:45 -070015795 @SuppressWarnings({"JavadocReference"})
Chris Tate6b391282010-10-14 15:48:59 -070015796 final public View getView() {
15797 return mView.get();
15798 }
15799
Christopher Tate2c095f32010-10-04 14:13:40 -070015800 /**
Joe Malin32736f02011-01-19 16:14:20 -080015801 * Provides the metrics for the shadow image. These include the dimensions of
15802 * the shadow image, and the point within that shadow that should
Christopher Tate2c095f32010-10-04 14:13:40 -070015803 * be centered under the touch location while dragging.
15804 * <p>
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015805 * The default implementation sets the dimensions of the shadow to be the
Joe Malin32736f02011-01-19 16:14:20 -080015806 * same as the dimensions of the View itself and centers the shadow under
15807 * the touch point.
15808 * </p>
Christopher Tate2c095f32010-10-04 14:13:40 -070015809 *
Joe Malin32736f02011-01-19 16:14:20 -080015810 * @param shadowSize A {@link android.graphics.Point} containing the width and height
15811 * of the shadow image. Your application must set {@link android.graphics.Point#x} to the
15812 * desired width and must set {@link android.graphics.Point#y} to the desired height of the
15813 * image.
15814 *
15815 * @param shadowTouchPoint A {@link android.graphics.Point} for the position within the
15816 * shadow image that should be underneath the touch point during the drag and drop
15817 * operation. Your application must set {@link android.graphics.Point#x} to the
15818 * X coordinate and {@link android.graphics.Point#y} to the Y coordinate of this position.
Christopher Tate2c095f32010-10-04 14:13:40 -070015819 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015820 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) {
Christopher Tatea0374192010-10-05 13:06:41 -070015821 final View view = mView.get();
15822 if (view != null) {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015823 shadowSize.set(view.getWidth(), view.getHeight());
15824 shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
Christopher Tatea0374192010-10-05 13:06:41 -070015825 } else {
15826 Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view");
15827 }
Christopher Tate2c095f32010-10-04 14:13:40 -070015828 }
15829
15830 /**
Joe Malin32736f02011-01-19 16:14:20 -080015831 * Draws the shadow image. The system creates the {@link android.graphics.Canvas} object
15832 * based on the dimensions it received from the
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015833 * {@link #onProvideShadowMetrics(Point, Point)} callback.
Christopher Tate2c095f32010-10-04 14:13:40 -070015834 *
Joe Malin32736f02011-01-19 16:14:20 -080015835 * @param canvas A {@link android.graphics.Canvas} object in which to draw the shadow image.
Christopher Tate2c095f32010-10-04 14:13:40 -070015836 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015837 public void onDrawShadow(Canvas canvas) {
Christopher Tatea0374192010-10-05 13:06:41 -070015838 final View view = mView.get();
15839 if (view != null) {
15840 view.draw(canvas);
15841 } else {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015842 Log.e(View.VIEW_LOG_TAG, "Asked to draw drag shadow but no view");
Christopher Tatea0374192010-10-05 13:06:41 -070015843 }
Christopher Tate2c095f32010-10-04 14:13:40 -070015844 }
15845 }
15846
15847 /**
Joe Malin32736f02011-01-19 16:14:20 -080015848 * Starts a drag and drop operation. When your application calls this method, it passes a
15849 * {@link android.view.View.DragShadowBuilder} object to the system. The
15850 * system calls this object's {@link DragShadowBuilder#onProvideShadowMetrics(Point, Point)}
15851 * to get metrics for the drag shadow, and then calls the object's
15852 * {@link DragShadowBuilder#onDrawShadow(Canvas)} to draw the drag shadow itself.
15853 * <p>
15854 * Once the system has the drag shadow, it begins the drag and drop operation by sending
15855 * drag events to all the View objects in your application that are currently visible. It does
15856 * this either by calling the View object's drag listener (an implementation of
15857 * {@link android.view.View.OnDragListener#onDrag(View,DragEvent) onDrag()} or by calling the
15858 * View object's {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} method.
15859 * Both are passed a {@link android.view.DragEvent} object that has a
15860 * {@link android.view.DragEvent#getAction()} value of
15861 * {@link android.view.DragEvent#ACTION_DRAG_STARTED}.
15862 * </p>
15863 * <p>
15864 * Your application can invoke startDrag() on any attached View object. The View object does not
15865 * need to be the one used in {@link android.view.View.DragShadowBuilder}, nor does it need to
15866 * be related to the View the user selected for dragging.
15867 * </p>
15868 * @param data A {@link android.content.ClipData} object pointing to the data to be
15869 * transferred by the drag and drop operation.
15870 * @param shadowBuilder A {@link android.view.View.DragShadowBuilder} object for building the
15871 * drag shadow.
15872 * @param myLocalState An {@link java.lang.Object} containing local data about the drag and
15873 * drop operation. This Object is put into every DragEvent object sent by the system during the
15874 * current drag.
15875 * <p>
15876 * myLocalState is a lightweight mechanism for the sending information from the dragged View
15877 * to the target Views. For example, it can contain flags that differentiate between a
15878 * a copy operation and a move operation.
15879 * </p>
15880 * @param flags Flags that control the drag and drop operation. No flags are currently defined,
15881 * so the parameter should be set to 0.
15882 * @return {@code true} if the method completes successfully, or
15883 * {@code false} if it fails anywhere. Returning {@code false} means the system was unable to
15884 * do a drag, and so no drag operation is in progress.
Christopher Tatea53146c2010-09-07 11:57:52 -070015885 */
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015886 public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015887 Object myLocalState, int flags) {
Christopher Tate2c095f32010-10-04 14:13:40 -070015888 if (ViewDebug.DEBUG_DRAG) {
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015889 Log.d(VIEW_LOG_TAG, "startDrag: data=" + data + " flags=" + flags);
Christopher Tatea53146c2010-09-07 11:57:52 -070015890 }
15891 boolean okay = false;
15892
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015893 Point shadowSize = new Point();
15894 Point shadowTouchPoint = new Point();
15895 shadowBuilder.onProvideShadowMetrics(shadowSize, shadowTouchPoint);
Christopher Tate2c095f32010-10-04 14:13:40 -070015896
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015897 if ((shadowSize.x < 0) || (shadowSize.y < 0) ||
15898 (shadowTouchPoint.x < 0) || (shadowTouchPoint.y < 0)) {
15899 throw new IllegalStateException("Drag shadow dimensions must not be negative");
Christopher Tate2c095f32010-10-04 14:13:40 -070015900 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015901
Chris Tatea32dcf72010-10-14 12:13:50 -070015902 if (ViewDebug.DEBUG_DRAG) {
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015903 Log.d(VIEW_LOG_TAG, "drag shadow: width=" + shadowSize.x + " height=" + shadowSize.y
15904 + " shadowX=" + shadowTouchPoint.x + " shadowY=" + shadowTouchPoint.y);
Chris Tatea32dcf72010-10-14 12:13:50 -070015905 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015906 Surface surface = new Surface();
15907 try {
15908 IBinder token = mAttachInfo.mSession.prepareDrag(mAttachInfo.mWindow,
Christopher Tate02d2b3b2011-01-10 20:43:53 -080015909 flags, shadowSize.x, shadowSize.y, surface);
Christopher Tate2c095f32010-10-04 14:13:40 -070015910 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "prepareDrag returned token=" + token
Christopher Tatea53146c2010-09-07 11:57:52 -070015911 + " surface=" + surface);
15912 if (token != null) {
15913 Canvas canvas = surface.lockCanvas(null);
Romain Guy0bb56672010-10-01 00:25:02 -070015914 try {
Chris Tate6b391282010-10-14 15:48:59 -070015915 canvas.drawColor(0, PorterDuff.Mode.CLEAR);
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015916 shadowBuilder.onDrawShadow(canvas);
Romain Guy0bb56672010-10-01 00:25:02 -070015917 } finally {
15918 surface.unlockCanvasAndPost(canvas);
15919 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015920
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070015921 final ViewRootImpl root = getViewRootImpl();
Christopher Tate407b4e92010-11-30 17:14:08 -080015922
15923 // Cache the local state object for delivery with DragEvents
15924 root.setLocalDragState(myLocalState);
15925
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015926 // repurpose 'shadowSize' for the last touch point
15927 root.getLastTouchPoint(shadowSize);
Christopher Tate2c095f32010-10-04 14:13:40 -070015928
Christopher Tatea53146c2010-09-07 11:57:52 -070015929 okay = mAttachInfo.mSession.performDrag(mAttachInfo.mWindow, token,
Christopher Tate36d4c3f2011-01-07 13:34:24 -080015930 shadowSize.x, shadowSize.y,
15931 shadowTouchPoint.x, shadowTouchPoint.y, data);
Christopher Tate2c095f32010-10-04 14:13:40 -070015932 if (ViewDebug.DEBUG_DRAG) Log.d(VIEW_LOG_TAG, "performDrag returned " + okay);
Christopher Tate8f73b5d2011-09-12 15:22:12 -070015933
15934 // Off and running! Release our local surface instance; the drag
15935 // shadow surface is now managed by the system process.
15936 surface.release();
Christopher Tatea53146c2010-09-07 11:57:52 -070015937 }
15938 } catch (Exception e) {
15939 Log.e(VIEW_LOG_TAG, "Unable to initiate drag", e);
15940 surface.destroy();
15941 }
15942
15943 return okay;
15944 }
15945
Christopher Tatea53146c2010-09-07 11:57:52 -070015946 /**
Joe Malin32736f02011-01-19 16:14:20 -080015947 * Handles drag events sent by the system following a call to
15948 * {@link android.view.View#startDrag(ClipData,DragShadowBuilder,Object,int) startDrag()}.
15949 *<p>
15950 * When the system calls this method, it passes a
15951 * {@link android.view.DragEvent} object. A call to
15952 * {@link android.view.DragEvent#getAction()} returns one of the action type constants defined
15953 * in DragEvent. The method uses these to determine what is happening in the drag and drop
15954 * operation.
15955 * @param event The {@link android.view.DragEvent} sent by the system.
15956 * The {@link android.view.DragEvent#getAction()} method returns an action type constant defined
15957 * in DragEvent, indicating the type of drag event represented by this object.
15958 * @return {@code true} if the method was successful, otherwise {@code false}.
15959 * <p>
15960 * The method should return {@code true} in response to an action type of
15961 * {@link android.view.DragEvent#ACTION_DRAG_STARTED} to receive drag events for the current
15962 * operation.
15963 * </p>
15964 * <p>
15965 * The method should also return {@code true} in response to an action type of
15966 * {@link android.view.DragEvent#ACTION_DROP} if it consumed the drop, or
15967 * {@code false} if it didn't.
15968 * </p>
Christopher Tatea53146c2010-09-07 11:57:52 -070015969 */
Christopher Tate5ada6cb2010-10-05 14:15:29 -070015970 public boolean onDragEvent(DragEvent event) {
Christopher Tatea53146c2010-09-07 11:57:52 -070015971 return false;
15972 }
15973
15974 /**
Joe Malin32736f02011-01-19 16:14:20 -080015975 * Detects if this View is enabled and has a drag event listener.
15976 * If both are true, then it calls the drag event listener with the
15977 * {@link android.view.DragEvent} it received. If the drag event listener returns
15978 * {@code true}, then dispatchDragEvent() returns {@code true}.
15979 * <p>
15980 * For all other cases, the method calls the
15981 * {@link android.view.View#onDragEvent(DragEvent) onDragEvent()} drag event handler
15982 * method and returns its result.
15983 * </p>
15984 * <p>
15985 * This ensures that a drag event is always consumed, even if the View does not have a drag
15986 * event listener. However, if the View has a listener and the listener returns true, then
15987 * onDragEvent() is not called.
15988 * </p>
Christopher Tatea53146c2010-09-07 11:57:52 -070015989 */
15990 public boolean dispatchDragEvent(DragEvent event) {
Romain Guy676b1732011-02-14 14:45:33 -080015991 //noinspection SimplifiableIfStatement
Dianne Hackborn0500b3c2011-11-01 15:28:43 -070015992 ListenerInfo li = mListenerInfo;
15993 if (li != null && li.mOnDragListener != null && (mViewFlags & ENABLED_MASK) == ENABLED
15994 && li.mOnDragListener.onDrag(this, event)) {
Chris Tate32affef2010-10-18 15:29:21 -070015995 return true;
15996 }
Christopher Tatea53146c2010-09-07 11:57:52 -070015997 return onDragEvent(event);
15998 }
15999
Christopher Tate3d4bf172011-03-28 16:16:46 -070016000 boolean canAcceptDrag() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016001 return (mPrivateFlags2 & PFLAG2_DRAG_CAN_ACCEPT) != 0;
Christopher Tate3d4bf172011-03-28 16:16:46 -070016002 }
16003
Christopher Tatea53146c2010-09-07 11:57:52 -070016004 /**
Dianne Hackbornffa42482009-09-23 22:20:11 -070016005 * This needs to be a better API (NOT ON VIEW) before it is exposed. If
16006 * it is ever exposed at all.
Dianne Hackborn29e4a3c2009-09-30 22:35:40 -070016007 * @hide
Dianne Hackbornffa42482009-09-23 22:20:11 -070016008 */
16009 public void onCloseSystemDialogs(String reason) {
16010 }
Joe Malin32736f02011-01-19 16:14:20 -080016011
Dianne Hackbornffa42482009-09-23 22:20:11 -070016012 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016013 * Given a Drawable whose bounds have been set to draw into this view,
Romain Guy5c22a8c2011-05-13 11:48:45 -070016014 * update a Region being computed for
16015 * {@link #gatherTransparentRegion(android.graphics.Region)} so
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016016 * that any non-transparent parts of the Drawable are removed from the
16017 * given transparent region.
16018 *
16019 * @param dr The Drawable whose transparency is to be applied to the region.
16020 * @param region A Region holding the current transparency information,
16021 * where any parts of the region that are set are considered to be
16022 * transparent. On return, this region will be modified to have the
16023 * transparency information reduced by the corresponding parts of the
16024 * Drawable that are not transparent.
16025 * {@hide}
16026 */
16027 public void applyDrawableToTransparentRegion(Drawable dr, Region region) {
16028 if (DBG) {
16029 Log.i("View", "Getting transparent region for: " + this);
16030 }
16031 final Region r = dr.getTransparentRegion();
16032 final Rect db = dr.getBounds();
16033 final AttachInfo attachInfo = mAttachInfo;
16034 if (r != null && attachInfo != null) {
16035 final int w = getRight()-getLeft();
16036 final int h = getBottom()-getTop();
16037 if (db.left > 0) {
16038 //Log.i("VIEW", "Drawable left " + db.left + " > view 0");
16039 r.op(0, 0, db.left, h, Region.Op.UNION);
16040 }
16041 if (db.right < w) {
16042 //Log.i("VIEW", "Drawable right " + db.right + " < view " + w);
16043 r.op(db.right, 0, w, h, Region.Op.UNION);
16044 }
16045 if (db.top > 0) {
16046 //Log.i("VIEW", "Drawable top " + db.top + " > view 0");
16047 r.op(0, 0, w, db.top, Region.Op.UNION);
16048 }
16049 if (db.bottom < h) {
16050 //Log.i("VIEW", "Drawable bottom " + db.bottom + " < view " + h);
16051 r.op(0, db.bottom, w, h, Region.Op.UNION);
16052 }
16053 final int[] location = attachInfo.mTransparentLocation;
16054 getLocationInWindow(location);
16055 r.translate(location[0], location[1]);
16056 region.op(r, Region.Op.INTERSECT);
16057 } else {
16058 region.op(db, Region.Op.DIFFERENCE);
16059 }
16060 }
16061
Patrick Dubroye0a799a2011-05-04 16:19:22 -070016062 private void checkForLongClick(int delayOffset) {
16063 if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) {
16064 mHasPerformedLongPress = false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016065
Patrick Dubroye0a799a2011-05-04 16:19:22 -070016066 if (mPendingCheckForLongPress == null) {
16067 mPendingCheckForLongPress = new CheckForLongPress();
16068 }
16069 mPendingCheckForLongPress.rememberWindowAttachCount();
16070 postDelayed(mPendingCheckForLongPress,
16071 ViewConfiguration.getLongPressTimeout() - delayOffset);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016072 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016073 }
16074
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016075 /**
16076 * Inflate a view from an XML resource. This convenience method wraps the {@link
16077 * LayoutInflater} class, which provides a full range of options for view inflation.
16078 *
16079 * @param context The Context object for your activity or application.
16080 * @param resource The resource ID to inflate
16081 * @param root A view group that will be the parent. Used to properly inflate the
16082 * layout_* parameters.
16083 * @see LayoutInflater
16084 */
16085 public static View inflate(Context context, int resource, ViewGroup root) {
16086 LayoutInflater factory = LayoutInflater.from(context);
16087 return factory.inflate(resource, root);
16088 }
Romain Guy33e72ae2010-07-17 12:40:29 -070016089
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016090 /**
Adam Powell637d3372010-08-25 14:37:03 -070016091 * Scroll the view with standard behavior for scrolling beyond the normal
16092 * content boundaries. Views that call this method should override
16093 * {@link #onOverScrolled(int, int, boolean, boolean)} to respond to the
16094 * results of an over-scroll operation.
16095 *
16096 * Views can use this method to handle any touch or fling-based scrolling.
16097 *
16098 * @param deltaX Change in X in pixels
16099 * @param deltaY Change in Y in pixels
16100 * @param scrollX Current X scroll value in pixels before applying deltaX
16101 * @param scrollY Current Y scroll value in pixels before applying deltaY
16102 * @param scrollRangeX Maximum content scroll range along the X axis
16103 * @param scrollRangeY Maximum content scroll range along the Y axis
16104 * @param maxOverScrollX Number of pixels to overscroll by in either direction
16105 * along the X axis.
16106 * @param maxOverScrollY Number of pixels to overscroll by in either direction
16107 * along the Y axis.
16108 * @param isTouchEvent true if this scroll operation is the result of a touch event.
16109 * @return true if scrolling was clamped to an over-scroll boundary along either
16110 * axis, false otherwise.
16111 */
Romain Guy7b5b6ab2011-03-14 18:05:08 -070016112 @SuppressWarnings({"UnusedParameters"})
Adam Powell637d3372010-08-25 14:37:03 -070016113 protected boolean overScrollBy(int deltaX, int deltaY,
16114 int scrollX, int scrollY,
16115 int scrollRangeX, int scrollRangeY,
16116 int maxOverScrollX, int maxOverScrollY,
16117 boolean isTouchEvent) {
16118 final int overScrollMode = mOverScrollMode;
16119 final boolean canScrollHorizontal =
16120 computeHorizontalScrollRange() > computeHorizontalScrollExtent();
16121 final boolean canScrollVertical =
16122 computeVerticalScrollRange() > computeVerticalScrollExtent();
16123 final boolean overScrollHorizontal = overScrollMode == OVER_SCROLL_ALWAYS ||
16124 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollHorizontal);
16125 final boolean overScrollVertical = overScrollMode == OVER_SCROLL_ALWAYS ||
16126 (overScrollMode == OVER_SCROLL_IF_CONTENT_SCROLLS && canScrollVertical);
16127
16128 int newScrollX = scrollX + deltaX;
16129 if (!overScrollHorizontal) {
16130 maxOverScrollX = 0;
16131 }
16132
16133 int newScrollY = scrollY + deltaY;
16134 if (!overScrollVertical) {
16135 maxOverScrollY = 0;
16136 }
16137
16138 // Clamp values if at the limits and record
16139 final int left = -maxOverScrollX;
16140 final int right = maxOverScrollX + scrollRangeX;
16141 final int top = -maxOverScrollY;
16142 final int bottom = maxOverScrollY + scrollRangeY;
16143
16144 boolean clampedX = false;
16145 if (newScrollX > right) {
16146 newScrollX = right;
16147 clampedX = true;
16148 } else if (newScrollX < left) {
16149 newScrollX = left;
16150 clampedX = true;
16151 }
16152
16153 boolean clampedY = false;
16154 if (newScrollY > bottom) {
16155 newScrollY = bottom;
16156 clampedY = true;
16157 } else if (newScrollY < top) {
16158 newScrollY = top;
16159 clampedY = true;
16160 }
16161
16162 onOverScrolled(newScrollX, newScrollY, clampedX, clampedY);
16163
16164 return clampedX || clampedY;
16165 }
16166
16167 /**
16168 * Called by {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)} to
16169 * respond to the results of an over-scroll operation.
16170 *
16171 * @param scrollX New X scroll value in pixels
16172 * @param scrollY New Y scroll value in pixels
16173 * @param clampedX True if scrollX was clamped to an over-scroll boundary
16174 * @param clampedY True if scrollY was clamped to an over-scroll boundary
16175 */
16176 protected void onOverScrolled(int scrollX, int scrollY,
16177 boolean clampedX, boolean clampedY) {
16178 // Intentionally empty.
16179 }
16180
16181 /**
16182 * Returns the over-scroll mode for this view. The result will be
16183 * one of {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16184 * (allow over-scrolling only if the view content is larger than the container),
16185 * or {@link #OVER_SCROLL_NEVER}.
16186 *
16187 * @return This view's over-scroll mode.
16188 */
16189 public int getOverScrollMode() {
16190 return mOverScrollMode;
16191 }
16192
16193 /**
16194 * Set the over-scroll mode for this view. Valid over-scroll modes are
16195 * {@link #OVER_SCROLL_ALWAYS} (default), {@link #OVER_SCROLL_IF_CONTENT_SCROLLS}
16196 * (allow over-scrolling only if the view content is larger than the container),
16197 * or {@link #OVER_SCROLL_NEVER}.
16198 *
16199 * Setting the over-scroll mode of a view will have an effect only if the
16200 * view is capable of scrolling.
16201 *
16202 * @param overScrollMode The new over-scroll mode for this view.
16203 */
16204 public void setOverScrollMode(int overScrollMode) {
16205 if (overScrollMode != OVER_SCROLL_ALWAYS &&
16206 overScrollMode != OVER_SCROLL_IF_CONTENT_SCROLLS &&
16207 overScrollMode != OVER_SCROLL_NEVER) {
16208 throw new IllegalArgumentException("Invalid overscroll mode " + overScrollMode);
16209 }
16210 mOverScrollMode = overScrollMode;
16211 }
16212
16213 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -080016214 * Gets a scale factor that determines the distance the view should scroll
16215 * vertically in response to {@link MotionEvent#ACTION_SCROLL}.
16216 * @return The vertical scroll scale factor.
16217 * @hide
16218 */
16219 protected float getVerticalScrollFactor() {
16220 if (mVerticalScrollFactor == 0) {
16221 TypedValue outValue = new TypedValue();
16222 if (!mContext.getTheme().resolveAttribute(
16223 com.android.internal.R.attr.listPreferredItemHeight, outValue, true)) {
16224 throw new IllegalStateException(
16225 "Expected theme to define listPreferredItemHeight.");
16226 }
16227 mVerticalScrollFactor = outValue.getDimension(
16228 mContext.getResources().getDisplayMetrics());
16229 }
16230 return mVerticalScrollFactor;
16231 }
16232
16233 /**
16234 * Gets a scale factor that determines the distance the view should scroll
16235 * horizontally in response to {@link MotionEvent#ACTION_SCROLL}.
16236 * @return The horizontal scroll scale factor.
16237 * @hide
16238 */
16239 protected float getHorizontalScrollFactor() {
16240 // TODO: Should use something else.
16241 return getVerticalScrollFactor();
16242 }
16243
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016244 /**
16245 * Return the value specifying the text direction or policy that was set with
16246 * {@link #setTextDirection(int)}.
16247 *
16248 * @return the defined text direction. It can be one of:
16249 *
16250 * {@link #TEXT_DIRECTION_INHERIT},
16251 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16252 * {@link #TEXT_DIRECTION_ANY_RTL},
16253 * {@link #TEXT_DIRECTION_LTR},
16254 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016255 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016256 */
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016257 @ViewDebug.ExportedProperty(category = "text", mapping = {
16258 @ViewDebug.IntToString(from = TEXT_DIRECTION_INHERIT, to = "INHERIT"),
16259 @ViewDebug.IntToString(from = TEXT_DIRECTION_FIRST_STRONG, to = "FIRST_STRONG"),
16260 @ViewDebug.IntToString(from = TEXT_DIRECTION_ANY_RTL, to = "ANY_RTL"),
16261 @ViewDebug.IntToString(from = TEXT_DIRECTION_LTR, to = "LTR"),
16262 @ViewDebug.IntToString(from = TEXT_DIRECTION_RTL, to = "RTL"),
16263 @ViewDebug.IntToString(from = TEXT_DIRECTION_LOCALE, to = "LOCALE")
16264 })
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016265 public int getTextDirection() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016266 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_MASK) >> PFLAG2_TEXT_DIRECTION_MASK_SHIFT;
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016267 }
16268
16269 /**
16270 * Set the text direction.
16271 *
16272 * @param textDirection the direction to set. Should be one of:
16273 *
16274 * {@link #TEXT_DIRECTION_INHERIT},
16275 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16276 * {@link #TEXT_DIRECTION_ANY_RTL},
16277 * {@link #TEXT_DIRECTION_LTR},
16278 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016279 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016280 */
16281 public void setTextDirection(int textDirection) {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016282 if (getTextDirection() != textDirection) {
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016283 // Reset the current text direction and the resolved one
Dianne Hackborn4702a852012-08-17 15:18:29 -070016284 mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016285 resetResolvedTextDirection();
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016286 // Set the new text direction
Dianne Hackborn4702a852012-08-17 15:18:29 -070016287 mPrivateFlags2 |= ((textDirection << PFLAG2_TEXT_DIRECTION_MASK_SHIFT) & PFLAG2_TEXT_DIRECTION_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016288 // Refresh
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016289 requestLayout();
Fabrice Di Meglio827d5c02012-03-23 15:13:41 -070016290 invalidate(true);
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016291 }
16292 }
16293
16294 /**
16295 * Return the resolved text direction.
16296 *
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016297 * This needs resolution if the value is TEXT_DIRECTION_INHERIT. The resolution matches
16298 * {@link #getTextDirection()}if it is not TEXT_DIRECTION_INHERIT, otherwise resolution proceeds
16299 * up the parent chain of the view. if there is no parent, then it will return the default
16300 * {@link #TEXT_DIRECTION_FIRST_STRONG}.
16301 *
16302 * @return the resolved text direction. Returns one of:
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016303 *
Doug Feltcb3791202011-07-07 11:57:48 -070016304 * {@link #TEXT_DIRECTION_FIRST_STRONG}
16305 * {@link #TEXT_DIRECTION_ANY_RTL},
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016306 * {@link #TEXT_DIRECTION_LTR},
16307 * {@link #TEXT_DIRECTION_RTL},
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016308 * {@link #TEXT_DIRECTION_LOCALE}
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016309 */
16310 public int getResolvedTextDirection() {
Fabrice Di Meglio22ab7752012-03-23 16:39:26 -070016311 // The text direction will be resolved only if needed
Dianne Hackborn4702a852012-08-17 15:18:29 -070016312 if ((mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED) != PFLAG2_TEXT_DIRECTION_RESOLVED) {
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016313 resolveTextDirection();
16314 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070016315 return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016316 }
16317
16318 /**
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016319 * Resolve the text direction. Will call {@link View#onResolvedTextDirectionChanged} when
16320 * resolution is done.
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016321 */
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016322 public void resolveTextDirection() {
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016323 // Reset any previous text direction resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070016324 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016325
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016326 if (hasRtlSupport()) {
16327 // Set resolved text direction flag depending on text direction flag
16328 final int textDirection = getTextDirection();
16329 switch(textDirection) {
16330 case TEXT_DIRECTION_INHERIT:
16331 if (canResolveTextDirection()) {
16332 ViewGroup viewGroup = ((ViewGroup) mParent);
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016333
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016334 // Set current resolved direction to the same value as the parent's one
16335 final int parentResolvedDirection = viewGroup.getResolvedTextDirection();
16336 switch (parentResolvedDirection) {
16337 case TEXT_DIRECTION_FIRST_STRONG:
16338 case TEXT_DIRECTION_ANY_RTL:
16339 case TEXT_DIRECTION_LTR:
16340 case TEXT_DIRECTION_RTL:
16341 case TEXT_DIRECTION_LOCALE:
16342 mPrivateFlags2 |=
Dianne Hackborn4702a852012-08-17 15:18:29 -070016343 (parentResolvedDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016344 break;
16345 default:
16346 // Default resolved direction is "first strong" heuristic
Dianne Hackborn4702a852012-08-17 15:18:29 -070016347 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016348 }
16349 } else {
16350 // We cannot do the resolution if there is no parent, so use the default one
Dianne Hackborn4702a852012-08-17 15:18:29 -070016351 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016352 }
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016353 break;
16354 case TEXT_DIRECTION_FIRST_STRONG:
16355 case TEXT_DIRECTION_ANY_RTL:
16356 case TEXT_DIRECTION_LTR:
16357 case TEXT_DIRECTION_RTL:
16358 case TEXT_DIRECTION_LOCALE:
16359 // Resolved direction is the same as text direction
Dianne Hackborn4702a852012-08-17 15:18:29 -070016360 mPrivateFlags2 |= (textDirection << PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016361 break;
16362 default:
16363 // Default resolved direction is "first strong" heuristic
Dianne Hackborn4702a852012-08-17 15:18:29 -070016364 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio59dfce82012-04-02 16:17:20 -070016365 }
16366 } else {
16367 // Default resolved direction is "first strong" heuristic
Dianne Hackborn4702a852012-08-17 15:18:29 -070016368 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED_DEFAULT;
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016369 }
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016370
16371 // Set to resolved
Dianne Hackborn4702a852012-08-17 15:18:29 -070016372 mPrivateFlags2 |= PFLAG2_TEXT_DIRECTION_RESOLVED;
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016373 onResolvedTextDirectionChanged();
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016374 }
16375
16376 /**
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016377 * Called when text direction has been resolved. Subclasses that care about text direction
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016378 * resolution should override this method.
16379 *
16380 * The default implementation does nothing.
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016381 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016382 public void onResolvedTextDirectionChanged() {
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016383 }
16384
16385 /**
Fabrice Di Megliob934db72012-03-20 14:33:01 -070016386 * Check if text direction resolution can be done.
16387 *
16388 * @return true if text direction resolution can be done otherwise return false.
16389 */
16390 public boolean canResolveTextDirection() {
16391 switch (getTextDirection()) {
16392 case TEXT_DIRECTION_INHERIT:
16393 return (mParent != null) && (mParent instanceof ViewGroup);
16394 default:
16395 return true;
16396 }
16397 }
16398
16399 /**
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016400 * Reset resolved text direction. Text direction can be resolved with a call to
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016401 * getResolvedTextDirection(). Will call {@link View#onResolvedTextDirectionReset} when
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016402 * reset is done.
16403 */
16404 public void resetResolvedTextDirection() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016405 mPrivateFlags2 &= ~(PFLAG2_TEXT_DIRECTION_RESOLVED | PFLAG2_TEXT_DIRECTION_RESOLVED_MASK);
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016406 onResolvedTextDirectionReset();
Fabrice Di Meglio6d3d5052012-02-15 20:22:56 -080016407 }
16408
16409 /**
16410 * Called when text direction is reset. Subclasses that care about text direction reset should
16411 * override this method and do a reset of the text direction of their children. The default
16412 * implementation does nothing.
16413 */
Fabrice Di Megliodd3ef2c2012-03-01 16:37:17 -080016414 public void onResolvedTextDirectionReset() {
Fabrice Di Meglio22268862011-06-27 18:13:18 -070016415 }
16416
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016417 /**
16418 * Return the value specifying the text alignment or policy that was set with
16419 * {@link #setTextAlignment(int)}.
16420 *
16421 * @return the defined text alignment. It can be one of:
16422 *
16423 * {@link #TEXT_ALIGNMENT_INHERIT},
16424 * {@link #TEXT_ALIGNMENT_GRAVITY},
16425 * {@link #TEXT_ALIGNMENT_CENTER},
16426 * {@link #TEXT_ALIGNMENT_TEXT_START},
16427 * {@link #TEXT_ALIGNMENT_TEXT_END},
16428 * {@link #TEXT_ALIGNMENT_VIEW_START},
16429 * {@link #TEXT_ALIGNMENT_VIEW_END}
16430 */
16431 @ViewDebug.ExportedProperty(category = "text", mapping = {
16432 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16433 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16434 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16435 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16436 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16437 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16438 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16439 })
16440 public int getTextAlignment() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016441 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_MASK) >> PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016442 }
16443
16444 /**
16445 * Set the text alignment.
16446 *
16447 * @param textAlignment The text alignment to set. Should be one of
16448 *
16449 * {@link #TEXT_ALIGNMENT_INHERIT},
16450 * {@link #TEXT_ALIGNMENT_GRAVITY},
16451 * {@link #TEXT_ALIGNMENT_CENTER},
16452 * {@link #TEXT_ALIGNMENT_TEXT_START},
16453 * {@link #TEXT_ALIGNMENT_TEXT_END},
16454 * {@link #TEXT_ALIGNMENT_VIEW_START},
16455 * {@link #TEXT_ALIGNMENT_VIEW_END}
16456 *
16457 * @attr ref android.R.styleable#View_textAlignment
16458 */
16459 public void setTextAlignment(int textAlignment) {
16460 if (textAlignment != getTextAlignment()) {
16461 // Reset the current and resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016462 mPrivateFlags2 &= ~PFLAG2_TEXT_ALIGNMENT_MASK;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016463 resetResolvedTextAlignment();
16464 // Set the new text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016465 mPrivateFlags2 |= ((textAlignment << PFLAG2_TEXT_ALIGNMENT_MASK_SHIFT) & PFLAG2_TEXT_ALIGNMENT_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016466 // Refresh
16467 requestLayout();
16468 invalidate(true);
16469 }
16470 }
16471
16472 /**
16473 * Return the resolved text alignment.
16474 *
16475 * The resolved text alignment. This needs resolution if the value is
16476 * TEXT_ALIGNMENT_INHERIT. The resolution matches {@link #setTextAlignment(int)} if it is
16477 * not TEXT_ALIGNMENT_INHERIT, otherwise resolution proceeds up the parent chain of the view.
16478 *
16479 * @return the resolved text alignment. Returns one of:
16480 *
16481 * {@link #TEXT_ALIGNMENT_GRAVITY},
16482 * {@link #TEXT_ALIGNMENT_CENTER},
16483 * {@link #TEXT_ALIGNMENT_TEXT_START},
16484 * {@link #TEXT_ALIGNMENT_TEXT_END},
16485 * {@link #TEXT_ALIGNMENT_VIEW_START},
16486 * {@link #TEXT_ALIGNMENT_VIEW_END}
16487 */
16488 @ViewDebug.ExportedProperty(category = "text", mapping = {
16489 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
16490 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_GRAVITY, to = "GRAVITY"),
16491 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_START, to = "TEXT_START"),
16492 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_TEXT_END, to = "TEXT_END"),
16493 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_CENTER, to = "CENTER"),
16494 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_START, to = "VIEW_START"),
16495 @ViewDebug.IntToString(from = TEXT_ALIGNMENT_VIEW_END, to = "VIEW_END")
16496 })
16497 public int getResolvedTextAlignment() {
16498 // If text alignment is not resolved, then resolve it
Dianne Hackborn4702a852012-08-17 15:18:29 -070016499 if ((mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED) != PFLAG2_TEXT_ALIGNMENT_RESOLVED) {
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016500 resolveTextAlignment();
16501 }
Dianne Hackborn4702a852012-08-17 15:18:29 -070016502 return (mPrivateFlags2 & PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK) >> PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016503 }
16504
16505 /**
16506 * Resolve the text alignment. Will call {@link View#onResolvedTextAlignmentChanged} when
16507 * resolution is done.
16508 */
16509 public void resolveTextAlignment() {
16510 // Reset any previous text alignment resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070016511 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016512
16513 if (hasRtlSupport()) {
16514 // Set resolved text alignment flag depending on text alignment flag
16515 final int textAlignment = getTextAlignment();
16516 switch (textAlignment) {
16517 case TEXT_ALIGNMENT_INHERIT:
16518 // Check if we can resolve the text alignment
16519 if (canResolveLayoutDirection() && mParent instanceof View) {
16520 View view = (View) mParent;
16521
16522 final int parentResolvedTextAlignment = view.getResolvedTextAlignment();
16523 switch (parentResolvedTextAlignment) {
16524 case TEXT_ALIGNMENT_GRAVITY:
16525 case TEXT_ALIGNMENT_TEXT_START:
16526 case TEXT_ALIGNMENT_TEXT_END:
16527 case TEXT_ALIGNMENT_CENTER:
16528 case TEXT_ALIGNMENT_VIEW_START:
16529 case TEXT_ALIGNMENT_VIEW_END:
16530 // Resolved text alignment is the same as the parent resolved
16531 // text alignment
16532 mPrivateFlags2 |=
Dianne Hackborn4702a852012-08-17 15:18:29 -070016533 (parentResolvedTextAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016534 break;
16535 default:
16536 // Use default resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016537 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016538 }
16539 }
16540 else {
16541 // We cannot do the resolution if there is no parent so use the default
Dianne Hackborn4702a852012-08-17 15:18:29 -070016542 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016543 }
16544 break;
16545 case TEXT_ALIGNMENT_GRAVITY:
16546 case TEXT_ALIGNMENT_TEXT_START:
16547 case TEXT_ALIGNMENT_TEXT_END:
16548 case TEXT_ALIGNMENT_CENTER:
16549 case TEXT_ALIGNMENT_VIEW_START:
16550 case TEXT_ALIGNMENT_VIEW_END:
16551 // Resolved text alignment is the same as text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016552 mPrivateFlags2 |= (textAlignment << PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK_SHIFT);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016553 break;
16554 default:
16555 // Use default resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016556 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016557 }
16558 } else {
16559 // Use default resolved text alignment
Dianne Hackborn4702a852012-08-17 15:18:29 -070016560 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED_DEFAULT;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016561 }
16562
16563 // Set the resolved
Dianne Hackborn4702a852012-08-17 15:18:29 -070016564 mPrivateFlags2 |= PFLAG2_TEXT_ALIGNMENT_RESOLVED;
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016565 onResolvedTextAlignmentChanged();
16566 }
16567
16568 /**
16569 * Check if text alignment resolution can be done.
16570 *
16571 * @return true if text alignment resolution can be done otherwise return false.
16572 */
16573 public boolean canResolveTextAlignment() {
16574 switch (getTextAlignment()) {
16575 case TEXT_DIRECTION_INHERIT:
16576 return (mParent != null);
16577 default:
16578 return true;
16579 }
16580 }
16581
16582 /**
16583 * Called when text alignment has been resolved. Subclasses that care about text alignment
16584 * resolution should override this method.
16585 *
16586 * The default implementation does nothing.
16587 */
16588 public void onResolvedTextAlignmentChanged() {
16589 }
16590
16591 /**
16592 * Reset resolved text alignment. Text alignment can be resolved with a call to
16593 * getResolvedTextAlignment(). Will call {@link View#onResolvedTextAlignmentReset} when
16594 * reset is done.
16595 */
16596 public void resetResolvedTextAlignment() {
16597 // Reset any previous text alignment resolution
Dianne Hackborn4702a852012-08-17 15:18:29 -070016598 mPrivateFlags2 &= ~(PFLAG2_TEXT_ALIGNMENT_RESOLVED | PFLAG2_TEXT_ALIGNMENT_RESOLVED_MASK);
Fabrice Di Meglio9da0f8a2012-03-13 19:37:57 -070016599 onResolvedTextAlignmentReset();
16600 }
16601
16602 /**
16603 * Called when text alignment is reset. Subclasses that care about text alignment reset should
16604 * override this method and do a reset of the text alignment of their children. The default
16605 * implementation does nothing.
16606 */
16607 public void onResolvedTextAlignmentReset() {
16608 }
16609
Adam Powella9108a22012-07-18 11:18:09 -070016610 /**
16611 * Generate a value suitable for use in {@link #setId(int)}.
16612 * This value will not collide with ID values generated at build time by aapt for R.id.
16613 *
16614 * @return a generated ID value
16615 */
16616 public static int generateViewId() {
16617 for (;;) {
16618 final int result = sNextGeneratedId.get();
16619 // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
16620 int newValue = result + 1;
16621 if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
16622 if (sNextGeneratedId.compareAndSet(result, newValue)) {
16623 return result;
16624 }
16625 }
16626 }
16627
Chet Haaseb39f0512011-05-24 14:36:40 -070016628 //
16629 // Properties
16630 //
16631 /**
16632 * A Property wrapper around the <code>alpha</code> functionality handled by the
16633 * {@link View#setAlpha(float)} and {@link View#getAlpha()} methods.
16634 */
Chet Haased47f1532011-12-16 11:18:52 -080016635 public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016636 @Override
16637 public void setValue(View object, float value) {
16638 object.setAlpha(value);
16639 }
16640
16641 @Override
16642 public Float get(View object) {
16643 return object.getAlpha();
16644 }
16645 };
16646
16647 /**
16648 * A Property wrapper around the <code>translationX</code> functionality handled by the
16649 * {@link View#setTranslationX(float)} and {@link View#getTranslationX()} methods.
16650 */
Chet Haased47f1532011-12-16 11:18:52 -080016651 public static final Property<View, Float> TRANSLATION_X = new FloatProperty<View>("translationX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016652 @Override
16653 public void setValue(View object, float value) {
16654 object.setTranslationX(value);
16655 }
16656
16657 @Override
16658 public Float get(View object) {
16659 return object.getTranslationX();
16660 }
16661 };
16662
16663 /**
16664 * A Property wrapper around the <code>translationY</code> functionality handled by the
16665 * {@link View#setTranslationY(float)} and {@link View#getTranslationY()} methods.
16666 */
Chet Haased47f1532011-12-16 11:18:52 -080016667 public static final Property<View, Float> TRANSLATION_Y = new FloatProperty<View>("translationY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016668 @Override
16669 public void setValue(View object, float value) {
16670 object.setTranslationY(value);
16671 }
16672
16673 @Override
16674 public Float get(View object) {
16675 return object.getTranslationY();
16676 }
16677 };
16678
16679 /**
16680 * A Property wrapper around the <code>x</code> functionality handled by the
16681 * {@link View#setX(float)} and {@link View#getX()} methods.
16682 */
Chet Haased47f1532011-12-16 11:18:52 -080016683 public static final Property<View, Float> X = new FloatProperty<View>("x") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016684 @Override
16685 public void setValue(View object, float value) {
16686 object.setX(value);
16687 }
16688
16689 @Override
16690 public Float get(View object) {
16691 return object.getX();
16692 }
16693 };
16694
16695 /**
16696 * A Property wrapper around the <code>y</code> functionality handled by the
16697 * {@link View#setY(float)} and {@link View#getY()} methods.
16698 */
Chet Haased47f1532011-12-16 11:18:52 -080016699 public static final Property<View, Float> Y = new FloatProperty<View>("y") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016700 @Override
16701 public void setValue(View object, float value) {
16702 object.setY(value);
16703 }
16704
16705 @Override
16706 public Float get(View object) {
16707 return object.getY();
16708 }
16709 };
16710
16711 /**
16712 * A Property wrapper around the <code>rotation</code> functionality handled by the
16713 * {@link View#setRotation(float)} and {@link View#getRotation()} methods.
16714 */
Chet Haased47f1532011-12-16 11:18:52 -080016715 public static final Property<View, Float> ROTATION = new FloatProperty<View>("rotation") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016716 @Override
16717 public void setValue(View object, float value) {
16718 object.setRotation(value);
16719 }
16720
16721 @Override
16722 public Float get(View object) {
16723 return object.getRotation();
16724 }
16725 };
16726
16727 /**
16728 * A Property wrapper around the <code>rotationX</code> functionality handled by the
16729 * {@link View#setRotationX(float)} and {@link View#getRotationX()} methods.
16730 */
Chet Haased47f1532011-12-16 11:18:52 -080016731 public static final Property<View, Float> ROTATION_X = new FloatProperty<View>("rotationX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016732 @Override
16733 public void setValue(View object, float value) {
16734 object.setRotationX(value);
16735 }
16736
16737 @Override
16738 public Float get(View object) {
16739 return object.getRotationX();
16740 }
16741 };
16742
16743 /**
16744 * A Property wrapper around the <code>rotationY</code> functionality handled by the
16745 * {@link View#setRotationY(float)} and {@link View#getRotationY()} methods.
16746 */
Chet Haased47f1532011-12-16 11:18:52 -080016747 public static final Property<View, Float> ROTATION_Y = new FloatProperty<View>("rotationY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016748 @Override
16749 public void setValue(View object, float value) {
16750 object.setRotationY(value);
16751 }
16752
16753 @Override
16754 public Float get(View object) {
16755 return object.getRotationY();
16756 }
16757 };
16758
16759 /**
16760 * A Property wrapper around the <code>scaleX</code> functionality handled by the
16761 * {@link View#setScaleX(float)} and {@link View#getScaleX()} methods.
16762 */
Chet Haased47f1532011-12-16 11:18:52 -080016763 public static final Property<View, Float> SCALE_X = new FloatProperty<View>("scaleX") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016764 @Override
16765 public void setValue(View object, float value) {
16766 object.setScaleX(value);
16767 }
16768
16769 @Override
16770 public Float get(View object) {
16771 return object.getScaleX();
16772 }
16773 };
16774
16775 /**
16776 * A Property wrapper around the <code>scaleY</code> functionality handled by the
16777 * {@link View#setScaleY(float)} and {@link View#getScaleY()} methods.
16778 */
Chet Haased47f1532011-12-16 11:18:52 -080016779 public static final Property<View, Float> SCALE_Y = new FloatProperty<View>("scaleY") {
Chet Haaseb39f0512011-05-24 14:36:40 -070016780 @Override
16781 public void setValue(View object, float value) {
16782 object.setScaleY(value);
16783 }
16784
16785 @Override
16786 public Float get(View object) {
16787 return object.getScaleY();
16788 }
16789 };
16790
Jeff Brown33bbfd22011-02-24 20:55:35 -080016791 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016792 * A MeasureSpec encapsulates the layout requirements passed from parent to child.
16793 * Each MeasureSpec represents a requirement for either the width or the height.
16794 * A MeasureSpec is comprised of a size and a mode. There are three possible
16795 * modes:
16796 * <dl>
16797 * <dt>UNSPECIFIED</dt>
16798 * <dd>
16799 * The parent has not imposed any constraint on the child. It can be whatever size
16800 * it wants.
16801 * </dd>
16802 *
16803 * <dt>EXACTLY</dt>
16804 * <dd>
16805 * The parent has determined an exact size for the child. The child is going to be
16806 * given those bounds regardless of how big it wants to be.
16807 * </dd>
16808 *
16809 * <dt>AT_MOST</dt>
16810 * <dd>
16811 * The child can be as large as it wants up to the specified size.
16812 * </dd>
16813 * </dl>
16814 *
16815 * MeasureSpecs are implemented as ints to reduce object allocation. This class
16816 * is provided to pack and unpack the &lt;size, mode&gt; tuple into the int.
16817 */
16818 public static class MeasureSpec {
16819 private static final int MODE_SHIFT = 30;
16820 private static final int MODE_MASK = 0x3 << MODE_SHIFT;
16821
16822 /**
16823 * Measure specification mode: The parent has not imposed any constraint
16824 * on the child. It can be whatever size it wants.
16825 */
16826 public static final int UNSPECIFIED = 0 << MODE_SHIFT;
16827
16828 /**
16829 * Measure specification mode: The parent has determined an exact size
16830 * for the child. The child is going to be given those bounds regardless
16831 * of how big it wants to be.
16832 */
16833 public static final int EXACTLY = 1 << MODE_SHIFT;
16834
16835 /**
16836 * Measure specification mode: The child can be as large as it wants up
16837 * to the specified size.
16838 */
16839 public static final int AT_MOST = 2 << MODE_SHIFT;
16840
16841 /**
16842 * Creates a measure specification based on the supplied size and mode.
16843 *
16844 * The mode must always be one of the following:
16845 * <ul>
16846 * <li>{@link android.view.View.MeasureSpec#UNSPECIFIED}</li>
16847 * <li>{@link android.view.View.MeasureSpec#EXACTLY}</li>
16848 * <li>{@link android.view.View.MeasureSpec#AT_MOST}</li>
16849 * </ul>
16850 *
16851 * @param size the size of the measure specification
16852 * @param mode the mode of the measure specification
16853 * @return the measure specification based on size and mode
16854 */
16855 public static int makeMeasureSpec(int size, int mode) {
16856 return size + mode;
16857 }
16858
16859 /**
16860 * Extracts the mode from the supplied measure specification.
16861 *
16862 * @param measureSpec the measure specification to extract the mode from
16863 * @return {@link android.view.View.MeasureSpec#UNSPECIFIED},
16864 * {@link android.view.View.MeasureSpec#AT_MOST} or
16865 * {@link android.view.View.MeasureSpec#EXACTLY}
16866 */
16867 public static int getMode(int measureSpec) {
16868 return (measureSpec & MODE_MASK);
16869 }
16870
16871 /**
16872 * Extracts the size from the supplied measure specification.
16873 *
16874 * @param measureSpec the measure specification to extract the size from
16875 * @return the size in pixels defined in the supplied measure specification
16876 */
16877 public static int getSize(int measureSpec) {
16878 return (measureSpec & ~MODE_MASK);
16879 }
16880
16881 /**
16882 * Returns a String representation of the specified measure
16883 * specification.
16884 *
16885 * @param measureSpec the measure specification to convert to a String
16886 * @return a String with the following format: "MeasureSpec: MODE SIZE"
16887 */
16888 public static String toString(int measureSpec) {
16889 int mode = getMode(measureSpec);
16890 int size = getSize(measureSpec);
16891
16892 StringBuilder sb = new StringBuilder("MeasureSpec: ");
16893
16894 if (mode == UNSPECIFIED)
16895 sb.append("UNSPECIFIED ");
16896 else if (mode == EXACTLY)
16897 sb.append("EXACTLY ");
16898 else if (mode == AT_MOST)
16899 sb.append("AT_MOST ");
16900 else
16901 sb.append(mode).append(" ");
16902
16903 sb.append(size);
16904 return sb.toString();
16905 }
16906 }
16907
16908 class CheckForLongPress implements Runnable {
16909
16910 private int mOriginalWindowAttachCount;
16911
16912 public void run() {
The Android Open Source Project10592532009-03-18 17:39:46 -070016913 if (isPressed() && (mParent != null)
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016914 && mOriginalWindowAttachCount == mWindowAttachCount) {
16915 if (performLongClick()) {
16916 mHasPerformedLongPress = true;
16917 }
16918 }
16919 }
16920
16921 public void rememberWindowAttachCount() {
16922 mOriginalWindowAttachCount = mWindowAttachCount;
16923 }
16924 }
Joe Malin32736f02011-01-19 16:14:20 -080016925
Adam Powelle14579b2009-12-16 18:39:52 -080016926 private final class CheckForTap implements Runnable {
16927 public void run() {
Dianne Hackborn4702a852012-08-17 15:18:29 -070016928 mPrivateFlags &= ~PFLAG_PREPRESSED;
Adam Powell4d6f0662012-02-21 15:11:11 -080016929 setPressed(true);
Patrick Dubroye0a799a2011-05-04 16:19:22 -070016930 checkForLongClick(ViewConfiguration.getTapTimeout());
Adam Powelle14579b2009-12-16 18:39:52 -080016931 }
16932 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016933
Adam Powella35d7682010-03-12 14:48:13 -080016934 private final class PerformClick implements Runnable {
16935 public void run() {
16936 performClick();
16937 }
16938 }
16939
Dianne Hackborn63042d62011-01-26 18:56:29 -080016940 /** @hide */
16941 public void hackTurnOffWindowResizeAnim(boolean off) {
16942 mAttachInfo.mTurnOffWindowResizeAnim = off;
16943 }
Joe Malin32736f02011-01-19 16:14:20 -080016944
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016945 /**
Chet Haasea00f3862011-02-22 06:34:40 -080016946 * This method returns a ViewPropertyAnimator object, which can be used to animate
16947 * specific properties on this View.
16948 *
16949 * @return ViewPropertyAnimator The ViewPropertyAnimator associated with this View.
16950 */
16951 public ViewPropertyAnimator animate() {
16952 if (mAnimator == null) {
16953 mAnimator = new ViewPropertyAnimator(this);
16954 }
16955 return mAnimator;
16956 }
16957
16958 /**
Jean Chalard405bc512012-05-29 19:12:34 +090016959 * Interface definition for a callback to be invoked when a hardware key event is
16960 * dispatched to this view. The callback will be invoked before the key event is
16961 * given to the view. This is only useful for hardware keyboards; a software input
16962 * method has no obligation to trigger this listener.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016963 */
16964 public interface OnKeyListener {
16965 /**
Jean Chalard405bc512012-05-29 19:12:34 +090016966 * Called when a hardware key is dispatched to a view. This allows listeners to
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016967 * get a chance to respond before the target view.
Jean Chalard405bc512012-05-29 19:12:34 +090016968 * <p>Key presses in software keyboards will generally NOT trigger this method,
16969 * although some may elect to do so in some situations. Do not assume a
16970 * software input method has to be key-based; even if it is, it may use key presses
16971 * in a different way than you expect, so there is no way to reliably catch soft
16972 * input key presses.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016973 *
16974 * @param v The view the key has been dispatched to.
16975 * @param keyCode The code for the physical key that was pressed
16976 * @param event The KeyEvent object containing full information about
16977 * the event.
16978 * @return True if the listener has consumed the event, false otherwise.
16979 */
16980 boolean onKey(View v, int keyCode, KeyEvent event);
16981 }
16982
16983 /**
16984 * Interface definition for a callback to be invoked when a touch event is
16985 * dispatched to this view. The callback will be invoked before the touch
16986 * event is given to the view.
16987 */
16988 public interface OnTouchListener {
16989 /**
16990 * Called when a touch event is dispatched to a view. This allows listeners to
16991 * get a chance to respond before the target view.
16992 *
16993 * @param v The view the touch event has been dispatched to.
16994 * @param event The MotionEvent object containing full information about
16995 * the event.
16996 * @return True if the listener has consumed the event, false otherwise.
16997 */
16998 boolean onTouch(View v, MotionEvent event);
16999 }
17000
17001 /**
Jeff Brown10b62902011-06-20 16:40:37 -070017002 * Interface definition for a callback to be invoked when a hover event is
17003 * dispatched to this view. The callback will be invoked before the hover
17004 * event is given to the view.
17005 */
17006 public interface OnHoverListener {
17007 /**
17008 * Called when a hover event is dispatched to a view. This allows listeners to
17009 * get a chance to respond before the target view.
17010 *
17011 * @param v The view the hover event has been dispatched to.
17012 * @param event The MotionEvent object containing full information about
17013 * the event.
17014 * @return True if the listener has consumed the event, false otherwise.
17015 */
17016 boolean onHover(View v, MotionEvent event);
17017 }
17018
17019 /**
Jeff Brown33bbfd22011-02-24 20:55:35 -080017020 * Interface definition for a callback to be invoked when a generic motion event is
17021 * dispatched to this view. The callback will be invoked before the generic motion
17022 * event is given to the view.
17023 */
17024 public interface OnGenericMotionListener {
17025 /**
17026 * Called when a generic motion event is dispatched to a view. This allows listeners to
17027 * get a chance to respond before the target view.
17028 *
17029 * @param v The view the generic motion event has been dispatched to.
17030 * @param event The MotionEvent object containing full information about
17031 * the event.
17032 * @return True if the listener has consumed the event, false otherwise.
17033 */
17034 boolean onGenericMotion(View v, MotionEvent event);
17035 }
17036
17037 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017038 * Interface definition for a callback to be invoked when a view has been clicked and held.
17039 */
17040 public interface OnLongClickListener {
17041 /**
17042 * Called when a view has been clicked and held.
17043 *
17044 * @param v The view that was clicked and held.
17045 *
Brad Fitzpatrick69ea4e12011-01-05 11:13:40 -080017046 * @return true if the callback consumed the long click, false otherwise.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017047 */
17048 boolean onLongClick(View v);
17049 }
17050
17051 /**
Chris Tate32affef2010-10-18 15:29:21 -070017052 * Interface definition for a callback to be invoked when a drag is being dispatched
17053 * to this view. The callback will be invoked before the hosting view's own
17054 * onDrag(event) method. If the listener wants to fall back to the hosting view's
17055 * onDrag(event) behavior, it should return 'false' from this callback.
Joe Fernandez558459f2011-10-13 16:47:36 -070017056 *
17057 * <div class="special reference">
17058 * <h3>Developer Guides</h3>
17059 * <p>For a guide to implementing drag and drop features, read the
17060 * <a href="{@docRoot}guide/topics/ui/drag-drop.html">Drag and Drop</a> developer guide.</p>
17061 * </div>
Chris Tate32affef2010-10-18 15:29:21 -070017062 */
17063 public interface OnDragListener {
17064 /**
17065 * Called when a drag event is dispatched to a view. This allows listeners
17066 * to get a chance to override base View behavior.
17067 *
Joe Malin32736f02011-01-19 16:14:20 -080017068 * @param v The View that received the drag event.
17069 * @param event The {@link android.view.DragEvent} object for the drag event.
17070 * @return {@code true} if the drag event was handled successfully, or {@code false}
17071 * if the drag event was not handled. Note that {@code false} will trigger the View
17072 * to call its {@link #onDragEvent(DragEvent) onDragEvent()} handler.
Chris Tate32affef2010-10-18 15:29:21 -070017073 */
17074 boolean onDrag(View v, DragEvent event);
17075 }
17076
17077 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017078 * Interface definition for a callback to be invoked when the focus state of
17079 * a view changed.
17080 */
17081 public interface OnFocusChangeListener {
17082 /**
17083 * Called when the focus state of a view has changed.
17084 *
17085 * @param v The view whose state has changed.
17086 * @param hasFocus The new focus state of v.
17087 */
17088 void onFocusChange(View v, boolean hasFocus);
17089 }
17090
17091 /**
17092 * Interface definition for a callback to be invoked when a view is clicked.
17093 */
17094 public interface OnClickListener {
17095 /**
17096 * Called when a view has been clicked.
17097 *
17098 * @param v The view that was clicked.
17099 */
17100 void onClick(View v);
17101 }
17102
17103 /**
17104 * Interface definition for a callback to be invoked when the context menu
17105 * for this view is being built.
17106 */
17107 public interface OnCreateContextMenuListener {
17108 /**
17109 * Called when the context menu for this view is being built. It is not
17110 * safe to hold onto the menu after this method returns.
17111 *
17112 * @param menu The context menu that is being built
17113 * @param v The view for which the context menu is being built
17114 * @param menuInfo Extra information about the item for which the
17115 * context menu should be shown. This information will vary
17116 * depending on the class of v.
17117 */
17118 void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
17119 }
17120
Joe Onorato664644d2011-01-23 17:53:23 -080017121 /**
17122 * Interface definition for a callback to be invoked when the status bar changes
Dianne Hackborn9a230e02011-10-06 11:51:27 -070017123 * visibility. This reports <strong>global</strong> changes to the system UI
Dianne Hackborncf675782012-05-10 15:07:24 -070017124 * state, not what the application is requesting.
Joe Onorato664644d2011-01-23 17:53:23 -080017125 *
Philip Milne6c8ea062012-04-03 17:38:43 -070017126 * @see View#setOnSystemUiVisibilityChangeListener(android.view.View.OnSystemUiVisibilityChangeListener)
Joe Onorato664644d2011-01-23 17:53:23 -080017127 */
17128 public interface OnSystemUiVisibilityChangeListener {
17129 /**
17130 * Called when the status bar changes visibility because of a call to
Romain Guy5c22a8c2011-05-13 11:48:45 -070017131 * {@link View#setSystemUiVisibility(int)}.
Joe Onorato664644d2011-01-23 17:53:23 -080017132 *
Dianne Hackborncf675782012-05-10 15:07:24 -070017133 * @param visibility Bitwise-or of flags {@link #SYSTEM_UI_FLAG_LOW_PROFILE},
17134 * {@link #SYSTEM_UI_FLAG_HIDE_NAVIGATION}, and {@link #SYSTEM_UI_FLAG_FULLSCREEN}.
17135 * This tells you the <strong>global</strong> state of these UI visibility
17136 * flags, not what your app is currently applying.
Joe Onorato664644d2011-01-23 17:53:23 -080017137 */
17138 public void onSystemUiVisibilityChange(int visibility);
17139 }
17140
Adam Powell4afd62b2011-02-18 15:02:18 -080017141 /**
17142 * Interface definition for a callback to be invoked when this view is attached
17143 * or detached from its window.
17144 */
17145 public interface OnAttachStateChangeListener {
17146 /**
17147 * Called when the view is attached to a window.
17148 * @param v The view that was attached
17149 */
17150 public void onViewAttachedToWindow(View v);
17151 /**
17152 * Called when the view is detached from a window.
17153 * @param v The view that was detached
17154 */
17155 public void onViewDetachedFromWindow(View v);
17156 }
17157
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017158 private final class UnsetPressedState implements Runnable {
17159 public void run() {
17160 setPressed(false);
17161 }
17162 }
17163
17164 /**
17165 * Base class for derived classes that want to save and restore their own
17166 * state in {@link android.view.View#onSaveInstanceState()}.
17167 */
17168 public static class BaseSavedState extends AbsSavedState {
17169 /**
17170 * Constructor used when reading from a parcel. Reads the state of the superclass.
17171 *
17172 * @param source
17173 */
17174 public BaseSavedState(Parcel source) {
17175 super(source);
17176 }
17177
17178 /**
17179 * Constructor called by derived classes when creating their SavedState objects
17180 *
17181 * @param superState The state of the superclass of this view
17182 */
17183 public BaseSavedState(Parcelable superState) {
17184 super(superState);
17185 }
17186
17187 public static final Parcelable.Creator<BaseSavedState> CREATOR =
17188 new Parcelable.Creator<BaseSavedState>() {
17189 public BaseSavedState createFromParcel(Parcel in) {
17190 return new BaseSavedState(in);
17191 }
17192
17193 public BaseSavedState[] newArray(int size) {
17194 return new BaseSavedState[size];
17195 }
17196 };
17197 }
17198
17199 /**
17200 * A set of information given to a view when it is attached to its parent
17201 * window.
17202 */
17203 static class AttachInfo {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017204 interface Callbacks {
17205 void playSoundEffect(int effectId);
17206 boolean performHapticFeedback(int effectId, boolean always);
17207 }
17208
17209 /**
17210 * InvalidateInfo is used to post invalidate(int, int, int, int) messages
17211 * to a Handler. This class contains the target (View) to invalidate and
17212 * the coordinates of the dirty rectangle.
17213 *
17214 * For performance purposes, this class also implements a pool of up to
17215 * POOL_LIMIT objects that get reused. This reduces memory allocations
17216 * whenever possible.
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017217 */
Romain Guyd928d682009-03-31 17:52:16 -070017218 static class InvalidateInfo implements Poolable<InvalidateInfo> {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017219 private static final int POOL_LIMIT = 10;
Romain Guy2e9bbce2009-04-01 10:40:10 -070017220 private static final Pool<InvalidateInfo> sPool = Pools.synchronizedPool(
17221 Pools.finitePool(new PoolableManager<InvalidateInfo>() {
Romain Guyd928d682009-03-31 17:52:16 -070017222 public InvalidateInfo newInstance() {
17223 return new InvalidateInfo();
17224 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017225
Romain Guyd928d682009-03-31 17:52:16 -070017226 public void onAcquired(InvalidateInfo element) {
17227 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017228
Romain Guyd928d682009-03-31 17:52:16 -070017229 public void onReleased(InvalidateInfo element) {
Romain Guy40c18f52011-09-01 17:01:18 -070017230 element.target = null;
Romain Guyd928d682009-03-31 17:52:16 -070017231 }
17232 }, POOL_LIMIT)
17233 );
17234
17235 private InvalidateInfo mNext;
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017236 private boolean mIsPooled;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017237
17238 View target;
17239
17240 int left;
17241 int top;
17242 int right;
17243 int bottom;
17244
Romain Guyd928d682009-03-31 17:52:16 -070017245 public void setNextPoolable(InvalidateInfo element) {
17246 mNext = element;
17247 }
17248
17249 public InvalidateInfo getNextPoolable() {
17250 return mNext;
17251 }
17252
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017253 static InvalidateInfo acquire() {
Romain Guyd928d682009-03-31 17:52:16 -070017254 return sPool.acquire();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017255 }
17256
17257 void release() {
Romain Guyd928d682009-03-31 17:52:16 -070017258 sPool.release(this);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017259 }
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017260
17261 public boolean isPooled() {
17262 return mIsPooled;
17263 }
17264
17265 public void setPooled(boolean isPooled) {
17266 mIsPooled = isPooled;
17267 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017268 }
17269
17270 final IWindowSession mSession;
17271
17272 final IWindow mWindow;
17273
17274 final IBinder mWindowToken;
17275
Jeff Brown98365d72012-08-19 20:30:52 -070017276 final Display mDisplay;
17277
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017278 final Callbacks mRootCallbacks;
17279
Romain Guy59a12ca2011-06-09 17:48:21 -070017280 HardwareCanvas mHardwareCanvas;
Chet Haasedaf98e92011-01-10 14:10:36 -080017281
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017282 /**
17283 * The top view of the hierarchy.
17284 */
17285 View mRootView;
Romain Guy8506ab42009-06-11 17:35:47 -070017286
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017287 IBinder mPanelParentWindowToken;
17288 Surface mSurface;
17289
Romain Guyb051e892010-09-28 19:09:36 -070017290 boolean mHardwareAccelerated;
Dianne Hackborn7eec10e2010-11-12 18:03:47 -080017291 boolean mHardwareAccelerationRequested;
Romain Guyb051e892010-09-28 19:09:36 -070017292 HardwareRenderer mHardwareRenderer;
Joe Malin32736f02011-01-19 16:14:20 -080017293
Romain Guy7e4e5612012-03-05 14:37:29 -080017294 boolean mScreenOn;
17295
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017296 /**
Romain Guy8506ab42009-06-11 17:35:47 -070017297 * Scale factor used by the compatibility mode
17298 */
17299 float mApplicationScale;
17300
17301 /**
17302 * Indicates whether the application is in compatibility mode
17303 */
17304 boolean mScalingRequired;
17305
17306 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070017307 * If set, ViewAncestor doesn't use its lame animation for when the window resizes.
Dianne Hackborn63042d62011-01-26 18:56:29 -080017308 */
17309 boolean mTurnOffWindowResizeAnim;
Joe Malin32736f02011-01-19 16:14:20 -080017310
Dianne Hackborn63042d62011-01-26 18:56:29 -080017311 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017312 * Left position of this view's window
17313 */
17314 int mWindowLeft;
17315
17316 /**
17317 * Top position of this view's window
17318 */
17319 int mWindowTop;
17320
17321 /**
Adam Powell26153a32010-11-08 15:22:27 -080017322 * Indicates whether views need to use 32-bit drawing caches
Romain Guy35b38ce2009-10-07 13:38:55 -070017323 */
Adam Powell26153a32010-11-08 15:22:27 -080017324 boolean mUse32BitDrawingCache;
Romain Guy35b38ce2009-10-07 13:38:55 -070017325
17326 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017327 * For windows that are full-screen but using insets to layout inside
17328 * of the screen decorations, these are the current insets for the
17329 * content of the window.
17330 */
17331 final Rect mContentInsets = new Rect();
17332
17333 /**
17334 * For windows that are full-screen but using insets to layout inside
17335 * of the screen decorations, these are the current insets for the
17336 * actual visible parts of the window.
17337 */
17338 final Rect mVisibleInsets = new Rect();
17339
17340 /**
17341 * The internal insets given by this window. This value is
17342 * supplied by the client (through
17343 * {@link ViewTreeObserver.OnComputeInternalInsetsListener}) and will
17344 * be given to the window manager when changed to be used in laying
17345 * out windows behind it.
17346 */
17347 final ViewTreeObserver.InternalInsetsInfo mGivenInternalInsets
17348 = new ViewTreeObserver.InternalInsetsInfo();
17349
17350 /**
17351 * All views in the window's hierarchy that serve as scroll containers,
17352 * used to determine if the window can be resized or must be panned
17353 * to adjust for a soft input area.
17354 */
17355 final ArrayList<View> mScrollContainers = new ArrayList<View>();
17356
Dianne Hackborn83fe3f52009-09-12 23:38:30 -070017357 final KeyEvent.DispatcherState mKeyDispatchState
17358 = new KeyEvent.DispatcherState();
17359
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017360 /**
17361 * Indicates whether the view's window currently has the focus.
17362 */
17363 boolean mHasWindowFocus;
17364
17365 /**
17366 * The current visibility of the window.
17367 */
17368 int mWindowVisibility;
17369
17370 /**
17371 * Indicates the time at which drawing started to occur.
17372 */
17373 long mDrawingTime;
17374
17375 /**
Romain Guy5bcdff42009-05-14 21:27:18 -070017376 * Indicates whether or not ignoring the DIRTY_MASK flags.
17377 */
17378 boolean mIgnoreDirtyState;
17379
17380 /**
Romain Guy02ccac62011-06-24 13:20:23 -070017381 * This flag tracks when the mIgnoreDirtyState flag is set during draw(),
17382 * to avoid clearing that flag prematurely.
17383 */
17384 boolean mSetIgnoreDirtyState = false;
17385
17386 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017387 * Indicates whether the view's window is currently in touch mode.
17388 */
17389 boolean mInTouchMode;
17390
17391 /**
Joe Onoratoc6cc0f82011-04-12 11:53:13 -070017392 * Indicates that ViewAncestor should trigger a global layout change
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017393 * the next time it performs a traversal
17394 */
17395 boolean mRecomputeGlobalAttributes;
17396
17397 /**
Dianne Hackborn9a230e02011-10-06 11:51:27 -070017398 * Always report new attributes at next traversal.
17399 */
17400 boolean mForceReportNewAttributes;
17401
17402 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017403 * Set during a traveral if any views want to keep the screen on.
17404 */
17405 boolean mKeepScreenOn;
17406
17407 /**
Joe Onorato664644d2011-01-23 17:53:23 -080017408 * Bitwise-or of all of the values that views have passed to setSystemUiVisibility().
17409 */
17410 int mSystemUiVisibility;
17411
17412 /**
Dianne Hackborn139e5aa2012-05-05 20:36:38 -070017413 * Hack to force certain system UI visibility flags to be cleared.
17414 */
17415 int mDisabledSystemUiVisibility;
17416
17417 /**
Dianne Hackborncf675782012-05-10 15:07:24 -070017418 * Last global system UI visibility reported by the window manager.
17419 */
17420 int mGlobalSystemUiVisibility;
17421
17422 /**
Joe Onorato664644d2011-01-23 17:53:23 -080017423 * True if a view in this hierarchy has an OnSystemUiVisibilityChangeListener
17424 * attached.
17425 */
17426 boolean mHasSystemUiListeners;
17427
17428 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017429 * Set if the visibility of any views has changed.
17430 */
17431 boolean mViewVisibilityChanged;
17432
17433 /**
17434 * Set to true if a view has been scrolled.
17435 */
17436 boolean mViewScrollChanged;
17437
17438 /**
17439 * Global to the view hierarchy used as a temporary for dealing with
17440 * x/y points in the transparent region computations.
17441 */
17442 final int[] mTransparentLocation = new int[2];
17443
17444 /**
17445 * Global to the view hierarchy used as a temporary for dealing with
17446 * x/y points in the ViewGroup.invalidateChild implementation.
17447 */
17448 final int[] mInvalidateChildLocation = new int[2];
17449
Chet Haasec3aa3612010-06-17 08:50:37 -070017450
17451 /**
17452 * Global to the view hierarchy used as a temporary for dealing with
17453 * x/y location when view is transformed.
17454 */
17455 final float[] mTmpTransformLocation = new float[2];
17456
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017457 /**
17458 * The view tree observer used to dispatch global events like
17459 * layout, pre-draw, touch mode change, etc.
17460 */
17461 final ViewTreeObserver mTreeObserver = new ViewTreeObserver();
17462
17463 /**
17464 * A Canvas used by the view hierarchy to perform bitmap caching.
17465 */
17466 Canvas mCanvas;
17467
17468 /**
Jeff Browna175a5b2012-02-15 19:18:31 -080017469 * The view root impl.
17470 */
17471 final ViewRootImpl mViewRootImpl;
17472
17473 /**
Dianne Hackborn6dd005b2011-07-18 13:22:50 -070017474 * A Handler supplied by a view's {@link android.view.ViewRootImpl}. This
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017475 * handler can be used to pump events in the UI events queue.
17476 */
17477 final Handler mHandler;
17478
17479 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017480 * Temporary for use in computing invalidate rectangles while
17481 * calling up the hierarchy.
17482 */
17483 final Rect mTmpInvalRect = new Rect();
svetoslavganov75986cf2009-05-14 22:28:01 -070017484
17485 /**
Chet Haasec3aa3612010-06-17 08:50:37 -070017486 * Temporary for use in computing hit areas with transformed views
17487 */
17488 final RectF mTmpTransformRect = new RectF();
17489
17490 /**
Chet Haase599913d2012-07-23 16:22:05 -070017491 * Temporary for use in transforming invalidation rect
17492 */
17493 final Matrix mTmpMatrix = new Matrix();
17494
17495 /**
17496 * Temporary for use in transforming invalidation rect
17497 */
17498 final Transformation mTmpTransformation = new Transformation();
17499
17500 /**
svetoslavganov75986cf2009-05-14 22:28:01 -070017501 * Temporary list for use in collecting focusable descendents of a view.
17502 */
Svetoslav Ganov42138042012-03-20 11:51:39 -070017503 final ArrayList<View> mTempArrayList = new ArrayList<View>(24);
svetoslavganov75986cf2009-05-14 22:28:01 -070017504
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017505 /**
Svetoslav Ganov8643aa02011-04-20 12:12:33 -070017506 * The id of the window for accessibility purposes.
17507 */
17508 int mAccessibilityWindowId = View.NO_ID;
17509
17510 /**
Svetoslav Ganov42138042012-03-20 11:51:39 -070017511 * Whether to ingore not exposed for accessibility Views when
17512 * reporting the view tree to accessibility services.
17513 */
17514 boolean mIncludeNotImportantViews;
17515
17516 /**
17517 * The drawable for highlighting accessibility focus.
17518 */
17519 Drawable mAccessibilityFocusDrawable;
17520
17521 /**
Philip Milne10ca24a2012-04-23 15:38:27 -070017522 * Show where the margins, bounds and layout bounds are for each view.
17523 */
Dianne Hackborna53de062012-05-08 18:53:51 -070017524 boolean mDebugLayout = SystemProperties.getBoolean(DEBUG_LAYOUT_PROPERTY, false);
Philip Milne10ca24a2012-04-23 15:38:27 -070017525
17526 /**
Romain Guyab4c4f4f2012-05-06 13:11:24 -070017527 * Point used to compute visible regions.
17528 */
17529 final Point mPoint = new Point();
17530
17531 /**
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017532 * Creates a new set of attachment information with the specified
17533 * events handler and thread.
17534 *
17535 * @param handler the events handler the view must use
17536 */
Jeff Brown98365d72012-08-19 20:30:52 -070017537 AttachInfo(IWindowSession session, IWindow window, Display display,
Jeff Browna175a5b2012-02-15 19:18:31 -080017538 ViewRootImpl viewRootImpl, Handler handler, Callbacks effectPlayer) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017539 mSession = session;
17540 mWindow = window;
17541 mWindowToken = window.asBinder();
Jeff Brown98365d72012-08-19 20:30:52 -070017542 mDisplay = display;
Jeff Browna175a5b2012-02-15 19:18:31 -080017543 mViewRootImpl = viewRootImpl;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017544 mHandler = handler;
17545 mRootCallbacks = effectPlayer;
17546 }
17547 }
17548
17549 /**
17550 * <p>ScrollabilityCache holds various fields used by a View when scrolling
17551 * is supported. This avoids keeping too many unused fields in most
17552 * instances of View.</p>
17553 */
Mike Cleronf116bf82009-09-27 19:14:12 -070017554 private static class ScrollabilityCache implements Runnable {
Joe Malin32736f02011-01-19 16:14:20 -080017555
Mike Cleronf116bf82009-09-27 19:14:12 -070017556 /**
17557 * Scrollbars are not visible
17558 */
17559 public static final int OFF = 0;
17560
17561 /**
17562 * Scrollbars are visible
17563 */
17564 public static final int ON = 1;
17565
17566 /**
17567 * Scrollbars are fading away
17568 */
17569 public static final int FADING = 2;
17570
17571 public boolean fadeScrollBars;
Joe Malin32736f02011-01-19 16:14:20 -080017572
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017573 public int fadingEdgeLength;
Mike Cleronf116bf82009-09-27 19:14:12 -070017574 public int scrollBarDefaultDelayBeforeFade;
17575 public int scrollBarFadeDuration;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017576
17577 public int scrollBarSize;
17578 public ScrollBarDrawable scrollBar;
Mike Cleronf116bf82009-09-27 19:14:12 -070017579 public float[] interpolatorValues;
17580 public View host;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017581
17582 public final Paint paint;
17583 public final Matrix matrix;
17584 public Shader shader;
17585
Mike Cleronf116bf82009-09-27 19:14:12 -070017586 public final Interpolator scrollBarInterpolator = new Interpolator(1, 2);
17587
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017588 private static final float[] OPAQUE = { 255 };
17589 private static final float[] TRANSPARENT = { 0.0f };
Joe Malin32736f02011-01-19 16:14:20 -080017590
Mike Cleronf116bf82009-09-27 19:14:12 -070017591 /**
17592 * When fading should start. This time moves into the future every time
17593 * a new scroll happens. Measured based on SystemClock.uptimeMillis()
17594 */
17595 public long fadeStartTime;
17596
17597
17598 /**
17599 * The current state of the scrollbars: ON, OFF, or FADING
17600 */
17601 public int state = OFF;
17602
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017603 private int mLastColor;
17604
Mike Cleronf116bf82009-09-27 19:14:12 -070017605 public ScrollabilityCache(ViewConfiguration configuration, View host) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017606 fadingEdgeLength = configuration.getScaledFadingEdgeLength();
17607 scrollBarSize = configuration.getScaledScrollBarSize();
Romain Guy35b38ce2009-10-07 13:38:55 -070017608 scrollBarDefaultDelayBeforeFade = ViewConfiguration.getScrollDefaultDelay();
17609 scrollBarFadeDuration = ViewConfiguration.getScrollBarFadeDuration();
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017610
17611 paint = new Paint();
17612 matrix = new Matrix();
17613 // use use a height of 1, and then wack the matrix each time we
17614 // actually use it.
17615 shader = new LinearGradient(0, 0, 0, 1, 0xFF000000, 0, Shader.TileMode.CLAMP);
Romain Guy8506ab42009-06-11 17:35:47 -070017616
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017617 paint.setShader(shader);
17618 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
Mike Cleronf116bf82009-09-27 19:14:12 -070017619 this.host = host;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017620 }
Romain Guy8506ab42009-06-11 17:35:47 -070017621
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017622 public void setFadeColor(int color) {
17623 if (color != 0 && color != mLastColor) {
17624 mLastColor = color;
17625 color |= 0xFF000000;
Romain Guy8506ab42009-06-11 17:35:47 -070017626
Romain Guye55e1a72009-08-27 10:42:26 -070017627 shader = new LinearGradient(0, 0, 0, 1, color | 0xFF000000,
17628 color & 0x00FFFFFF, Shader.TileMode.CLAMP);
Romain Guy8506ab42009-06-11 17:35:47 -070017629
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017630 paint.setShader(shader);
17631 // Restore the default transfer mode (src_over)
17632 paint.setXfermode(null);
17633 }
17634 }
Joe Malin32736f02011-01-19 16:14:20 -080017635
Mike Cleronf116bf82009-09-27 19:14:12 -070017636 public void run() {
Mike Cleron3ecd58c2009-09-28 11:39:02 -070017637 long now = AnimationUtils.currentAnimationTimeMillis();
Mike Cleronf116bf82009-09-27 19:14:12 -070017638 if (now >= fadeStartTime) {
17639
17640 // the animation fades the scrollbars out by changing
17641 // the opacity (alpha) from fully opaque to fully
17642 // transparent
17643 int nextFrame = (int) now;
17644 int framesCount = 0;
17645
17646 Interpolator interpolator = scrollBarInterpolator;
17647
17648 // Start opaque
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017649 interpolator.setKeyFrame(framesCount++, nextFrame, OPAQUE);
Mike Cleronf116bf82009-09-27 19:14:12 -070017650
17651 // End transparent
17652 nextFrame += scrollBarFadeDuration;
Gilles Debunne3dbf55c2010-12-16 10:31:51 -080017653 interpolator.setKeyFrame(framesCount, nextFrame, TRANSPARENT);
Mike Cleronf116bf82009-09-27 19:14:12 -070017654
17655 state = FADING;
17656
17657 // Kick off the fade animation
Romain Guy0fd89bf2011-01-26 15:41:30 -080017658 host.invalidate(true);
Mike Cleronf116bf82009-09-27 19:14:12 -070017659 }
17660 }
Svetoslav Ganova0156172011-06-26 17:55:44 -070017661 }
Mike Cleronf116bf82009-09-27 19:14:12 -070017662
Svetoslav Ganova0156172011-06-26 17:55:44 -070017663 /**
17664 * Resuable callback for sending
17665 * {@link AccessibilityEvent#TYPE_VIEW_SCROLLED} accessibility event.
17666 */
17667 private class SendViewScrolledAccessibilityEvent implements Runnable {
17668 public volatile boolean mIsPending;
17669
17670 public void run() {
17671 sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
17672 mIsPending = false;
17673 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017674 }
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017675
17676 /**
17677 * <p>
17678 * This class represents a delegate that can be registered in a {@link View}
17679 * to enhance accessibility support via composition rather via inheritance.
17680 * It is specifically targeted to widget developers that extend basic View
17681 * classes i.e. classes in package android.view, that would like their
17682 * applications to be backwards compatible.
17683 * </p>
Joe Fernandeze1302ed2012-02-06 14:30:15 -080017684 * <div class="special reference">
17685 * <h3>Developer Guides</h3>
17686 * <p>For more information about making applications accessible, read the
17687 * <a href="{@docRoot}guide/topics/ui/accessibility/index.html">Accessibility</a>
17688 * developer guide.</p>
17689 * </div>
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017690 * <p>
17691 * A scenario in which a developer would like to use an accessibility delegate
17692 * is overriding a method introduced in a later API version then the minimal API
17693 * version supported by the application. For example, the method
17694 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} is not available
17695 * in API version 4 when the accessibility APIs were first introduced. If a
17696 * developer would like his application to run on API version 4 devices (assuming
17697 * all other APIs used by the application are version 4 or lower) and take advantage
17698 * of this method, instead of overriding the method which would break the application's
17699 * backwards compatibility, he can override the corresponding method in this
17700 * delegate and register the delegate in the target View if the API version of
17701 * the system is high enough i.e. the API version is same or higher to the API
17702 * version that introduced
17703 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)}.
17704 * </p>
17705 * <p>
17706 * Here is an example implementation:
17707 * </p>
17708 * <code><pre><p>
17709 * if (Build.VERSION.SDK_INT >= 14) {
17710 * // If the API version is equal of higher than the version in
17711 * // which onInitializeAccessibilityNodeInfo was introduced we
17712 * // register a delegate with a customized implementation.
17713 * View view = findViewById(R.id.view_id);
17714 * view.setAccessibilityDelegate(new AccessibilityDelegate() {
17715 * public void onInitializeAccessibilityNodeInfo(View host,
17716 * AccessibilityNodeInfo info) {
17717 * // Let the default implementation populate the info.
17718 * super.onInitializeAccessibilityNodeInfo(host, info);
17719 * // Set some other information.
17720 * info.setEnabled(host.isEnabled());
17721 * }
17722 * });
17723 * }
17724 * </code></pre></p>
17725 * <p>
17726 * This delegate contains methods that correspond to the accessibility methods
17727 * in View. If a delegate has been specified the implementation in View hands
17728 * off handling to the corresponding method in this delegate. The default
17729 * implementation the delegate methods behaves exactly as the corresponding
17730 * method in View for the case of no accessibility delegate been set. Hence,
17731 * to customize the behavior of a View method, clients can override only the
17732 * corresponding delegate method without altering the behavior of the rest
17733 * accessibility related methods of the host view.
17734 * </p>
17735 */
17736 public static class AccessibilityDelegate {
17737
17738 /**
17739 * Sends an accessibility event of the given type. If accessibility is not
17740 * enabled this method has no effect.
17741 * <p>
17742 * The default implementation behaves as {@link View#sendAccessibilityEvent(int)
17743 * View#sendAccessibilityEvent(int)} for the case of no accessibility delegate
17744 * been set.
17745 * </p>
17746 *
17747 * @param host The View hosting the delegate.
17748 * @param eventType The type of the event to send.
17749 *
17750 * @see View#sendAccessibilityEvent(int) View#sendAccessibilityEvent(int)
17751 */
17752 public void sendAccessibilityEvent(View host, int eventType) {
17753 host.sendAccessibilityEventInternal(eventType);
17754 }
17755
17756 /**
alanv8eeefef2012-05-07 16:57:53 -070017757 * Performs the specified accessibility action on the view. For
17758 * possible accessibility actions look at {@link AccessibilityNodeInfo}.
17759 * <p>
17760 * The default implementation behaves as
17761 * {@link View#performAccessibilityAction(int, Bundle)
17762 * View#performAccessibilityAction(int, Bundle)} for the case of
17763 * no accessibility delegate been set.
17764 * </p>
17765 *
17766 * @param action The action to perform.
17767 * @return Whether the action was performed.
17768 *
17769 * @see View#performAccessibilityAction(int, Bundle)
17770 * View#performAccessibilityAction(int, Bundle)
17771 */
17772 public boolean performAccessibilityAction(View host, int action, Bundle args) {
17773 return host.performAccessibilityActionInternal(action, args);
17774 }
17775
17776 /**
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017777 * Sends an accessibility event. This method behaves exactly as
17778 * {@link #sendAccessibilityEvent(View, int)} but takes as an argument an
17779 * empty {@link AccessibilityEvent} and does not perform a check whether
17780 * accessibility is enabled.
17781 * <p>
17782 * The default implementation behaves as
17783 * {@link View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17784 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)} for
17785 * the case of no accessibility delegate been set.
17786 * </p>
17787 *
17788 * @param host The View hosting the delegate.
17789 * @param event The event to send.
17790 *
17791 * @see View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17792 * View#sendAccessibilityEventUnchecked(AccessibilityEvent)
17793 */
17794 public void sendAccessibilityEventUnchecked(View host, AccessibilityEvent event) {
17795 host.sendAccessibilityEventUncheckedInternal(event);
17796 }
17797
17798 /**
17799 * Dispatches an {@link AccessibilityEvent} to the host {@link View} first and then
17800 * to its children for adding their text content to the event.
17801 * <p>
17802 * The default implementation behaves as
17803 * {@link View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17804 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)} for
17805 * the case of no accessibility delegate been set.
17806 * </p>
17807 *
17808 * @param host The View hosting the delegate.
17809 * @param event The event.
17810 * @return True if the event population was completed.
17811 *
17812 * @see View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17813 * View#dispatchPopulateAccessibilityEvent(AccessibilityEvent)
17814 */
17815 public boolean dispatchPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17816 return host.dispatchPopulateAccessibilityEventInternal(event);
17817 }
17818
17819 /**
17820 * Gives a chance to the host View to populate the accessibility event with its
17821 * text content.
17822 * <p>
17823 * The default implementation behaves as
17824 * {@link View#onPopulateAccessibilityEvent(AccessibilityEvent)
17825 * View#onPopulateAccessibilityEvent(AccessibilityEvent)} for
17826 * the case of no accessibility delegate been set.
17827 * </p>
17828 *
17829 * @param host The View hosting the delegate.
17830 * @param event The accessibility event which to populate.
17831 *
17832 * @see View#onPopulateAccessibilityEvent(AccessibilityEvent)
17833 * View#onPopulateAccessibilityEvent(AccessibilityEvent)
17834 */
17835 public void onPopulateAccessibilityEvent(View host, AccessibilityEvent event) {
17836 host.onPopulateAccessibilityEventInternal(event);
17837 }
17838
17839 /**
17840 * Initializes an {@link AccessibilityEvent} with information about the
17841 * the host View which is the event source.
17842 * <p>
17843 * The default implementation behaves as
17844 * {@link View#onInitializeAccessibilityEvent(AccessibilityEvent)
17845 * View#onInitializeAccessibilityEvent(AccessibilityEvent)} for
17846 * the case of no accessibility delegate been set.
17847 * </p>
17848 *
17849 * @param host The View hosting the delegate.
17850 * @param event The event to initialize.
17851 *
17852 * @see View#onInitializeAccessibilityEvent(AccessibilityEvent)
17853 * View#onInitializeAccessibilityEvent(AccessibilityEvent)
17854 */
17855 public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
17856 host.onInitializeAccessibilityEventInternal(event);
17857 }
17858
17859 /**
17860 * Initializes an {@link AccessibilityNodeInfo} with information about the host view.
17861 * <p>
17862 * The default implementation behaves as
17863 * {@link View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17864 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)} for
17865 * the case of no accessibility delegate been set.
17866 * </p>
17867 *
17868 * @param host The View hosting the delegate.
17869 * @param info The instance to initialize.
17870 *
17871 * @see View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17872 * View#onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo)
17873 */
17874 public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
17875 host.onInitializeAccessibilityNodeInfoInternal(info);
17876 }
17877
17878 /**
17879 * Called when a child of the host View has requested sending an
17880 * {@link AccessibilityEvent} and gives an opportunity to the parent (the host)
17881 * to augment the event.
17882 * <p>
17883 * The default implementation behaves as
17884 * {@link ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17885 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)} for
17886 * the case of no accessibility delegate been set.
17887 * </p>
17888 *
17889 * @param host The View hosting the delegate.
17890 * @param child The child which requests sending the event.
17891 * @param event The event to be sent.
17892 * @return True if the event should be sent
17893 *
17894 * @see ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17895 * ViewGroup#onRequestSendAccessibilityEvent(View, AccessibilityEvent)
17896 */
17897 public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child,
17898 AccessibilityEvent event) {
17899 return host.onRequestSendAccessibilityEventInternal(child, event);
17900 }
Svetoslav Ganov02107852011-10-03 17:06:56 -070017901
17902 /**
17903 * Gets the provider for managing a virtual view hierarchy rooted at this View
17904 * and reported to {@link android.accessibilityservice.AccessibilityService}s
17905 * that explore the window content.
17906 * <p>
17907 * The default implementation behaves as
17908 * {@link View#getAccessibilityNodeProvider() View#getAccessibilityNodeProvider()} for
17909 * the case of no accessibility delegate been set.
17910 * </p>
17911 *
17912 * @return The provider.
17913 *
17914 * @see AccessibilityNodeProvider
17915 */
17916 public AccessibilityNodeProvider getAccessibilityNodeProvider(View host) {
17917 return null;
17918 }
Svetoslav Ganov031d9c12011-09-09 16:41:13 -070017919 }
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080017920}