2022-10-02 23:06:56 +02:00
package android.view ;
import android.content.Context ;
2022-11-24 23:10:27 +01:00
import android.content.res.Resources ;
2022-10-02 23:06:56 +02:00
import android.graphics.Canvas ;
2023-06-22 11:45:46 +02:00
import android.graphics.Rect ;
2023-08-17 10:46:24 +02:00
import android.graphics.drawable.Drawable ;
import android.os.Handler ;
2023-01-09 12:07:57 +01:00
import android.os.IBinder ;
2023-08-17 10:46:24 +02:00
import android.os.Looper ;
2023-06-22 11:45:46 +02:00
import android.util.AttributeSet ;
import android.util.LayoutDirection ;
2023-08-17 10:46:24 +02:00
import java.util.ArrayList ;
2022-10-02 23:06:56 +02:00
import java.util.HashMap ;
2023-08-17 10:46:24 +02:00
import java.util.Map ;
2022-10-02 23:06:56 +02:00
public class View extends Object {
2023-06-22 11:45:46 +02:00
// --- constants from android source
2022-10-02 23:06:56 +02:00
2022-10-18 18:35:15 +02:00
/ * *
2023-06-22 11:45:46 +02:00
* The logging tag used by this class with android . util . Log .
* /
2022-10-18 18:35:15 +02:00
protected static final String VIEW_LOG_TAG = " View " ;
/ * *
2023-06-22 11:45:46 +02:00
* When set to true , apps will draw debugging information about their layouts .
*
* @hide
* /
2022-10-18 18:35:15 +02:00
public static final String DEBUG_LAYOUT_PROPERTY = " debug.layout " ;
/ * *
2023-06-22 11:45:46 +02:00
* Used to mark a View that has no ID .
* /
2022-10-18 18:35:15 +02:00
public static final int NO_ID = - 1 ;
/ * *
2023-06-22 11:45:46 +02:00
* Signals that compatibility booleans have been initialized according to
* target SDK versions .
* /
2022-10-18 18:35:15 +02:00
private static boolean sCompatibilityDone = false ;
/ * *
2023-06-22 11:45:46 +02:00
* Use the old ( broken ) way of building MeasureSpecs .
* /
2022-10-18 18:35:15 +02:00
private static boolean sUseBrokenMakeMeasureSpec = false ;
/ * *
2023-06-22 11:45:46 +02:00
* Ignore any optimizations using the measure cache .
* /
2022-10-18 18:35:15 +02:00
private static boolean sIgnoreMeasureCache = false ;
/ * *
2023-06-22 11:45:46 +02:00
* This view does not want keystrokes . Use with TAKES_FOCUS_MASK when
* calling setFlags .
* /
2022-10-18 18:35:15 +02:00
private static final int NOT_FOCUSABLE = 0x00000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view wants keystrokes . Use with TAKES_FOCUS_MASK when calling
* setFlags .
* /
2022-10-18 18:35:15 +02:00
private static final int FOCUSABLE = 0x00000001 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for use with setFlags indicating bits used for focus .
* /
2022-10-18 18:35:15 +02:00
private static final int FOCUSABLE_MASK = 0x00000001 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view will adjust its padding to fit sytem windows ( e . g . status bar )
* /
2022-10-18 18:35:15 +02:00
private static final int FITS_SYSTEM_WINDOWS = 0x00000002 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view is visible .
* Use with { @link # setVisibility } and < a href = " #attr_android:visibility " > { @code
* android : visibility } .
* /
2022-10-18 18:35:15 +02:00
public static final int VISIBLE = 0x00000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view is invisible , but it still takes up space for layout purposes .
* Use with { @link # setVisibility } and < a href = " #attr_android:visibility " > { @code
* android : visibility } .
* /
2022-10-18 18:35:15 +02:00
public static final int INVISIBLE = 0x00000004 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view is invisible , and it doesn ' t take any space for layout
* purposes . Use with { @link # setVisibility } and < a href = " #attr_android:visibility " > { @code
* android : visibility } .
* /
2022-10-18 18:35:15 +02:00
public static final int GONE = 0x00000008 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for use with setFlags indicating bits used for visibility .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int VISIBILITY_MASK = 0x0000000C ;
private static final int [ ] VISIBILITY_FLAGS = { VISIBLE , INVISIBLE , GONE } ;
/ * *
2023-06-22 11:45:46 +02:00
* This view is enabled . Interpretation varies by subclass .
* Use with ENABLED_MASK when calling setFlags .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int ENABLED = 0x00000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view is disabled . Interpretation varies by subclass .
* Use with ENABLED_MASK when calling setFlags .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int DISABLED = 0x00000020 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for use with setFlags indicating bits used for indicating whether
* this view is enabled
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int ENABLED_MASK = 0x00000020 ;
/ * *
2023-06-22 11:45:46 +02:00
* This view won ' t draw . { @link # onDraw ( android . graphics . Canvas ) } won ' t be
* called and further optimizations will be performed . It is okay to have
* this flag set and a background . Use with DRAW_MASK when calling setFlags .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int WILL_NOT_DRAW = 0x00000080 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for use with setFlags indicating bits used for indicating whether
* this view is will draw
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int DRAW_MASK = 0x00000080 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > This view doesn ' t show scrollbars . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_NONE = 0x00000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > This view shows horizontal scrollbars . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_HORIZONTAL = 0x00000100 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > This view shows vertical scrollbars . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_VERTICAL = 0x00000200 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Mask for use with setFlags indicating bits used for indicating which
* scrollbars are enabled . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_MASK = 0x00000300 ;
/ * *
2023-06-22 11:45:46 +02:00
* Indicates that the view should filter touches when its window is obscured .
* Refer to the class comments for more information about this security feature .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int FILTER_TOUCHES_WHEN_OBSCURED = 0x00000400 ;
/ * *
2023-06-22 11:45:46 +02:00
* Set for framework elements that use FITS_SYSTEM_WINDOWS , to indicate
* that they are optional and should be skipped if the window has
* requested system UI flags that ignore those insets for layout .
* /
2022-10-18 18:35:15 +02:00
static final int OPTIONAL_FITS_SYSTEM_WINDOWS = 0x00000800 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > This view doesn ' t show fading edges . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int FADING_EDGE_NONE = 0x00000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > This view shows horizontal fading edges . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int FADING_EDGE_HORIZONTAL = 0x00001000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > This view shows vertical fading edges . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int FADING_EDGE_VERTICAL = 0x00002000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Mask for use with setFlags indicating bits used for indicating which
* fading edges are enabled . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int FADING_EDGE_MASK = 0x00003000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates this view can be clicked . When clickable , a View reacts
* to clicks by notifying the OnClickListener . < p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int CLICKABLE = 0x00004000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates this view is caching its drawing into a bitmap . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int DRAWING_CACHE_ENABLED = 0x00008000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates that no icicle should be saved for this view . < p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SAVE_DISABLED = 0x000010000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Mask for use with setFlags indicating bits used for the saveEnabled
* property . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SAVE_DISABLED_MASK = 0x000010000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates that no drawing cache should ever be created for this view . < p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int WILL_NOT_CACHE_DRAWING = 0x000020000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates this view can take / keep focus when int touch mode . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int FOCUSABLE_IN_TOUCH_MODE = 0x00040000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Enables low quality mode for the drawing cache . < / p >
* /
2022-10-18 18:35:15 +02:00
public static final int DRAWING_CACHE_QUALITY_LOW = 0x00080000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Enables high quality mode for the drawing cache . < / p >
* /
2022-10-18 18:35:15 +02:00
public static final int DRAWING_CACHE_QUALITY_HIGH = 0x00100000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Enables automatic quality mode for the drawing cache . < / p >
* /
2022-10-18 18:35:15 +02:00
public static final int DRAWING_CACHE_QUALITY_AUTO = 0x00000000 ;
private static final int [ ] DRAWING_CACHE_QUALITY_FLAGS = {
2023-06-22 11:45:46 +02:00
DRAWING_CACHE_QUALITY_AUTO , DRAWING_CACHE_QUALITY_LOW , DRAWING_CACHE_QUALITY_HIGH } ;
2022-10-18 18:35:15 +02:00
/ * *
2023-06-22 11:45:46 +02:00
* < p > Mask for use with setFlags indicating bits used for the cache
* quality property . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int DRAWING_CACHE_QUALITY_MASK = 0x00180000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p >
* Indicates this view can be long clicked . When long clickable , a View
* reacts to long clicks by notifying the OnLongClickListener or showing a
* context menu .
* < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int LONG_CLICKABLE = 0x00200000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates that this view gets its drawable states from its direct parent
* and ignores its original internal states . < / p >
*
* @hide
* /
2022-10-18 18:35:15 +02:00
static final int DUPLICATE_PARENT_STATE = 0x00400000 ;
/ * *
2023-06-22 11:45:46 +02:00
* The scrollbar style to display the scrollbars inside the content area ,
* without increasing the padding . The scrollbars will be overlaid with
* translucency on the view ' s content .
* /
2022-10-18 18:35:15 +02:00
public static final int SCROLLBARS_INSIDE_OVERLAY = 0 ;
/ * *
2023-06-22 11:45:46 +02:00
* The scrollbar style to display the scrollbars inside the padded area ,
* increasing the padding of the view . The scrollbars will not overlap the
* content area of the view .
* /
2022-10-18 18:35:15 +02:00
public static final int SCROLLBARS_INSIDE_INSET = 0x01000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* The scrollbar style to display the scrollbars at the edge of the view ,
* without increasing the padding . The scrollbars will be overlaid with
* translucency .
* /
2022-10-18 18:35:15 +02:00
public static final int SCROLLBARS_OUTSIDE_OVERLAY = 0x02000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* The scrollbar style to display the scrollbars at the edge of the view ,
* increasing the padding of the view . The scrollbars will only overlap the
* background , if any .
* /
2022-10-18 18:35:15 +02:00
public static final int SCROLLBARS_OUTSIDE_INSET = 0x03000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask to check if the scrollbar style is overlay or inset .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_INSET_MASK = 0x01000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask to check if the scrollbar style is inside or outside .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_OUTSIDE_MASK = 0x02000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for scrollbar style .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int SCROLLBARS_STYLE_MASK = 0x03000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* View flag indicating that the screen should remain on while the
* window containing this view is visible to the user . This effectively
* takes care of automatically setting the WindowManager ' s
* { @link WindowManager . LayoutParams # FLAG_KEEP_SCREEN_ON } .
* /
2022-10-18 18:35:15 +02:00
public static final int KEEP_SCREEN_ON = 0x04000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* View flag indicating whether this view should have sound effects enabled
* for events such as clicking and touching .
* /
2022-10-18 18:35:15 +02:00
public static final int SOUND_EFFECTS_ENABLED = 0x08000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* View flag indicating whether this view should have haptic feedback
* enabled for events such as long presses .
* /
2022-10-18 18:35:15 +02:00
public static final int HAPTIC_FEEDBACK_ENABLED = 0x10000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Indicates that the view hierarchy should stop saving state when
* it reaches this view . If state saving is initiated immediately at
* the view , it will be allowed .
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int PARENT_SAVE_DISABLED = 0x20000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* < p > Mask for use with setFlags indicating bits used for PARENT_SAVE_DISABLED . < / p >
* { @hide }
* /
2022-10-18 18:35:15 +02:00
static final int PARENT_SAVE_DISABLED_MASK = 0x20000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* View flag indicating whether { @link # addFocusables ( ArrayList , int , int ) }
* should add all focusable Views regardless if they are focusable in touch mode .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUSABLES_ALL = 0x00000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* View flag indicating whether { @link # addFocusables ( ArrayList , int , int ) }
* should add only Views focusable in touch mode .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUSABLES_TOUCH_MODE = 0x00000001 ;
/ * *
2023-06-22 11:45:46 +02:00
* Use with { @link # focusSearch ( int ) } . Move focus to the previous selectable
* item .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUS_BACKWARD = 0x00000001 ;
/ * *
2023-06-22 11:45:46 +02:00
* Use with { @link # focusSearch ( int ) } . Move focus to the next selectable
* item .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUS_FORWARD = 0x00000002 ;
/ * *
2023-06-22 11:45:46 +02:00
* Use with { @link # focusSearch ( int ) } . Move focus to the left .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUS_LEFT = 0x00000011 ;
/ * *
2023-06-22 11:45:46 +02:00
* Use with { @link # focusSearch ( int ) } . Move focus up .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUS_UP = 0x00000021 ;
/ * *
2023-06-22 11:45:46 +02:00
* Use with { @link # focusSearch ( int ) } . Move focus to the right .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUS_RIGHT = 0x00000042 ;
/ * *
2023-06-22 11:45:46 +02:00
* Use with { @link # focusSearch ( int ) } . Move focus down .
* /
2022-10-18 18:35:15 +02:00
public static final int FOCUS_DOWN = 0x00000082 ;
/ * *
2023-06-22 11:45:46 +02:00
* Bits of { @link # getMeasuredWidthAndState ( ) } and
* { @link # getMeasuredWidthAndState ( ) } that provide the actual measured size .
* /
2022-10-18 18:35:15 +02:00
public static final int MEASURED_SIZE_MASK = 0x00ffffff ;
/ * *
2023-06-22 11:45:46 +02:00
* Bits of { @link # getMeasuredWidthAndState ( ) } and
* { @link # getMeasuredWidthAndState ( ) } that provide the additional state bits .
* /
2022-10-18 18:35:15 +02:00
public static final int MEASURED_STATE_MASK = 0xff000000 ;
/ * *
2023-06-22 11:45:46 +02:00
* Bit shift of { @link # MEASURED_STATE_MASK } to get to the height bits
* for functions that combine both width and height into a single int ,
* such as { @link # getMeasuredState ( ) } and the childState argument of
* { @link # resolveSizeAndState ( int , int , int ) } .
* /
2022-10-18 18:35:15 +02:00
public static final int MEASURED_HEIGHT_STATE_SHIFT = 16 ;
/ * *
2023-06-22 11:45:46 +02:00
* Bit of { @link # getMeasuredWidthAndState ( ) } and
* { @link # getMeasuredWidthAndState ( ) } that indicates the measured size
* is smaller that the space the view would like to have .
* /
2022-10-18 18:35:15 +02:00
public static final int MEASURED_STATE_TOO_SMALL = 0x01000000 ;
2022-10-02 23:06:56 +02:00
2023-06-22 11:45:46 +02:00
// --- and some flags
2022-10-02 23:06:56 +02:00
2022-10-18 18:35:15 +02:00
/ * *
2023-06-22 11:45:46 +02:00
* Indicates that this view has reported that it can accept the current drag ' s content .
* Cleared when the drag operation concludes .
* @hide
* /
static final int PFLAG2_DRAG_CAN_ACCEPT = 0x00000001 ;
2022-10-18 18:35:15 +02:00
/ * *
2023-06-22 11:45:46 +02:00
* Indicates that this view is currently directly under the drag location in a
* drag - and - drop operation involving content that it can accept . Cleared when
* the drag exits the view , or when the drag operation concludes .
* @hide
* /
static final int PFLAG2_DRAG_HOVERED = 0x00000002 ;
2022-10-18 18:35:15 +02:00
/ * *
2023-06-22 11:45:46 +02:00
* Horizontal layout direction of this view is from Left to Right .
* Use with { @link # setLayoutDirection } .
* /
2022-10-18 18:35:15 +02:00
public static final int LAYOUT_DIRECTION_LTR = LayoutDirection . LTR ;
/ * *
2023-06-22 11:45:46 +02:00
* Horizontal layout direction of this view is from Right to Left .
* Use with { @link # setLayoutDirection } .
* /
2022-10-18 18:35:15 +02:00
public static final int LAYOUT_DIRECTION_RTL = LayoutDirection . RTL ;
/ * *
2023-06-22 11:45:46 +02:00
* Horizontal layout direction of this view is inherited from its parent .
* Use with { @link # setLayoutDirection } .
* /
2022-10-18 18:35:15 +02:00
public static final int LAYOUT_DIRECTION_INHERIT = LayoutDirection . INHERIT ;
/ * *
2023-06-22 11:45:46 +02:00
* Horizontal layout direction of this view is from deduced from the default language
* script for the locale . Use with { @link # setLayoutDirection } .
* /
2022-10-18 18:35:15 +02:00
public static final int LAYOUT_DIRECTION_LOCALE = LayoutDirection . LOCALE ;
/ * *
2023-06-22 11:45:46 +02:00
* Bit shift to get the horizontal layout direction . ( bits after DRAG_HOVERED )
* @hide
* /
2022-10-18 18:35:15 +02:00
static final int PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT = 2 ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for use with private flags indicating bits used for horizontal layout direction .
* @hide
* /
2022-10-18 18:35:15 +02:00
static final int PFLAG2_LAYOUT_DIRECTION_MASK = 0x00000003 < < PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT ;
/ * *
2023-06-22 11:45:46 +02:00
* Indicates whether the view horizontal layout direction has been resolved and drawn to the
* right - to - left direction .
* @hide
* /
2022-10-18 18:35:15 +02:00
static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_RTL = 4 < < PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT ;
/ * *
2023-06-22 11:45:46 +02:00
* Indicates whether the view horizontal layout direction has been resolved .
* @hide
* /
2022-10-18 18:35:15 +02:00
static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED = 8 < < PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT ;
/ * *
2023-06-22 11:45:46 +02:00
* Mask for use with private flags indicating bits used for resolved horizontal layout direction .
* @hide
* /
2022-10-18 18:35:15 +02:00
static final int PFLAG2_LAYOUT_DIRECTION_RESOLVED_MASK = 0x0000000C < < PFLAG2_LAYOUT_DIRECTION_MASK_SHIFT ;
2022-10-02 23:06:56 +02:00
2023-08-12 13:09:33 +02:00
// --- apparently there's more...
@Deprecated public static final int STATUS_BAR_HIDDEN = 1 ; // 0x1
@Deprecated public static final int STATUS_BAR_VISIBLE = 0 ; // 0x0
public static final int SYSTEM_UI_FLAG_FULLSCREEN = 4 ; // 0x4
public static final int SYSTEM_UI_FLAG_HIDE_NAVIGATION = 2 ; // 0x2
public static final int SYSTEM_UI_FLAG_IMMERSIVE = 2048 ; // 0x800
public static final int SYSTEM_UI_FLAG_IMMERSIVE_STICKY = 4096 ; // 0x1000
public static final int SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN = 1024 ; // 0x400
public static final int SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION = 512 ; // 0x200
public static final int SYSTEM_UI_FLAG_LAYOUT_STABLE = 256 ; // 0x100
public static final int SYSTEM_UI_FLAG_LOW_PROFILE = 1 ; // 0x1
public static final int SYSTEM_UI_FLAG_VISIBLE = 0 ; // 0x0
public static final int SYSTEM_UI_LAYOUT_FLAGS = 1536 ; // 0x600
public static final int TEXT_ALIGNMENT_CENTER = 4 ; // 0x4
public static final int TEXT_ALIGNMENT_GRAVITY = 1 ; // 0x1
public static final int TEXT_ALIGNMENT_INHERIT = 0 ; // 0x0
public static final int TEXT_ALIGNMENT_TEXT_END = 3 ; // 0x3
public static final int TEXT_ALIGNMENT_TEXT_START = 2 ; // 0x2
public static final int TEXT_ALIGNMENT_VIEW_END = 6 ; // 0x6
public static final int TEXT_ALIGNMENT_VIEW_START = 5 ; // 0x5
public static final int TEXT_DIRECTION_ANY_RTL = 2 ; // 0x2
public static final int TEXT_DIRECTION_FIRST_STRONG = 1 ; // 0x1
public static final int TEXT_DIRECTION_INHERIT = 0 ; // 0x0
public static final int TEXT_DIRECTION_LOCALE = 5 ; // 0x5
public static final int TEXT_DIRECTION_LTR = 3 ; // 0x3
public static final int TEXT_DIRECTION_RTL = 4 ; // 0x4
2023-06-22 11:45:46 +02:00
// --- end of constants from android source
2022-10-02 23:06:56 +02:00
2023-06-22 11:45:46 +02:00
// --- interfaces from android source
2022-10-18 18:35:15 +02:00
public interface OnTouchListener {
/ * *
* Called when a touch event is dispatched to a view . This allows listeners to
* get a chance to respond before the target view .
*
* @param v The view the touch event has been dispatched to .
* @param event The MotionEvent object containing full information about
* the event .
* @return True if the listener has consumed the event , false otherwise .
* /
boolean onTouch ( View v , MotionEvent event ) ;
}
public interface OnClickListener {
void onClick ( View v ) ;
}
2022-10-02 23:06:56 +02:00
public interface OnAttachStateChangeListener {
// TODO
}
2022-10-26 18:39:04 +02:00
public interface OnGenericMotionListener {
// TODO
}
public interface OnSystemUiVisibilityChangeListener {
// TODO
}
2022-10-02 23:06:56 +02:00
public static interface OnKeyListener {
2023-06-22 11:45:46 +02:00
// TODO
// boolean onKey(View v, int keyCode, KeyEvent event);
}
2023-08-17 10:46:24 +02:00
public interface OnLongClickListener {
// TODO
}
public interface OnHoverListener {
// TODO
}
public interface OnApplyWindowInsetsListener {
// TODO
}
public interface OnLayoutChangeListener {
// TODO
}
2023-08-12 13:09:33 +02:00
public interface OnCreateContextMenuListener {
/ * *
* Called when the context menu for this view is being built . It is not
* safe to hold onto the menu after this method returns .
*
* @param menu The context menu that is being built
* @param v The view for which the context menu is being built
* @param menuInfo Extra information about the item for which the
* context menu should be shown . This information will vary
* depending on the class of v .
* /
// void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);
}
2023-06-22 11:45:46 +02:00
// --- end of interfaces
// --- subclasses
/ * *
* A MeasureSpec encapsulates the layout requirements passed from parent to child .
* Each MeasureSpec represents a requirement for either the width or the height .
* A MeasureSpec is comprised of a size and a mode . There are three possible
* modes :
* < dl >
* < dt > UNSPECIFIED < / dt >
* < dd >
* The parent has not imposed any constraint on the child . It can be whatever size
* it wants .
* < / dd >
*
* < dt > EXACTLY < / dt >
* < dd >
* The parent has determined an exact size for the child . The child is going to be
* given those bounds regardless of how big it wants to be .
* < / dd >
*
* < dt > AT_MOST < / dt >
* < dd >
* The child can be as large as it wants up to the specified size .
* < / dd >
* < / dl >
*
* MeasureSpecs are implemented as ints to reduce object allocation . This class
* is provided to pack and unpack the & lt ; size , mode & gt ; tuple into the int .
* /
2022-10-18 18:35:15 +02:00
public static class MeasureSpec {
private static final int MODE_SHIFT = 30 ;
2023-06-22 11:45:46 +02:00
private static final int MODE_MASK = 0x3 < < MODE_SHIFT ;
2022-10-18 18:35:15 +02:00
/ * *
* Measure specification mode : The parent has not imposed any constraint
* on the child . It can be whatever size it wants .
* /
public static final int UNSPECIFIED = 0 < < MODE_SHIFT ;
/ * *
* Measure specification mode : The parent has determined an exact size
* for the child . The child is going to be given those bounds regardless
* of how big it wants to be .
* /
2023-06-22 11:45:46 +02:00
public static final int EXACTLY = 1 < < MODE_SHIFT ;
2022-10-18 18:35:15 +02:00
/ * *
* Measure specification mode : The child can be as large as it wants up
* to the specified size .
* /
2023-06-22 11:45:46 +02:00
public static final int AT_MOST = 2 < < MODE_SHIFT ;
2022-10-18 18:35:15 +02:00
/ * *
* Creates a measure specification based on the supplied size and mode .
*
* The mode must always be one of the following :
* < ul >
* < li > { @link android . view . View . MeasureSpec # UNSPECIFIED } < / li >
* < li > { @link android . view . View . MeasureSpec # EXACTLY } < / li >
* < li > { @link android . view . View . MeasureSpec # AT_MOST } < / li >
* < / ul >
*
* < p > < strong > Note : < / strong > On API level 17 and lower , makeMeasureSpec ' s
* implementation was such that the order of arguments did not matter
* and overflow in either value could impact the resulting MeasureSpec .
* { @link android . widget . RelativeLayout } was affected by this bug .
* Apps targeting API levels greater than 17 will get the fixed , more strict
* behavior . < / p >
*
* @param size the size of the measure specification
* @param mode the mode of the measure specification
* @return the measure specification based on size and mode
* /
public static int makeMeasureSpec ( int size , int mode ) {
if ( sUseBrokenMakeMeasureSpec ) {
2023-06-22 11:45:46 +02:00
return size + mode ;
2022-10-18 18:35:15 +02:00
} else {
2023-06-22 11:45:46 +02:00
return ( size & ~ MODE_MASK ) | ( mode & MODE_MASK ) ;
2022-10-18 18:35:15 +02:00
}
}
/ * *
* Extracts the mode from the supplied measure specification .
*
* @param measureSpec the measure specification to extract the mode from
* @return { @link android . view . View . MeasureSpec # UNSPECIFIED } ,
* { @link android . view . View . MeasureSpec # AT_MOST } or
* { @link android . view . View . MeasureSpec # EXACTLY }
* /
public static int getMode ( int measureSpec ) {
return ( measureSpec & MODE_MASK ) ;
}
/ * *
* Extracts the size from the supplied measure specification .
*
* @param measureSpec the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure specification
* /
public static int getSize ( int measureSpec ) {
return ( measureSpec & ~ MODE_MASK ) ;
}
static int adjust ( int measureSpec , int delta ) {
return makeMeasureSpec ( getSize ( measureSpec + delta ) , getMode ( measureSpec ) ) ;
}
/ * *
* Returns a String representation of the specified measure
* specification .
*
* @param measureSpec the measure specification to convert to a String
* @return a String with the following format : " MeasureSpec: MODE SIZE "
* /
public static String toString ( int measureSpec ) {
int mode = getMode ( measureSpec ) ;
int size = getSize ( measureSpec ) ;
StringBuilder sb = new StringBuilder ( " MeasureSpec: " ) ;
if ( mode = = UNSPECIFIED )
2023-06-22 11:45:46 +02:00
sb . append ( " UNSPECIFIED " ) ;
2022-10-18 18:35:15 +02:00
else if ( mode = = EXACTLY )
2023-06-22 11:45:46 +02:00
sb . append ( " EXACTLY " ) ;
2022-10-18 18:35:15 +02:00
else if ( mode = = AT_MOST )
2023-06-22 11:45:46 +02:00
sb . append ( " AT_MOST " ) ;
2022-10-18 18:35:15 +02:00
else
2023-06-22 11:45:46 +02:00
sb . append ( mode ) . append ( " " ) ;
2022-10-18 18:35:15 +02:00
sb . append ( size ) ;
return sb . toString ( ) ;
}
}
2022-10-02 23:06:56 +02:00
2023-06-22 11:45:46 +02:00
// --- end of subclasses
2022-10-02 23:06:56 +02:00
public int id ;
2023-08-12 13:09:33 +02:00
private int system_ui_visibility = 0 ;
2022-10-02 23:06:56 +02:00
public ViewGroup parent ;
public AttributeSet attrs ;
protected ViewGroup . LayoutParams layout_params ;
private Context context ;
2023-08-17 10:46:24 +02:00
private Map < Integer , Object > tags = new HashMap < > ( ) ;
2022-10-02 23:06:56 +02:00
public long widget ; // pointer
public static HashMap < Integer , View > view_by_id = new HashMap < Integer , View > ( ) ;
2023-08-22 13:49:09 +02:00
public View ( ) {
this ( Context . this_application ) ;
} // FIXME
2022-10-02 23:06:56 +02:00
2023-07-14 18:02:04 +02:00
public View ( Context context , AttributeSet attrs ) {
2023-08-17 12:59:37 +02:00
this ( context , attrs , 0 ) ;
2022-10-02 23:06:56 +02:00
2023-07-14 18:02:04 +02:00
if ( attrs ! = null ) {
id = attrs . getAttributeResourceValue ( " http://schemas.android.com/apk/res/android " , " id " , 0 ) ;
if ( id ! = 0 )
setId ( id ) ;
}
2022-10-02 23:06:56 +02:00
}
2023-08-17 10:46:24 +02:00
public View ( Context context , AttributeSet attrs , int defStyle ) {
2023-08-17 12:59:37 +02:00
this . context = context ;
widget = native_constructor ( context , attrs ) ;
2023-08-17 10:46:24 +02:00
}
2022-10-02 23:06:56 +02:00
public View findViewById ( int id ) {
/* TODO: this should probably only search among children, but the id is surely unique anyway? :P */
return view_by_id . get ( id ) ;
}
public void onDraw ( Canvas canvas ) { }
public View ( Context context ) {
2023-08-17 12:59:37 +02:00
this ( context , null ) ;
2022-10-02 23:06:56 +02:00
}
public final ViewParent getParent ( ) {
return parent ;
}
public void setLayoutParams ( ViewGroup . LayoutParams params ) {
if ( params = = null ) {
throw new NullPointerException ( " Layout parameters cannot be null " ) ;
}
native_set_size_request ( params . width , params . height ) ;
2023-06-22 11:45:46 +02:00
if ( params . gravity ! = - 1 ) {
2022-10-02 23:06:56 +02:00
setGravity ( params . gravity ) ;
}
layout_params = params ;
}
public ViewGroup . LayoutParams getLayoutParams ( ) {
return layout_params ;
}
protected final void setMeasuredDimension ( int measuredWidth , int measuredHeight ) {
native_set_size_request ( MeasureSpec . getSize ( measuredWidth ) , MeasureSpec . getSize ( measuredHeight ) ) ;
}
2022-11-24 23:10:27 +01:00
public Resources getResources ( ) {
return Context . this_application . getResources ( ) ;
}
2022-10-02 23:06:56 +02:00
public native void setGravity ( int gravity ) ;
public native void setOnTouchListener ( OnTouchListener l ) ;
public native void setOnClickListener ( OnClickListener l ) ;
2022-10-26 18:39:04 +02:00
public /*native*/ void setOnSystemUiVisibilityChangeListener ( OnSystemUiVisibilityChangeListener l ) { }
2022-10-18 18:35:15 +02:00
public native final int getWidth ( ) ;
public native final int getHeight ( ) ;
2022-10-02 23:06:56 +02:00
2023-08-17 12:59:37 +02:00
protected native long native_constructor ( Context context , AttributeSet attrs ) ; // will create a custom GtkWidget with a custom drawing function
2022-10-02 23:06:56 +02:00
private native void native_set_size_request ( int width , int height ) ;
2023-08-22 13:49:09 +02:00
protected native void native_destructor ( long widget ) ;
2022-10-02 23:06:56 +02:00
2023-06-22 11:45:46 +02:00
// --- stubs
2022-10-02 23:06:56 +02:00
2022-11-24 23:10:27 +01:00
public void setContentDescription ( CharSequence contentDescription ) {
2023-06-22 11:45:46 +02:00
System . out . println ( " setContentDescription called with: > " + contentDescription + " < " ) ;
2022-11-24 23:10:27 +01:00
}
2023-07-14 18:02:04 +02:00
public void setId ( int id ) {
2023-08-17 10:46:24 +02:00
this . id = id ;
2023-07-14 18:02:04 +02:00
view_by_id . put ( id , this ) ;
}
2022-11-24 23:10:27 +01:00
2022-10-02 23:06:56 +02:00
public void setOnKeyListener ( OnKeyListener l ) { }
public void setFocusable ( boolean focusable ) { }
public void setFocusableInTouchMode ( boolean focusableInTouchMode ) { }
2022-10-18 18:35:15 +02:00
public final boolean requestFocus ( ) {
return requestFocus ( View . FOCUS_DOWN ) ;
}
public final boolean requestFocus ( int direction ) {
return requestFocus ( direction , null ) ;
}
public boolean requestFocus ( int direction , Rect previouslyFocusedRect ) {
return true ;
}
2022-10-02 23:06:56 +02:00
2023-08-12 13:09:33 +02:00
public void setSystemUiVisibility ( int visibility ) {
system_ui_visibility = visibility ;
}
public int getSystemUiVisibility ( ) {
return system_ui_visibility ;
} ;
2022-10-02 23:06:56 +02:00
protected void onMeasure ( int widthMeasureSpec , int heightMeasureSpec ) { }
public void setPressed ( boolean pressed ) {
2023-06-22 11:45:46 +02:00
System . out . println ( " calling setPressed on " + this + " with value: " + pressed ) ;
2022-10-02 23:06:56 +02:00
}
public void setSelected ( boolean selected ) {
2023-06-22 11:45:46 +02:00
System . out . println ( " calling setSelected on " + this + " with value: " + selected ) ;
2022-10-02 23:06:56 +02:00
}
public ViewTreeObserver getViewTreeObserver ( ) {
return new ViewTreeObserver ( ) ;
}
protected void onFinishInflate ( ) { }
public void invalidate ( Rect dirty ) { }
public void invalidate ( int l , int t , int r , int b ) { }
2023-07-13 22:38:01 +02:00
public void invalidate ( ) {
nativeInvalidate ( widget ) ;
}
private static native void nativeInvalidate ( long widget ) ;
2022-10-02 23:06:56 +02:00
public void setBackgroundColor ( int color ) { }
public native void setVisibility ( int visibility ) ;
public void setPadding ( int left , int top , int right , int bottom ) { }
public void setBackgroundResource ( int resid ) {
2023-06-22 11:45:46 +02:00
// System.out.println("*** setBackgroundResource: " + getString(resid));
2022-10-02 23:06:56 +02:00
}
public void getHitRect ( Rect outRect ) { }
public final boolean getLocalVisibleRect ( Rect r ) { return false ; }
public final int getTop ( ) { return 0 ; }
public final int getScrollY ( ) { return 0 ; }
public void scrollTo ( int x , int y ) { }
public void getLocationOnScreen ( int [ ] location ) { // FIXME: actually return the widget's location (and also have the onclick callback convert to window coordinates, because is seems that's what android deals in..)
location [ 0 ] = 0 ;
location [ 1 ] = 0 ;
}
public boolean performHapticFeedback ( int feedbackConstant ) {
return performHapticFeedback ( feedbackConstant , 0 ) ;
}
public boolean performHapticFeedback ( int feedbackConstant , int flags ) {
System . out . println ( " vibration motor go burrrr " ) ;
return true ; // FIXME why is it not void
}
public int getPaddingLeft ( ) {
return 0 ;
}
public int getPaddingRight ( ) {
return 0 ;
}
public int getPaddingTop ( ) {
return 0 ;
}
public int getPaddingBottom ( ) {
return 0 ;
}
public void postInvalidate ( ) { }
public void postInvalidate ( int left , int top , int right , int bottom ) {
2023-06-22 11:45:46 +02:00
System . out . println ( " postInvalidate( " + left + " , " + top + " , " + right + " , " + bottom + " ) called " ) ;
2022-10-02 23:06:56 +02:00
}
2022-11-02 16:40:15 +05:00
2023-06-22 11:45:46 +02:00
public void setOnGenericMotionListener ( View . OnGenericMotionListener l ) { }
2023-01-09 12:07:57 +01:00
public IBinder getWindowToken ( ) {
return new IBinder ( ) ;
}
public void getLocationInWindow ( int [ ] xxx ) { }
public void addOnAttachStateChangeListener ( OnAttachStateChangeListener l ) { }
public Context getContext ( ) {
return this . context ;
}
2023-06-18 11:03:43 +02:00
public void refreshDrawableState ( ) {
}
2023-08-17 10:46:24 +02:00
public void setDescendantFocusability ( int value ) { }
public void setAccessibilityDelegate ( AccessibilityDelegate delegate ) { }
public static class AccessibilityDelegate { }
public Drawable getBackground ( ) {
return null ;
}
public void setClickable ( boolean clickable ) { }
public void setEnabled ( boolean enabled ) { }
public CharSequence getContentDescription ( ) {
return null ;
}
public void setOnLongClickListener ( OnLongClickListener listener ) { }
public void setLongClickable ( boolean longClickable ) { }
public void setOnHoverListener ( OnHoverListener listener ) { }
public final void measure ( int widthMeasureSpec , int heightMeasureSpec ) { }
public final int getMeasuredWidth ( ) {
return getWidth ( ) ;
}
public final int getMeasuredHeight ( ) {
return getHeight ( ) ;
}
public void setBackgroundDrawable ( Drawable backgroundDrawable ) { }
public int getOverScrollMode ( ) { return 0 ; }
public void setFitsSystemWindows ( boolean fitsSystemWindows ) { }
public void setWillNotDraw ( boolean value ) { }
public void setScrollContainer ( boolean isScrollContainer ) { }
public boolean removeCallbacks ( Runnable action ) { return false ; }
public void requestLayout ( ) { } ;
public void setOverScrollMode ( int mode ) { }
public int getId ( ) { return id ; }
public boolean postDelayed ( Runnable action , long delayMillis ) {
new Handler ( Looper . getMainLooper ( ) ) . postDelayed ( action , delayMillis ) ;
return true ;
}
public boolean post ( Runnable action ) {
new Handler ( Looper . getMainLooper ( ) ) . post ( action ) ;
return true ;
}
public void setSaveFromParentEnabled ( boolean enabled ) { }
public void setTag ( int key , Object tag ) {
tags . put ( key , tag ) ;
}
public Object getTag ( int key ) {
return tags . get ( key ) ;
}
public void addOnLayoutChangeListener ( OnLayoutChangeListener listener ) { }
public boolean isSelected ( ) { return false ; }
public void sendAccessibilityEvent ( int eventType ) { }
public void setMinimumHeight ( int minHeight ) { }
public void setMinimumWidth ( int minWidth ) { }
public void setActivated ( boolean activated ) { }
public int getVisibility ( ) { return View . VISIBLE ; }
public boolean isInEditMode ( ) { return false ; }
2023-08-22 13:49:09 +02:00
@Override
protected void finalize ( ) throws Throwable {
try {
native_destructor ( widget ) ;
} finally {
super . finalize ( ) ;
}
}
2022-10-02 23:06:56 +02:00
}