@quicktvui/ai 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (204) hide show
  1. package/package.json +1 -1
  2. package/rules/.clinerules +27 -4
  3. package/rules/.cursorrules +27 -4
  4. package/rules/.github/copilot-instructions.md +27 -4
  5. package/rules/.source/hippy/extend_views/CoverFlowHorizontalView.java +203 -0
  6. package/rules/.source/hippy/extend_views/CoverFlowVerticalView.java +203 -0
  7. package/rules/.source/hippy/extend_views/CoverFlowViewController.java +195 -0
  8. package/rules/.source/hippy/extend_views/EngineRootView.java +125 -0
  9. package/rules/.source/hippy/extend_views/ExtendTag.java +83 -0
  10. package/rules/.source/hippy/extend_views/FocusSearchHelper.java +124 -0
  11. package/rules/.source/hippy/extend_views/IRecyclerItemView.java +12 -0
  12. package/rules/.source/hippy/extend_views/JSEventHandleView.java +5 -0
  13. package/rules/.source/hippy/extend_views/MarqueeRelayManager.java +133 -0
  14. package/rules/.source/hippy/extend_views/MarqueeRelayTextView.java +211 -0
  15. package/rules/.source/hippy/extend_views/ProgressBarView.java +83 -0
  16. package/rules/.source/hippy/extend_views/ProgressBarViewController.java +145 -0
  17. package/rules/.source/hippy/extend_views/SeekBarView.java +104 -0
  18. package/rules/.source/hippy/extend_views/SeekBarViewController.java +218 -0
  19. package/rules/.source/hippy/extend_views/StateImageView.java +149 -0
  20. package/rules/.source/hippy/extend_views/StateImageViewController.java +34 -0
  21. package/rules/.source/hippy/extend_views/TVButtonView.java +314 -0
  22. package/rules/.source/hippy/extend_views/TVButtonViewController.java +89 -0
  23. package/rules/.source/hippy/extend_views/TVTextView.java +684 -0
  24. package/rules/.source/hippy/extend_views/TVViewActor.java +811 -0
  25. package/rules/.source/hippy/extend_views/TVViewActorHost.java +6 -0
  26. package/rules/.source/hippy/extend_views/TVViewActor/346/216/245/345/205/245.md +66 -0
  27. package/rules/.source/hippy/extend_views/TemplateUtil.java +336 -0
  28. package/rules/.source/hippy/extend_views/TextButtonNode.java +47 -0
  29. package/rules/.source/hippy/extend_views/TextViewController.java +377 -0
  30. package/rules/.source/hippy/extend_views/fastlist/CenterFlyInAnimator.java +96 -0
  31. package/rules/.source/hippy/extend_views/fastlist/ChildOnScreenScroller.java +548 -0
  32. package/rules/.source/hippy/extend_views/fastlist/ClonedViewTag.java +17 -0
  33. package/rules/.source/hippy/extend_views/fastlist/EventDeliverer.java +55 -0
  34. package/rules/.source/hippy/extend_views/fastlist/FastAdapter.java +4683 -0
  35. package/rules/.source/hippy/extend_views/fastlist/FastAdapterUtil.java +982 -0
  36. package/rules/.source/hippy/extend_views/fastlist/FastFlexNode.java +48 -0
  37. package/rules/.source/hippy/extend_views/fastlist/FastFlexView.java +873 -0
  38. package/rules/.source/hippy/extend_views/fastlist/FastFlexViewController.java +130 -0
  39. package/rules/.source/hippy/extend_views/fastlist/FastItemNode.java +67 -0
  40. package/rules/.source/hippy/extend_views/fastlist/FastItemView.java +306 -0
  41. package/rules/.source/hippy/extend_views/fastlist/FastItemViewController.java +106 -0
  42. package/rules/.source/hippy/extend_views/fastlist/FastListModule.java +95 -0
  43. package/rules/.source/hippy/extend_views/fastlist/FastListNode.java +90 -0
  44. package/rules/.source/hippy/extend_views/fastlist/FastListView.java +2466 -0
  45. package/rules/.source/hippy/extend_views/fastlist/FastListViewController.java +1038 -0
  46. package/rules/.source/hippy/extend_views/fastlist/FastListView/346/270/262/346/237/223/346/265/201/347/250/213/345/233/276.graffle +0 -0
  47. package/rules/.source/hippy/extend_views/fastlist/FastPendingView.java +47 -0
  48. package/rules/.source/hippy/extend_views/fastlist/ItemDecorations.java +71 -0
  49. package/rules/.source/hippy/extend_views/fastlist/ItemStoreNode.java +64 -0
  50. package/rules/.source/hippy/extend_views/fastlist/ItemStoreView.java +13 -0
  51. package/rules/.source/hippy/extend_views/fastlist/ItemStoreViewController.java +45 -0
  52. package/rules/.source/hippy/extend_views/fastlist/ListItemHolder.java +7 -0
  53. package/rules/.source/hippy/extend_views/fastlist/ListViewControlProp.java +41 -0
  54. package/rules/.source/hippy/extend_views/fastlist/MouseRecycleView.java +509 -0
  55. package/rules/.source/hippy/extend_views/fastlist/OnFastItemClickListener.java +12 -0
  56. package/rules/.source/hippy/extend_views/fastlist/OnFastItemFocusChangeListener.java +9 -0
  57. package/rules/.source/hippy/extend_views/fastlist/OnFastScrollStateChangedListener.java +7 -0
  58. package/rules/.source/hippy/extend_views/fastlist/PendingListNode.java +18 -0
  59. package/rules/.source/hippy/extend_views/fastlist/PendingViewController.java +13 -0
  60. package/rules/.source/hippy/extend_views/fastlist/PostHandlerView.java +6 -0
  61. package/rules/.source/hippy/extend_views/fastlist/PostTaskHolder.java +20 -0
  62. package/rules/.source/hippy/extend_views/fastlist/ReplaceChildController.java +105 -0
  63. package/rules/.source/hippy/extend_views/fastlist/ReplaceChildView.java +312 -0
  64. package/rules/.source/hippy/extend_views/fastlist/TVListView.java +3692 -0
  65. package/rules/.source/hippy/extend_views/fastlist/TemplateCodeParser.java +247 -0
  66. package/rules/.source/hippy/extend_views/fastlist/Utils.java +572 -0
  67. package/rules/.source/hippy/extend_views/fastlist/ViewTag.java +317 -0
  68. package/rules/.source/hippy/extend_views/fastlist/VirtualListView.java +8 -0
  69. package/rules/.source/hippy/extend_views/fastlist/diff/FastListDataBindingHelper.java +320 -0
  70. package/rules/.source/hippy/extend_views/fastlist/diff/KeyDiffHelper.java +289 -0
  71. package/rules/.source/hippy/extend_views/fastlist/diff/NoKeyDiffHelper.java +278 -0
  72. package/rules/.source/hippy/extend_views/tag/FontTag.java +53 -0
  73. package/rules/.source/hippy/extend_views/tag/HtmlTag.java +191 -0
  74. package/rules/.source/hippy/extend_views/tag/HtmlTagHandler.java +185 -0
  75. package/rules/.source/hippy/extend_views/tag/SpanTag.java +160 -0
  76. package/rules/.source/hippy/extend_views/tag/TextFontSpan.java +102 -0
  77. package/rules/.source/hippy/extend_views/waterfall/Chunk.java +10 -0
  78. package/rules/.source/hippy/extend_views/waterfall/ChunkGroup.java +5 -0
  79. package/rules/.source/hippy/extend_views/waterfall/Section.java +4 -0
  80. package/rules/.source/hippy/extend_views/waterfall/Tabs.java +5 -0
  81. package/rules/.source/hippy/extend_views/waterfall/WaterfallUtils.java +26 -0
  82. package/rules/.source/hippy/hippy_uimanager/ControllerHolder.java +30 -0
  83. package/rules/.source/hippy/hippy_uimanager/ControllerManager.java +651 -0
  84. package/rules/.source/hippy/hippy_uimanager/ControllerRegistry.java +102 -0
  85. package/rules/.source/hippy/hippy_uimanager/ControllerUpdateManger.java +252 -0
  86. package/rules/.source/hippy/hippy_uimanager/CustomControllerHelper.java +425 -0
  87. package/rules/.source/hippy/hippy_uimanager/DiffUtils.java +526 -0
  88. package/rules/.source/hippy/hippy_uimanager/ExtendViewGroup.java +36 -0
  89. package/rules/.source/hippy/hippy_uimanager/HippyCustomViewCreator.java +29 -0
  90. package/rules/.source/hippy/hippy_uimanager/HippyGroupController.java +83 -0
  91. package/rules/.source/hippy/hippy_uimanager/HippyViewBase.java +27 -0
  92. package/rules/.source/hippy/hippy_uimanager/HippyViewController.java +2189 -0
  93. package/rules/.source/hippy/hippy_uimanager/HippyViewEvent.java +52 -0
  94. package/rules/.source/hippy/hippy_uimanager/IHippyZIndexViewGroup.java +24 -0
  95. package/rules/.source/hippy/hippy_uimanager/InternalExtendViewUtil.java +395 -0
  96. package/rules/.source/hippy/hippy_uimanager/ListItemRenderNode.java +143 -0
  97. package/rules/.source/hippy/hippy_uimanager/ListViewRenderNode.java +44 -0
  98. package/rules/.source/hippy/hippy_uimanager/MatrixUtil.java +470 -0
  99. package/rules/.source/hippy/hippy_uimanager/NativeGestureDispatcher.java +349 -0
  100. package/rules/.source/hippy/hippy_uimanager/NativeGestureProcessor.java +188 -0
  101. package/rules/.source/hippy/hippy_uimanager/PullFooterRenderNode.java +43 -0
  102. package/rules/.source/hippy/hippy_uimanager/PullHeaderRenderNode.java +43 -0
  103. package/rules/.source/hippy/hippy_uimanager/RenderManager.java +304 -0
  104. package/rules/.source/hippy/hippy_uimanager/RenderNode.java +533 -0
  105. package/rules/.source/hippy/hippy_uimanager/StateView.java +17 -0
  106. package/rules/.source/hippy/hippy_uimanager/TransformUtil.java +125 -0
  107. package/rules/.source/hippy/hippy_uimanager/ViewGroupDrawingOrderHelper.java +108 -0
  108. package/rules/.source/hippy/hippy_uimanager/ViewStateProvider.java +10 -0
  109. package/rules/.source/hippy/hippy_views/audioview/AudioPlayManager.java +457 -0
  110. package/rules/.source/hippy/hippy_views/audioview/AudioView.java +225 -0
  111. package/rules/.source/hippy/hippy_views/audioview/AudioViewController.java +135 -0
  112. package/rules/.source/hippy/hippy_views/common/CommonBackgroundDrawable.java +58 -0
  113. package/rules/.source/hippy/hippy_views/common/CommonBorder.java +37 -0
  114. package/rules/.source/hippy/hippy_views/custom/HippyCustomPropsController.java +61 -0
  115. package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerListAdapter.java +399 -0
  116. package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerView.java +378 -0
  117. package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerViewController.java +187 -0
  118. package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerViewHolder.java +39 -0
  119. package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerViewWrapper.java +134 -0
  120. package/rules/.source/hippy/hippy_views/hippylist/NodePositionHelper.java +55 -0
  121. package/rules/.source/hippy/hippy_views/hippylist/PreloadHelper.java +54 -0
  122. package/rules/.source/hippy/hippy_views/hippylist/PullFooterEventHelper.java +61 -0
  123. package/rules/.source/hippy/hippy_views/hippylist/PullHeaderEventHelper.java +127 -0
  124. package/rules/.source/hippy/hippy_views/hippylist/RecyclerViewEventHelper.java +394 -0
  125. package/rules/.source/hippy/hippy_views/image/HippyContentDrawable.java +113 -0
  126. package/rules/.source/hippy/hippy_views/image/HippyImageView.java +1608 -0
  127. package/rules/.source/hippy/hippy_views/image/HippyImageViewController.java +382 -0
  128. package/rules/.source/hippy/hippy_views/image/IImageStateListener.java +7 -0
  129. package/rules/.source/hippy/hippy_views/list/ChildOnScreenScroller.java +255 -0
  130. package/rules/.source/hippy/hippy_views/list/HippyListAdapter.java +647 -0
  131. package/rules/.source/hippy/hippy_views/list/HippyListItemView.java +162 -0
  132. package/rules/.source/hippy/hippy_views/list/HippyListItemViewController.java +45 -0
  133. package/rules/.source/hippy/hippy_views/list/HippyListView.java +915 -0
  134. package/rules/.source/hippy/hippy_views/list/HippyListViewController.java +622 -0
  135. package/rules/.source/hippy/hippy_views/list/HippyRecycler.java +31 -0
  136. package/rules/.source/hippy/hippy_views/list/IRecycleItemTypeChange.java +23 -0
  137. package/rules/.source/hippy/hippy_views/list/ItemDecorations.java +70 -0
  138. package/rules/.source/hippy/hippy_views/list/NegativeLongKeyFlinger.java +156 -0
  139. package/rules/.source/hippy/hippy_views/list/NodeHolder.java +34 -0
  140. package/rules/.source/hippy/hippy_views/list/RecycleViewFlinger.java +126 -0
  141. package/rules/.source/hippy/hippy_views/list/TVRecyclerView.java +2070 -0
  142. package/rules/.source/hippy/hippy_views/list/TVSingleLineListView.java +15 -0
  143. package/rules/.source/hippy/hippy_views/modal/HippyModalHostManager.java +102 -0
  144. package/rules/.source/hippy/hippy_views/modal/HippyModalHostView.java +597 -0
  145. package/rules/.source/hippy/hippy_views/modal/ModalHostHelper.java +46 -0
  146. package/rules/.source/hippy/hippy_views/modal/ModalStyleNode.java +34 -0
  147. package/rules/.source/hippy/hippy_views/modal/RequestCloseEvent.java +32 -0
  148. package/rules/.source/hippy/hippy_views/modal/ShowEvent.java +31 -0
  149. package/rules/.source/hippy/hippy_views/navigator/Navigator.java +126 -0
  150. package/rules/.source/hippy/hippy_views/navigator/NavigatorController.java +120 -0
  151. package/rules/.source/hippy/hippy_views/refresh/HippyPullFooterView.java +47 -0
  152. package/rules/.source/hippy/hippy_views/refresh/HippyPullFooterViewController.java +65 -0
  153. package/rules/.source/hippy/hippy_views/refresh/HippyPullHeaderView.java +39 -0
  154. package/rules/.source/hippy/hippy_views/refresh/HippyPullHeaderViewController.java +104 -0
  155. package/rules/.source/hippy/hippy_views/refresh/RefreshWrapper.java +237 -0
  156. package/rules/.source/hippy/hippy_views/refresh/RefreshWrapperController.java +62 -0
  157. package/rules/.source/hippy/hippy_views/refresh/RefreshWrapperItemController.java +39 -0
  158. package/rules/.source/hippy/hippy_views/refresh/RefreshWrapperItemView.java +26 -0
  159. package/rules/.source/hippy/hippy_views/scroll/HippyHorizontalScrollView.java +500 -0
  160. package/rules/.source/hippy/hippy_views/scroll/HippyOnScrollHelper.java +39 -0
  161. package/rules/.source/hippy/hippy_views/scroll/HippyScrollView.java +46 -0
  162. package/rules/.source/hippy/hippy_views/scroll/HippyScrollViewController.java +178 -0
  163. package/rules/.source/hippy/hippy_views/scroll/HippyScrollViewEventHelper.java +92 -0
  164. package/rules/.source/hippy/hippy_views/scroll/HippyVerticalScrollView.java +522 -0
  165. package/rules/.source/hippy/hippy_views/text/HippyTextView.java +512 -0
  166. package/rules/.source/hippy/hippy_views/text/HippyTextViewController.java +77 -0
  167. package/rules/.source/hippy/hippy_views/textinput/HippyTextInput.java +668 -0
  168. package/rules/.source/hippy/hippy_views/textinput/HippyTextInputController.java +528 -0
  169. package/rules/.source/hippy/hippy_views/textinput/TextInputNode.java +115 -0
  170. package/rules/.source/hippy/hippy_views/videoview/APEZProvider.java +287 -0
  171. package/rules/.source/hippy/hippy_views/videoview/APKExpansionSupport.java +82 -0
  172. package/rules/.source/hippy/hippy_views/videoview/PivotPoint.java +13 -0
  173. package/rules/.source/hippy/hippy_views/videoview/ScalableType.java +34 -0
  174. package/rules/.source/hippy/hippy_views/videoview/ScalableVideoView.java +265 -0
  175. package/rules/.source/hippy/hippy_views/videoview/ScaleManager.java +191 -0
  176. package/rules/.source/hippy/hippy_views/videoview/Size.java +19 -0
  177. package/rules/.source/hippy/hippy_views/videoview/VideoHippyView.java +917 -0
  178. package/rules/.source/hippy/hippy_views/videoview/VideoHippyViewController.java +236 -0
  179. package/rules/.source/hippy/hippy_views/videoview/ZipResourceFile.java +427 -0
  180. package/rules/.source/hippy/hippy_views/view/CardRootView.java +28 -0
  181. package/rules/.source/hippy/hippy_views/view/CustomLayoutView.java +10 -0
  182. package/rules/.source/hippy/hippy_views/view/CustomNodeView.java +5 -0
  183. package/rules/.source/hippy/hippy_views/view/DialogViewGroup.java +113 -0
  184. package/rules/.source/hippy/hippy_views/view/HippyViewGroup.java +2042 -0
  185. package/rules/.source/hippy/hippy_views/view/HippyViewGroupController.java +583 -0
  186. package/rules/.source/hippy/hippy_views/view/WindowRoot.java +5 -0
  187. package/rules/.source/hippy/hippy_views/viewpager/HippyViewPager.java +308 -0
  188. package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerAdapter.java +148 -0
  189. package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerController.java +246 -0
  190. package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerItem.java +27 -0
  191. package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerItemController.java +42 -0
  192. package/rules/.source/hippy/hippy_views/viewpager/ViewPagerPageChangeListener.java +114 -0
  193. package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageItemExposureEvent.java +40 -0
  194. package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageScrollEvent.java +43 -0
  195. package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageScrollStateChangedEvent.java +42 -0
  196. package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageSelectedEvent.java +42 -0
  197. package/rules/.source/hippy/hippy_views/webview/HippyWebView.java +160 -0
  198. package/rules/.source/hippy/hippy_views/webview/HippyWebViewBridge.java +20 -0
  199. package/rules/.source/hippy/hippy_views/webview/HippyWebViewController.java +103 -0
  200. package/rules/.source/hippy/hippy_views/webview/HippyWebViewInner.java +77 -0
  201. package/rules/.windsurfrules +27 -4
  202. package/rules/AGENTS.md +27 -4
  203. package/rules/CLAUDE.md +27 -3
  204. package/rules/GEMINI.md +25 -3
@@ -0,0 +1,2042 @@
1
+ /* Tencent is pleased to support the open source community by making Hippy available.
2
+ * Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights reserved.
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
+ package com.tencent.mtt.hippy.views.view;
17
+
18
+ import android.animation.Animator;
19
+ import android.animation.AnimatorListenerAdapter;
20
+ import android.animation.ObjectAnimator;
21
+ import android.animation.ValueAnimator;
22
+ import android.annotation.SuppressLint;
23
+ import android.content.Context;
24
+ import android.graphics.Canvas;
25
+ import android.graphics.Color;
26
+ import android.graphics.Path;
27
+ import android.graphics.Rect;
28
+ import android.graphics.RectF;
29
+ import android.graphics.drawable.GradientDrawable;
30
+ import android.os.Build;
31
+ import android.support.annotation.NonNull;
32
+ import android.text.TextUtils;
33
+ import android.util.Log;
34
+ import android.view.InputDevice;
35
+ import android.view.KeyEvent;
36
+ import android.view.MotionEvent;
37
+ import android.view.View;
38
+ import android.view.ViewConfiguration;
39
+ import android.view.ViewGroup;
40
+ import android.view.ViewParent;
41
+ import android.view.ViewTreeObserver;
42
+ import android.view.animation.CycleInterpolator;
43
+
44
+ import com.tencent.extend.AutoFocusManager;
45
+ import com.tencent.extend.FocusManagerModule;
46
+ import com.tencent.extend.FocusUtils;
47
+ import com.tencent.extend.RenderUtil;
48
+ import com.tencent.extend.TVFocusScaleExcuter;
49
+ import com.tencent.extend.TVViewUtil;
50
+ import com.tencent.extend.TriggerTaskHost;
51
+ import com.tencent.extend.TriggerTaskManagerModule;
52
+ import com.tencent.extend.views.EngineRootView;
53
+ import com.tencent.extend.views.FocusSearchHelper;
54
+ import com.tencent.extend.views.fastlist.Utils;
55
+ import com.tencent.mtt.hippy.FocusDispatchView;
56
+ import com.tencent.mtt.hippy.HippyEngineContext;
57
+ import com.tencent.mtt.hippy.HippyInstanceContext;
58
+ import com.tencent.mtt.hippy.R;
59
+ import com.tencent.mtt.hippy.common.HippyArray;
60
+ import com.tencent.mtt.hippy.common.HippyMap;
61
+ import com.tencent.mtt.hippy.dom.node.NodeProps;
62
+ import com.tencent.mtt.hippy.uimanager.ControllerManager;
63
+ import com.tencent.mtt.hippy.uimanager.ExtendViewGroup;
64
+ import com.tencent.mtt.hippy.uimanager.HippyViewEvent;
65
+ import com.tencent.mtt.hippy.uimanager.IHippyZIndexViewGroup;
66
+ import com.tencent.mtt.hippy.uimanager.InternalExtendViewUtil;
67
+ import com.tencent.mtt.hippy.uimanager.ViewGroupDrawingOrderHelper;
68
+ import com.tencent.mtt.hippy.utils.ExtendUtil;
69
+ import com.tencent.mtt.hippy.utils.LogAdapterUtils;
70
+ import com.tencent.mtt.hippy.utils.LogUtils;
71
+ import com.tencent.mtt.hippy.utils.PixelUtil;
72
+ import com.tencent.mtt.hippy.views.image.HippyImageView;
73
+
74
+ import java.util.ArrayList;
75
+
76
+ @SuppressWarnings({"unused"})
77
+ public class HippyViewGroup extends HippyImageView implements IHippyZIndexViewGroup, TriggerTaskHost, ExtendViewGroup, CustomLayoutView {
78
+
79
+ private static final int LAYER_TYPE_NOT_SET = -1;
80
+ private final ViewGroupDrawingOrderHelper mDrawingOrderHelper;
81
+ float mDownX = 0;
82
+ float mDownY = 0;
83
+ boolean isHandlePullUp = false;
84
+ // private CommonBackgroundDrawable mBGDrawable;
85
+ // private NativeGestureDispatcher mGestureDispatcher;
86
+ private String mOverflow;
87
+ private Path mOverflowPath;
88
+ private RectF mOverflowRect;
89
+ private int mOldLayerType;
90
+ private ViewConfiguration mViewConfiguration;
91
+
92
+ // Scroller mScroller;
93
+
94
+ //zhaopeng add
95
+ private int overFlowViewIndex = -1;
96
+ private boolean mBringToFrontOnFocus = false;
97
+
98
+ private boolean useAdvancedFocusSearch = false;
99
+
100
+
101
+ private GradientDrawable mBackDrawable;
102
+
103
+ private View mSpecialFocusSearchRequest;
104
+
105
+ public static final String TAG = "DIV_LOG";
106
+ //在tvList焦点滚动时是否以此为目标
107
+ private boolean isFocusScrollTarget = false;
108
+ private final HippyEngineContext hippyEngineContext;
109
+ //焦点抖动开关
110
+ protected boolean shakeSelf;
111
+ private boolean interceptKeyEvent = false;
112
+ private HippyArray interceptKeyEvents = null;
113
+ private HippyViewEvent interceptKeyJSEvent = null;
114
+ //Focus memory
115
+ protected View memoryFocused = null;
116
+ private boolean focusMemoryEnable = false;
117
+
118
+ private boolean enableOverScrollX = false;
119
+ private boolean enableOverScrollY = false;
120
+ private FocusSearchHelper mFocusSearchHelper;
121
+ // protected boolean overScrollImmediately = true;
122
+
123
+
124
+ public void setEnableOverScrollX(boolean enableOverScrollX) {
125
+ this.enableOverScrollX = enableOverScrollX;
126
+ }
127
+
128
+ public void setEnableOverScrollY(boolean enableOverScrollY) {
129
+ this.enableOverScrollY = enableOverScrollY;
130
+ }
131
+
132
+ public boolean isEnableOverScrollX() {
133
+ return enableOverScrollX;
134
+ }
135
+
136
+ public boolean isEnableOverScrollY() {
137
+ return enableOverScrollY;
138
+ }
139
+
140
+ public void setInterceptKeyEvent(boolean b){
141
+ Log.i(TAG,"setInterceptKeyEvent :"+b +",this:"+this);
142
+ this.interceptKeyEvent = b;
143
+ }
144
+
145
+ public void setInterceptKeyEvents(HippyArray array) {
146
+ Log.i(TAG,"setInterceptKeyEvents :"+array+",this:"+this);
147
+ this.interceptKeyEvents = array;
148
+ }
149
+
150
+ public HippyViewGroup(Context context) {
151
+ super(context);
152
+
153
+
154
+ // setBackgroundResource(R.drawable.selector_item_bg);
155
+ mDrawingOrderHelper = new ViewGroupDrawingOrderHelper(this);
156
+ mOldLayerType = LAYER_TYPE_NOT_SET;
157
+ setScaleType(ScaleType.ORIGIN);
158
+ /*zhaopeng add 默认false*/
159
+ // setClipChildren(false);
160
+ //初始化焦点抖动配置
161
+ hippyEngineContext = ((HippyInstanceContext) context).getEngineContext();
162
+ if (hippyEngineContext != null) {
163
+ shakeSelf = hippyEngineContext.getGlobalConfigs().getEsBaseConfigManager().IsShakeSelf();
164
+ }
165
+ mFocusSearchHelper = new FocusSearchHelper(this);
166
+ }
167
+
168
+ @Override
169
+ public void onViewRemoved(View child) {
170
+ super.onViewRemoved(child);
171
+ if (defaultSectionPosition > -1 && defaultSectionPosition == searchChildIndex(child)) {
172
+ defaultSectionPosition = -1;
173
+ }
174
+ }
175
+
176
+ @Override
177
+ public void onViewAdded(View child) {
178
+ super.onViewAdded(child);
179
+ if (defaultSectionPosition > -1 && defaultSectionPosition == searchChildIndex(child)) {
180
+ changeSelectState(defaultSectionPosition,true);
181
+ }
182
+
183
+ }
184
+
185
+ // @Override
186
+ // protected void onLayout(boolean changed, int l, int t, int r, int b)
187
+ // {
188
+ //
189
+ // }
190
+
191
+ // @Override
192
+ // public void requestLayout()
193
+ // {
194
+ // //super.requestLayout();
195
+ // }
196
+
197
+ @SuppressWarnings("SuspiciousNameCombination")
198
+ @Override
199
+ protected void dispatchDraw(Canvas canvas) {
200
+ if (mOverflow != null) {
201
+ switch (mOverflow) {
202
+ case "visible":
203
+ if (mOverflowPath != null) {
204
+ mOverflowPath.rewind();
205
+ }
206
+ restoreLayerType();
207
+ break;
208
+ case "hidden":
209
+ if (mBGDrawable != null) {
210
+ float left = 0f;
211
+ float top = 0f;
212
+ float right = getWidth();
213
+ float bottom = getHeight();
214
+ float borderWidth;
215
+ if (mBGDrawable.getBorderWidthArray() != null
216
+ && mBGDrawable.getBorderWidthArray()[0] != 0f) {
217
+ borderWidth = mBGDrawable.getBorderWidthArray()[0];
218
+ left += borderWidth;
219
+ top += borderWidth;
220
+ right -= borderWidth;
221
+ bottom -= borderWidth;
222
+ }
223
+ float radius =
224
+ mBGDrawable.getBorderRadiusArray() != null ? mBGDrawable.getBorderRadiusArray()[0]
225
+ : 0f;
226
+
227
+ if (radius > 0f) {
228
+ if (mOverflowPath == null) {
229
+ mOverflowPath = new Path();
230
+ }
231
+ mOverflowPath.rewind();
232
+ if (mOverflowRect == null) {
233
+ mOverflowRect = new RectF();
234
+ }
235
+ mOverflowRect.set(left, top, right, bottom);
236
+ mOverflowPath.addRoundRect(mOverflowRect, radius, radius, Path.Direction.CW);
237
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
238
+ if (mOldLayerType == LAYER_TYPE_NOT_SET) {
239
+ mOldLayerType = this.getLayerType();
240
+ }
241
+ this.setLayerType(LAYER_TYPE_SOFTWARE, null);
242
+ }
243
+ try {
244
+ canvas.clipPath(mOverflowPath);
245
+ } catch (Throwable throwable) {
246
+ restoreLayerType();
247
+ }
248
+ }
249
+ }
250
+ break;
251
+ default:
252
+ restoreLayerType();
253
+ break;
254
+ }
255
+ }
256
+
257
+ super.dispatchDraw(canvas);
258
+
259
+ //zhaopeng add
260
+ if (mBringToFrontOnFocus && getFocusedChild() != null) {
261
+ super.drawChild(canvas, getFocusedChild(), getDrawingTime());
262
+ }
263
+ // if (mScroller != null) {
264
+ // mScroller.computeScrollOffset();
265
+ // int cx = getScrollX();
266
+ // int cy = getScrollY();
267
+ // if(cx != mScroller.getCurrX() || cy != mScroller.getCurrY()){
268
+ // postInvalidateDelayed(16);
269
+ // scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
270
+ // }
271
+ // }
272
+
273
+ if (overFlowViewIndex > -1 && overFlowViewIndex < getChildCount()) {
274
+ final View v = getChildAt(overFlowViewIndex);
275
+ if (v != null) {
276
+ super.drawChild(canvas, v, getDrawingTime());
277
+ }
278
+ }
279
+ // String testString = "View ID:" + this.getId();
280
+ // Paint mPaint = new Paint();
281
+ // mPaint.setStrokeWidth(3);
282
+ // mPaint.setTextSize(40);
283
+ // mPaint.setColor(Color.RED);
284
+ // mPaint.setTextAlign(Paint.Align.LEFT);
285
+ // Rect bounds = new Rect();
286
+ // mPaint.getTextBounds(testString, 0, testString.length(), bounds);
287
+ // Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
288
+ // int baseline = (getMeasuredHeight() - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top;
289
+ // canvas.drawText(testString, getMeasuredWidth() / 2 - bounds.width() / 2, baseline, mPaint);
290
+
291
+ if (needLayoutFromCustom) {
292
+ onMeasureCustom();
293
+ needLayoutFromCustom = false;
294
+ }
295
+
296
+ }
297
+
298
+ int[] preferSize = new int[4];
299
+
300
+ protected void onMeasureCustom() {
301
+ if (LogUtils.isDebug()) {
302
+ Log.e(CustomLayoutView.TAG, "layoutCustom on DispatchDraw view:" + this);
303
+ }
304
+ for (int i = 0; i < getChildCount(); i++) {
305
+ final View child = getChildAt(i);
306
+ if (child instanceof CustomNodeView) {
307
+ ((CustomNodeView) child).getNodeSize(preferSize);
308
+ if (preferSize[2] > -1 || preferSize[3] > -1) {
309
+ RenderUtil.reLayoutView(child, preferSize[0], preferSize[1], preferSize[2], preferSize[3]);
310
+ }
311
+ } else if (child != null) {
312
+ RenderUtil.requestNodeLayout2(getContext(), child.getId());
313
+ }
314
+ }
315
+ }
316
+
317
+
318
+ private void restoreLayerType() {
319
+ if (mOldLayerType > LAYER_TYPE_NOT_SET) {
320
+ this.setLayerType(mOldLayerType, null);
321
+ }
322
+ }
323
+
324
+
325
+
326
+ // public void setBorderRadius(float radius, int position)
327
+ // {
328
+ // getBackGround().setBorderRadius(radius, position);
329
+ // }
330
+ //
331
+ // public void setBorderWidth(float width, int position)
332
+ // {
333
+ // getBackGround().setBorderWidth(width, position);
334
+ // }
335
+ //
336
+ // public void setBorderColor(int color, int position)
337
+ // {
338
+ // getBackGround().setBorderColor(color, position);
339
+ // }
340
+ //
341
+ // private CommonBackgroundDrawable getBackGround()
342
+ // {
343
+ // if (mBGDrawable == null)
344
+ // {
345
+ // mBGDrawable = new CommonBackgroundDrawable();
346
+ // Drawable currBGDrawable = getBackground();
347
+ // super.setBackgroundDrawable(null);
348
+ // if (currBGDrawable == null)
349
+ // {
350
+ // super.setBackgroundDrawable(mBGDrawable);
351
+ // }
352
+ // else
353
+ // {
354
+ // LayerDrawable layerDrawable = new LayerDrawable(new Drawable[] { mBGDrawable, currBGDrawable });
355
+ // super.setBackgroundDrawable(layerDrawable);
356
+ // }
357
+ // }
358
+ // return mBGDrawable;
359
+ // }
360
+
361
+ public void smoothScrollBy(int x,int y){
362
+ //Fixme 这里初步实现了无动画的滚动,后续支持动画
363
+ // if (mScroller == null) {
364
+ // mScroller = new Scroller(getContext());
365
+ // }
366
+ // mScroller.startScroll(getScrollX(),getScrollY(),x,y,200);
367
+ //// scrollBy(x,y);
368
+ // postInvalidateDelayed(16);
369
+ }
370
+
371
+
372
+
373
+ public void setOverflow(String overflow) {
374
+ mOverflow = overflow;
375
+ //robinsli Android 支持 overflow: visible,超出容器之外的属性节点也可以正常显示
376
+ if (!TextUtils.isEmpty(mOverflow)) {
377
+ switch (mOverflow) {
378
+ case "visible":
379
+ setClipChildren(false); //可以超出父亲区域
380
+ break;
381
+ case "hidden": {
382
+ setClipChildren(true); //默认值是false
383
+ break;
384
+ }
385
+ }
386
+ }
387
+ invalidate();
388
+ }
389
+
390
+ // @Override
391
+ // public void setBackgroundColor(int color)
392
+ // {
393
+ // getBackGround().setBackgroundColor(color);
394
+ // }
395
+
396
+ // @Override
397
+ // public boolean onTouchEvent(MotionEvent event)
398
+ // {
399
+ // boolean result = super.onTouchEvent(event);
400
+ // if (mGestureDispatcher != null)
401
+ // {
402
+ // result |= mGestureDispatcher.handleTouchEvent(event);
403
+ // }
404
+ // return result;
405
+ // }
406
+
407
+ @Override
408
+ public boolean onInterceptTouchEvent(MotionEvent ev) {
409
+ int action = ev.getAction() & MotionEvent.ACTION_MASK;
410
+ if (action == MotionEvent.ACTION_DOWN) {
411
+ mDownX = ev.getX();
412
+ mDownY = ev.getY();
413
+ isHandlePullUp = false;
414
+ }
415
+
416
+ boolean result = super.onInterceptTouchEvent(ev);
417
+
418
+ if (mGestureDispatcher != null) {
419
+ result |= mGestureDispatcher.needHandle(NodeProps.ON_INTERCEPT_TOUCH_EVENT);
420
+ }
421
+
422
+ if (!result && mGestureDispatcher != null && mGestureDispatcher
423
+ .needHandle(NodeProps.ON_INTERCEPT_PULL_UP_EVENT)) {
424
+ //noinspection SwitchStatementWithTooFewBranches
425
+ switch (action) {
426
+ case MotionEvent.ACTION_MOVE: {
427
+ if (isHandlePullUp) {
428
+ break;
429
+ }
430
+ if (mViewConfiguration == null) {
431
+ //noinspection deprecation
432
+ mViewConfiguration = new ViewConfiguration();
433
+ }
434
+ float dx = ev.getX() - mDownX;
435
+ float dy = ev.getY() - mDownY;
436
+ if (dy < 0 && Math.abs(dx) < Math.abs(dy) && Math.abs(dy) > mViewConfiguration
437
+ .getScaledTouchSlop()) {
438
+ mGestureDispatcher.handle(NodeProps.ON_TOUCH_DOWN, mDownX, mDownY);
439
+ isHandlePullUp = true;
440
+ }
441
+ break;
442
+ }
443
+ }
444
+ result = isHandlePullUp;
445
+ }
446
+ return result;
447
+ }
448
+
449
+ // @Override
450
+ // public NativeGestureDispatcher getGestureDispatcher()
451
+ // {
452
+ // return mGestureDispatcher;
453
+ // }
454
+
455
+ // @Override
456
+ // public void setGestureDispatcher(NativeGestureDispatcher dispatcher)
457
+ // {
458
+ // mGestureDispatcher = dispatcher;
459
+ // }
460
+
461
+ @Override
462
+ protected int getChildDrawingOrder(int childCount, int index) {
463
+ return mDrawingOrderHelper.getChildDrawingOrder(childCount, index);
464
+ }
465
+
466
+ @Override
467
+ public int getZIndexMappedChildIndex(int index) {
468
+ if (mDrawingOrderHelper.shouldEnableCustomDrawingOrder()) {
469
+ return mDrawingOrderHelper.getChildDrawingOrder(getChildCount(), index);
470
+ } else {
471
+ return index;
472
+ }
473
+ }
474
+
475
+ @Override
476
+ public void updateDrawingOrder() {
477
+ mDrawingOrderHelper.update();
478
+ setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder());
479
+ invalidate();
480
+ }
481
+
482
+ @Override
483
+ public void addView(View child, int index) {
484
+ super.addView(child, index);
485
+ mDrawingOrderHelper.handleAddView(child);
486
+ setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder());
487
+ }
488
+
489
+ @Override
490
+ public void removeView(View view) {
491
+ super.removeView(view);
492
+ mDrawingOrderHelper.handleRemoveView(view);
493
+ setChildrenDrawingOrderEnabled(mDrawingOrderHelper.shouldEnableCustomDrawingOrder());
494
+ }
495
+
496
+ @Override
497
+ public void onResetBeforeCache() {
498
+ super.onResetBeforeCache();
499
+ memoryFocused = null;
500
+ }
501
+
502
+ @Override
503
+ public void resetProps() {
504
+ // HippyViewController.resetTransform(this);
505
+
506
+ HippyViewGroupController.removeViewZIndex(this);
507
+
508
+ // mBGDrawable = null;
509
+ // super.setBackgroundDrawable(null);
510
+ mOverflow = null;
511
+ memoryFocused = null;
512
+ // if(enableOverScrollY || enableOverScrollX) {
513
+ // overScrollImmediately = true;
514
+ // scrollTo(0, 0);
515
+ // setEnableOverScrollX(false);
516
+ // setEnableOverScrollY(false);
517
+ // }
518
+ setClipChildren(true); //默认值是false
519
+ // setAlpha(1.0f);
520
+ }
521
+
522
+ // @Override
523
+ // public void clear()
524
+ // {
525
+ //
526
+ // }
527
+
528
+ public void setUseAdvancedFocusSearch(boolean useAdvancedFocusSearch) {
529
+ this.useAdvancedFocusSearch = useAdvancedFocusSearch;
530
+ LogUtils.d(TAG, "setUseAdvancedFocusSearch :" + useAdvancedFocusSearch + ",this:" + this);
531
+ }
532
+
533
+ @Override
534
+ protected void onSizeChanged(int w, int h, int oldw, int oldh) {
535
+ super.onSizeChanged(w, h, oldw, oldh);
536
+
537
+ // if (oldw == 0 || oldh == 0) {
538
+ // overScrollImmediately = true;
539
+ // }
540
+ if (mBackDrawable != null) {
541
+ mBackDrawable.setBounds(0, 0, w, h);
542
+ }
543
+
544
+ }
545
+
546
+ @Override
547
+ protected void onChangeShowOnState() {
548
+ super.onChangeShowOnState();
549
+ }
550
+
551
+ @Override
552
+ public void onDraw(Canvas canvas) {
553
+ super.onDraw(canvas);
554
+ }
555
+
556
+
557
+ @Override
558
+ public void draw(Canvas canvas) {
559
+ if (mBackDrawable != null) {
560
+ if (mBackDrawable.getBounds().isEmpty()) {
561
+ if (getBackgroundDrawable().getBounds().isEmpty()) {
562
+ mBackDrawable.setBounds(new Rect(0, 0, getWidth(), getHeight()));
563
+ } else {
564
+ mBackDrawable.setBounds(getBackgroundDrawable().getBounds());
565
+ }
566
+ }
567
+ mBackDrawable.draw(canvas);
568
+ }
569
+ super.draw(canvas);
570
+ // Log.v("zhaopeng","draw called isFocused:"+isFocused());
571
+ }
572
+
573
+ public void setBringFocusChildToFront(boolean mBringToFrontOnFocus) {
574
+ this.mBringToFrontOnFocus = mBringToFrontOnFocus;
575
+ if(LogUtils.isDebug()){
576
+ Log.i(TAG,"setBringFocusChildToFront this:"+this+",b : "+mBringToFrontOnFocus);
577
+ }
578
+ postInvalidateDelayed(16);
579
+ }
580
+
581
+ @Override
582
+ public View focusSearch(View focused, int direction) {
583
+ final View result = useAdvancedFocusSearch ? advanceFocusSearch(focused, direction) : super.focusSearch(focused, direction);
584
+ final int nextId = InternalExtendViewUtil.findInterceptViewID(this, direction);
585
+ if(LogUtils.isDebug()) {
586
+ Log.i(FocusDispatchView.TAG, "focusSearch nextId :" + nextId + ",result:" + ExtendUtil.debugViewLite(result) + ",this:" + ExtendUtil.debugFocusInfo(this));
587
+ }
588
+ if (nextId > -1) {
589
+ final boolean nextInGroup = TVViewUtil.isViewDescendantOf(result, this);
590
+ if (!nextInGroup || result == null) {
591
+ //
592
+ if (shakeSelf) {
593
+ shakeSelf(focused, direction);
594
+ }
595
+ return InternalExtendViewUtil.interceptViewGroupIfNeed(this,nextId, focused, result);
596
+ // return null;
597
+ }
598
+ }
599
+ return result;
600
+ }
601
+
602
+
603
+
604
+ private void markSpecifiedFocusSearch(View specialTarget) {
605
+ // Log.d(TAG, "+mark SpecifiedFocusSearch target : "+specialTarget)
606
+ mSpecialFocusSearchRequest = specialTarget;
607
+ }
608
+
609
+ private void consumeSpecifiedFocusSearchRequest() {
610
+ if (mSpecialFocusSearchRequest != null) {
611
+ // Log.d(TAG, "-consume SpecifiedFocusSearchRequest")
612
+ mSpecialFocusSearchRequest = null;
613
+ }
614
+ }
615
+
616
+ private boolean isSpecifiedFocusSearch() {
617
+ return mSpecialFocusSearchRequest != null;
618
+ }
619
+
620
+ private ArrayList<View> mTempFocusList = new ArrayList<>();
621
+
622
+ protected View advanceFocusSearch(View focused, int direction) {
623
+ return this.advanceFocusSearch(focused, direction, false);
624
+ }
625
+
626
+ protected View advanceFocusSearch(View focused, int direction, boolean justSpecial) {
627
+ if (LogUtils.isDebug()) {
628
+ Log.d(TAG, "-----------------begin : focusSearch with focused : $focused direction : $direction -------------");
629
+ Log.d(FocusDispatchView.TAG, "-----------------begin : advanceFocusSearch in div with focused : $focused direction : $direction -------------");
630
+ }
631
+ //return super.focusSearch(focused, direction)
632
+
633
+ //寻找结果
634
+ View found = null;
635
+ //用户自定义的目标view
636
+ View userSpecifiedTarget = null;
637
+ //用户自定义的目标viewID
638
+ String userSpecifiedTargetName = null;
639
+ String userSpecifiedTargetSID = null;
640
+ //当前焦点的parent
641
+ ViewGroup focusedParent = null;
642
+
643
+ try {
644
+
645
+ FocusUtils.FocusParams fp = null;
646
+ //1, find user specified
647
+ if (focused != null) {
648
+ //发现用户指定targetView,则直接调用此view的addFocusables方法
649
+ fp = ExtendUtil.findUserSpecifiedNextFocusViewIdTraverse(this, focused, direction,this);
650
+ if (LogUtils.isDebug()) {
651
+ Log.i(FocusDispatchView.TAG,"div advance focus search fp :"+fp+",focused:"+ExtendUtil.debugViewLite(focused)+",this:"+ExtendUtil.debugViewLite(this));
652
+ }
653
+ userSpecifiedTargetName = fp.specifiedTargetViewName;
654
+ userSpecifiedTargetSID = fp.specifiedTargetSID;
655
+ if(userSpecifiedTargetSID != null && userSpecifiedTargetSID.equals(ExtendUtil.getViewSID(focused))) {
656
+ //Log.d(FocusDispatchView.TAG, "0 : find focused self " + ExtendUtil.debugViewLite(userSpecifiedTarget));
657
+ userSpecifiedTarget = focused;
658
+ }else if(userSpecifiedTargetName != null && userSpecifiedTargetName.equals(ExtendUtil.getViewName(focused))) {
659
+ userSpecifiedTarget = focused;
660
+ }
661
+ //2025.07.22 新增nextFocus设成自己时,阻拦逻辑
662
+ if(userSpecifiedTarget != null && ExtendUtil.isPureFocusView(userSpecifiedTarget)) {
663
+ if(LogUtils.isDebug()) {
664
+ Log.i(FocusDispatchView.TAG, "0 : find nextFocused is self " + ExtendUtil.debugViewLite(userSpecifiedTarget));
665
+ }
666
+ return focused;
667
+ }
668
+ userSpecifiedTarget = ExtendUtil.findViewByNameOrSID(focused,fp, this);
669
+ if(LogUtils.isDebug()){
670
+ Log.d(FocusDispatchView.TAG,"1 : pre find userSpecifiedTarget "+ExtendUtil.debugViewLite(userSpecifiedTarget));
671
+ }
672
+ if(userSpecifiedTarget != null){
673
+ if(!userSpecifiedTarget.isFocusable()){
674
+ if(Utils.isParentItemRootView(userSpecifiedTarget)){
675
+ userSpecifiedTarget = Utils.getPlaceholderContainer(userSpecifiedTarget);
676
+ }
677
+ }
678
+ if (LogUtils.isDebug()) {
679
+ Log.e(FocusDispatchView.TAG, "advanceFocusSearch in div return userSpecifiedTarget FocusParams:" + fp + ",result:" + ExtendUtil.debugViewLite(userSpecifiedTarget));
680
+ }
681
+ if(userSpecifiedTarget != null && userSpecifiedTarget.getVisibility() != View.VISIBLE){
682
+ userSpecifiedTarget = null;
683
+ }
684
+ }
685
+ if (LogUtils.isDebug()) {
686
+ Log.d(FocusDispatchView.TAG, "1 : find specifiedTargetViewName is " +
687
+ "$userSpecifiedTargetName specifiedView is $userSpecifiedTarget name:" + userSpecifiedTargetName + ",userSpecifiedTargetSID:" + userSpecifiedTargetSID+",userSpecifiedTarget:"+ExtendUtil.debugViewLite(userSpecifiedTarget));
688
+ if(userSpecifiedTarget instanceof ViewGroup) {
689
+ Log.d(FocusDispatchView.TAG, "1 : userSpecifiedTarget visible :" + userSpecifiedTarget.getVisibility() + ",alpha :" + userSpecifiedTarget.getAlpha()
690
+ + ",descendantFocusability isBlock:" + (((ViewGroup) userSpecifiedTarget).getDescendantFocusability() == ViewGroup.FOCUS_BLOCK_DESCENDANTS) + ",focusable :" + userSpecifiedTarget.isFocusable());
691
+ }
692
+ }
693
+ if (focused.getParent() instanceof ViewGroup)
694
+ focusedParent = (ViewGroup) focused.getParent();
695
+ }
696
+
697
+ //2 , find focus
698
+ if (userSpecifiedTarget != null && userSpecifiedTarget.getVisibility() == View.VISIBLE) {
699
+
700
+ if (fp.isPureSpecifiedTarget && ExtendUtil.isPureFocusView(userSpecifiedTarget)) {
701
+ found = userSpecifiedTarget;
702
+ if (LogUtils.isDebug()) {
703
+ Log.d(FocusDispatchView.TAG, "2-0 : find userSpecifiedTarget is pure specified target $found :" + ExtendUtil.debugViewLite(found));
704
+ }
705
+ }
706
+
707
+ markSpecifiedFocusSearch(userSpecifiedTarget);
708
+ // it.addFocusables(views,direction,focusableMode)
709
+ //这里要区分出来userSpecifiedTarget是一个focusable的View,还是一个ViewGroup
710
+
711
+ //1,优先在当前parent中寻找,以保证优先搜索比较近的view
712
+ if (found == null) {
713
+ if (focusedParent != userSpecifiedTarget && focusedParent != userSpecifiedTarget.getParent()) { //确保俩个parent不是同一个
714
+ if (focusedParent != null)
715
+ focusedParent.addFocusables(mTempFocusList, direction);
716
+ //zhaopeng 20190327 由于这里focused不是focusedParent的子view时,会发生崩溃,所以这里try catch
717
+ if(mTempFocusList.size() > 0) {
718
+ found = ExtendUtil.executeFindNextFocus(focusedParent, focused, direction);
719
+ }
720
+ if (LogUtils.isDebug()) {
721
+ Log.d(FocusDispatchView.TAG, "2-1: find from focusedParent found : $found :" + ExtendUtil.debugViewLite(found));
722
+ }
723
+ }
724
+ }
725
+ //2, 从IFocusGroup中寻找
726
+
727
+ //3, userSpecifiedTarget中寻找
728
+ if (found == null) {
729
+ mTempFocusList.clear();
730
+ userSpecifiedTarget.addFocusables(mTempFocusList, direction);
731
+ // for(int i = 0; i < mTempFocusList.size(); i++){
732
+ // View v = mTempFocusList.get(i);
733
+ // Log.i(FocusDispatchView.TAG,"2-3 : addFocusables view :"+ExtendUtil.debugView(v));
734
+ // }
735
+ if(mTempFocusList.size() > 0){
736
+ found = ExtendUtil.executeFindNextFocus(this, focused, direction);
737
+ }
738
+ if (LogUtils.isDebug()) {
739
+ Log.d(FocusDispatchView.TAG, "2-3 : find from userSpecifiedTarget $found : " + ExtendUtil.debugViewLite(found));
740
+ }
741
+ }
742
+
743
+
744
+ //4 这里处理用户是否拦截了焦点
745
+ if (found == null) {
746
+ if (focused != null) {
747
+ // if(getParent() instanceof ViewGroup && getParent().id == userSpecifiedTargetId){
748
+ if (ExtendUtil.sameDescend(this, focused, userSpecifiedTargetName,userSpecifiedTargetSID)) {
749
+ // 这种情况下,用户将nextXXID 设置成本身,所以将focused返回
750
+ if (LogUtils.isDebug()) {
751
+ Log.d(FocusDispatchView.TAG, "2-4 : find from : sameDescend return focused "+ExtendUtil.debugViewLite(focused)+", userSpecifiedTargetName is "+userSpecifiedTargetName);
752
+ }
753
+ // if(userSpecifiedTargetName != null && userSpecifiedTargetName.equals(ExtendUtil.getViewName(focused))){
754
+ // //found = focused;
755
+ // //name设置成自身如果是name
756
+ // }
757
+ found = focused;
758
+ }
759
+ }
760
+ }
761
+
762
+ //5 这里只有一种情况,用户设置的焦点不太符合物理逻辑,所以不再考虑focused位置的情况下再次搜索
763
+ if (found == null) {
764
+ // Log.i(FocusDispatchView.TAG,"2-5 : mTempFocusList size :"+mTempFocusList.size());
765
+ // for(int i = 0; i < mTempFocusList.size(); i++){
766
+ // View v = mTempFocusList.get(i);
767
+ // Log.i(FocusDispatchView.TAG,"2-5 : addFocusables view :"+ExtendUtil.debugView(v));
768
+ // }
769
+ if(mTempFocusList == null || mTempFocusList.size() < 1 && (userSpecifiedTarget != null && !userSpecifiedTarget.isFocusable())){
770
+ Log.e(FocusDispatchView.TAG,"2-5 : mTempFocusList is null or size is 0 skip search next focus");
771
+ }else {
772
+ mTempFocusList.clear();
773
+ if (userSpecifiedTarget != null) {
774
+ userSpecifiedTarget.addFocusables(mTempFocusList, direction);
775
+ found = ExtendUtil.executeFindNextFocus(this, null, direction);
776
+ if (LogUtils.isDebug()) {
777
+ Log.d(FocusDispatchView.TAG, "2-5 : find without focused found is $found:" + ExtendUtil.debugViewLite(found));
778
+ }
779
+ }
780
+ }
781
+ }
782
+
783
+ } else {
784
+ if (LogUtils.isDebug()) {
785
+ Log.d(FocusDispatchView.TAG, "2 : ** userSpecifiedTarget is NULL find from Root");
786
+ }
787
+ //2 为空时用户没有设定,从root中寻找
788
+ if (!justSpecial) {
789
+ super.addFocusables(mTempFocusList, direction);
790
+ //3 find nextFocus from root
791
+ // 注意: 此方法会调用this.addFocusables()
792
+ found = ExtendUtil.executeFindNextFocus(this, focused, direction);
793
+ }
794
+ if (LogUtils.isDebug()) {
795
+ Log.d(FocusDispatchView.TAG, "3 : FocusFinder search from Root result is $found " + found + ",justSpecial" + justSpecial);
796
+ }
797
+ }
798
+ } finally {
799
+ mTempFocusList.clear();
800
+ }
801
+ consumeSpecifiedFocusSearchRequest();
802
+ if (LogUtils.isDebug()) {
803
+ Log.d(FocusDispatchView.TAG, "-----------------end : focusSearch searched : $found-----------------");
804
+ }
805
+ if (justSpecial) {
806
+ if (LogUtils.isDebug()) {
807
+ Log.e(FocusDispatchView.TAG, "-----------------end : justSpecial focusSearch return -----------------" + found);
808
+ }
809
+ return found;
810
+ }
811
+ if (found != null) {
812
+ // Log.d(TAG, "-----------------end : focusSearch found!=null shakeSelf:" + shakeSelf);
813
+ if ((found == focused || (userSpecifiedTargetName != null && userSpecifiedTarget == null)
814
+ || (userSpecifiedTargetSID != null && userSpecifiedTarget == null)) && shakeSelf) {//todo 有bug
815
+ if (LogUtils.isDebug()) {
816
+ Log.e(FocusDispatchView.TAG, "-----------------end found = focused: shakeSelf-----------------");
817
+ }
818
+ shakeSelf(focused, direction);
819
+ }
820
+ return found;
821
+ } else {
822
+ View view = super.focusSearch(focused, direction);
823
+ // Log.d(TAG, "-----------------end : focusSearch found==null shakeSelf:" + shakeSelf);
824
+ if (view == null && shakeSelf) {
825
+ if (LogUtils.isDebug()) {
826
+ Log.e(FocusDispatchView.TAG, "-----------------end found = null: shakeSelf-----------------");
827
+ }
828
+ shakeSelf(focused, direction);
829
+ }
830
+ return view;
831
+ }
832
+ // return found != null ? found : super.focusSearch(focused,direction);
833
+ }
834
+
835
+ private boolean animRunning = false;
836
+
837
+ private void shakeSelf(View view, int direction) {
838
+ if (direction == View.FOCUS_DOWN || direction == View.FOCUS_UP) {
839
+ if (!animRunning) {
840
+ animRunning = true;
841
+ ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_Y.getName(), 0, 5f);//抖动幅度0到5
842
+ objectAnimator.setDuration(250);//持续时间
843
+ objectAnimator.setInterpolator(new CycleInterpolator(2));//抖动次数
844
+ objectAnimator.addListener(new AnimatorListenerAdapter() {
845
+ @Override
846
+ public void onAnimationCancel(Animator animation) {
847
+ animRunning = false;
848
+ }
849
+
850
+ @Override
851
+ public void onAnimationEnd(Animator animation) {
852
+ animRunning = false;
853
+ }
854
+ });
855
+ objectAnimator.start();//开始动画
856
+ }
857
+ } else {
858
+ if (!animRunning) {
859
+ animRunning = true;
860
+ ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(view, View.TRANSLATION_X.getName(), 0, 5f);//抖动幅度0到5
861
+ objectAnimator.setDuration(250);//持续时间
862
+ objectAnimator.setInterpolator(new CycleInterpolator(2));//抖动次数
863
+ objectAnimator.addListener(new AnimatorListenerAdapter() {
864
+ @Override
865
+ public void onAnimationCancel(Animator animation) {
866
+ animRunning = false;
867
+ }
868
+
869
+ @Override
870
+ public void onAnimationEnd(Animator animation) {
871
+ animRunning = false;
872
+ }
873
+ });
874
+ objectAnimator.start();//开始动画
875
+ }
876
+ }
877
+ }
878
+
879
+
880
+ private String firstFocusTargetName = null;
881
+
882
+ public void setFirstFocusTargetName(String name) {
883
+ this.firstFocusTargetName = name;
884
+ }
885
+
886
+ public HippyMap focusSearchTarget;
887
+
888
+ public void setFocusSearchTarget(HippyMap map) {
889
+ this.focusSearchTarget = map;
890
+ }
891
+
892
+ public static String getDirectionName(int direction) {
893
+ return ExtendUtil.getDirectionName(direction);
894
+ }
895
+
896
+ public View findFocusTargetName(int direction) {
897
+ if (focusSearchTarget != null) {
898
+ final String key = getDirectionName(direction);
899
+ if (key != null) {
900
+ final String target = focusSearchTarget.getString(key);
901
+ return ControllerManager.findViewByName(this, target);
902
+ } else {
903
+ if (LogUtils.isDebug()) {
904
+ LogUtils.e(TAG, "div: +addFocusables findFocusTargetName key is null :" + focusSearchTarget);
905
+ }
906
+ }
907
+ }
908
+ return null;
909
+ }
910
+
911
+ public View findNextSpecialFocusView(View focused, int direction) {
912
+ return advanceFocusSearch(focused, direction, true);
913
+ }
914
+
915
+ @Override
916
+ public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
917
+ if(mFocusSearchHelper.addFocusables(views,direction)){
918
+ return;
919
+ }
920
+ if (!hasFocus() && focusSearchTarget != null) {
921
+ final View view = findFocusTargetName(direction);
922
+ if (view != null) {
923
+ if (LogUtils.isDebug()) {
924
+ LogUtils.d(TAG, "div: +addFocusables by focusSearchTarget : " + direction + ",view :" + view.getId() + ",focusSearchTarget:" + focusSearchTarget);
925
+ }
926
+ view.addFocusables(views, direction, focusableMode);
927
+ return;
928
+ } else {
929
+ if (LogUtils.isDebug()) {
930
+ LogUtils.d(TAG, "div: +addFocusables by focusSearchTarget : " + direction + ",view :" + null);
931
+ }
932
+ }
933
+ }
934
+
935
+ // Log.i(FocusDispatchView.TAG,"addFocusables hasFocus: "+hasFocus()+",this:"+ExtendUtil.debugView(this));
936
+ if(!hasFocus() && focusMemoryEnable && memoryFocused != null){
937
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
938
+ if(memoryFocused.getVisibility() == View.VISIBLE && memoryFocused.isAttachedToWindow()){
939
+ if (LogUtils.isDebug()) {
940
+ LogUtils.d(TAG, "div: +addFocusables on memoryFocused : " + direction + ",view :" + ExtendUtil.debugView(memoryFocused));
941
+ }
942
+ memoryFocused.addFocusables(views,direction,focusableMode);
943
+ return;
944
+ }
945
+ }
946
+ }
947
+
948
+ if (!hasFocus() && firstFocusTargetName != null) {
949
+ final View view = ControllerManager.findViewByName(this, firstFocusTargetName);
950
+ if (view != null) {
951
+ LogUtils.d(TAG, "div: +addFocusables by firstTargetName : " + firstFocusTargetName + ",view :" + view.getId());
952
+ view.addFocusables(views, direction, focusableMode);
953
+ return;
954
+ }
955
+ }
956
+ if (useAdvancedFocusSearch && mTempFocusList != null && mTempFocusList.size() > 0) {
957
+ if (LogUtils.isDebug()) Log.d(TAG, "+addFocusables views : $mTempFocusList");
958
+ if (views != null) views.addAll(mTempFocusList);
959
+ } else {
960
+ super.addFocusables(views, direction, focusableMode);
961
+ }
962
+
963
+ }
964
+
965
+ @Override
966
+ public void addFocusables(ArrayList<View> views, int direction) {
967
+ if (!hasFocus() && focusSearchTarget != null) {
968
+ final View view = findFocusTargetName(direction);
969
+ if (view != null) {
970
+ LogUtils.d(TAG, "div: +addFocusables by focusSearchTarget : " + direction + ",view :" + view.getId());
971
+ view.addFocusables(views, direction);
972
+ return;
973
+ } else {
974
+ LogUtils.d(TAG, "div: +addFocusables by focusSearchTarget : " + direction + ",view :" + null);
975
+ }
976
+ }
977
+
978
+ if (!hasFocus() && firstFocusTargetName != null) {
979
+ final View view = ControllerManager.findViewByName(this, firstFocusTargetName);
980
+ if (view != null) {
981
+ LogUtils.d(TAG, "div: +addFocusables by firstTargetName : " + firstFocusTargetName + ",view :" + view.getId());
982
+ view.addFocusables(views, direction);
983
+ return;
984
+ }
985
+ }
986
+ if (useAdvancedFocusSearch && mTempFocusList != null && mTempFocusList.size() > 0) {
987
+ if (LogUtils.isDebug()) Log.d(TAG, "+addFocusables views : $mTempFocusList");
988
+ if (views != null) views.addAll(mTempFocusList);
989
+ } else {
990
+ super.addFocusables(views, direction);
991
+ }
992
+ }
993
+
994
+ private void postFocusChange(final boolean gainFocus, final int direction, final Rect previouslyFocusedRect) {
995
+ // Log.d("zhaopeng","onFocusChange gainFocus:"+gainFocus+",view:"+this+"");
996
+
997
+ if (mPostFocusTask != null) {
998
+ removeCallbacks(mPostFocusTask);
999
+ }
1000
+
1001
+ if (isInReFocus()) {
1002
+ handleFocusScaleImmediately(gainFocus, direction, previouslyFocusedRect);
1003
+ } else {
1004
+ onHandleFocusScale(gainFocus, direction, previouslyFocusedRect);
1005
+ }
1006
+
1007
+ }
1008
+
1009
+
1010
+ @Override
1011
+ protected void onDetachedFromWindow() {
1012
+ // Log.v("zhaopeng","------onDetachedFromWindow focused:"+isFocused());
1013
+ super.onDetachedFromWindow();
1014
+ if (isFocusable()) {
1015
+ TVFocusScaleExcuter.changeFocusScaleDirectly(this, 1, 1);
1016
+ }
1017
+ if (isSelected()) {
1018
+ setSelected(false);
1019
+ }
1020
+ memoryFocused = null;
1021
+
1022
+ stopListenGlobalFocusChange();
1023
+
1024
+ }
1025
+
1026
+
1027
+
1028
+ @Override
1029
+ protected void onAttachedToWindow() {
1030
+ super.onAttachedToWindow();
1031
+ // Log.v("zhaopeng","+++++++onAttachedToWindow focused:"+isFocused());
1032
+
1033
+ listenGlobalFocusChangeIfNeed();
1034
+ }
1035
+
1036
+
1037
+ private Runnable mPostFocusTask;
1038
+
1039
+ @Override
1040
+ protected void onFocusChanged(final boolean gainFocus, int direction, Rect previouslyFocusedRect) {
1041
+ super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
1042
+ //border
1043
+ // if(isPostTaskEnabled()){
1044
+ // if(gainFocus) {
1045
+ // mPostHandlerView.postTask(TVListView.PostContentHolder.POST_TASK_CATEGORY_DIV_FOCUS_CHANGE, 1,
1046
+ // () -> postFocusChange(true, direction, previouslyFocusedRect), 300);
1047
+ // }else{
1048
+ // mPostHandlerView.clearTask(TVListView.PostContentHolder.POST_TASK_CATEGORY_DIV_FOCUS_CHANGE, 1);
1049
+ // postFocusChange(false, direction, previouslyFocusedRect);
1050
+ // }
1051
+ // }else{
1052
+ postFocusChange(gainFocus, direction, previouslyFocusedRect);
1053
+ // }
1054
+ }
1055
+
1056
+ /**
1057
+ * zhaopeng add
1058
+ */
1059
+ public void setOverFlowViewIndex(int overFlowViewIndex) {
1060
+ this.overFlowViewIndex = overFlowViewIndex;
1061
+ postInvalidateDelayed(16);
1062
+ }
1063
+
1064
+ private HippyMap scrollOverride;
1065
+ public void setScrollOverride(HippyMap map){
1066
+ //Log.i("ChildOnScreenScroller","setScrollOverride map:"+map+",this:"+this);
1067
+ this.scrollOverride = map;
1068
+ }
1069
+
1070
+ public HippyMap getScrollOverride() {
1071
+ return scrollOverride;
1072
+ }
1073
+
1074
+ public void setGradientDrawable(HippyMap map) {
1075
+
1076
+ if (map == null) {
1077
+ mBackDrawable = null;
1078
+ } else {
1079
+ this.mBackDrawable = createGradientDrawable(this, map);
1080
+
1081
+ }
1082
+
1083
+ invalidate();
1084
+ }
1085
+
1086
+
1087
+ public static GradientDrawable createGradientDrawable(View view, HippyMap map) {
1088
+ int type = GradientDrawable.LINEAR_GRADIENT;
1089
+ if (map.containsKey("type")) {
1090
+ type = map.getInt("type");
1091
+ }
1092
+ int shape = GradientDrawable.RECTANGLE;
1093
+ if (map.containsKey("shape")) {
1094
+ shape = map.getInt("shape");
1095
+ }
1096
+ GradientDrawable.Orientation orientation = GradientDrawable.Orientation.TOP_BOTTOM;
1097
+
1098
+ if (map.containsKey("orientation")) {
1099
+ int orientationValue = map.getInt("orientation");
1100
+ switch (orientationValue) {
1101
+ case 1:
1102
+ orientation = GradientDrawable.Orientation.TR_BL;
1103
+ break;
1104
+ case 2:
1105
+ orientation = GradientDrawable.Orientation.RIGHT_LEFT;
1106
+ break;
1107
+ case 3:
1108
+ orientation = GradientDrawable.Orientation.BR_TL;
1109
+ break;
1110
+ case 4:
1111
+ orientation = GradientDrawable.Orientation.BOTTOM_TOP;
1112
+ break;
1113
+ case 5:
1114
+ orientation = GradientDrawable.Orientation.BL_TR;
1115
+ break;
1116
+ case 6:
1117
+ orientation = GradientDrawable.Orientation.LEFT_RIGHT;
1118
+ break;
1119
+ case 7:
1120
+ orientation = GradientDrawable.Orientation.TL_BR;
1121
+ break;
1122
+ }
1123
+ }
1124
+
1125
+ HippyArray colorArray = map.getArray("colors");
1126
+ if (colorArray == null) {
1127
+ return null;
1128
+ }
1129
+ int[] colors = new int[colorArray.size()];
1130
+
1131
+ try {
1132
+ for (int i = 0; i < colors.length; i++) {
1133
+ final String colorStr = colorArray.getString(i);
1134
+ colors[i] = Color.parseColor(colorStr);
1135
+ if (LogUtils.isDebug()) {
1136
+ // Log.d(TAG, "createGradientDrawable colorStr :" + colorStr + ",this:" + view.getId());
1137
+ }
1138
+ }
1139
+ } catch (Exception e) {
1140
+ if(LogUtils.isDebug()) {
1141
+ Log.e("hippy", "color parse fail createGradientDrawable return !");
1142
+ }
1143
+ return null;
1144
+ }
1145
+
1146
+ final GradientDrawable g = new GradientDrawable(orientation, colors);
1147
+ g.setShape(shape);
1148
+ g.setGradientType(type);
1149
+ if (map.containsKey("gradientRadius")) {
1150
+ g.setGradientRadius(PixelUtil.dp2px(map.getInt("gradientRadius")));
1151
+ }
1152
+ if (map.containsKey("cornerRadius")) {
1153
+ g.setCornerRadius(PixelUtil.dp2px((float) map.getDouble("cornerRadius")));
1154
+ }
1155
+ if (map.containsKey("cornerRadii4")) {
1156
+ HippyArray array = map.getArray("cornerRadii4");
1157
+ if (array.size() != 4) {
1158
+ throw new IllegalArgumentException("cornerRadii4 size need 8");
1159
+ }
1160
+ g.setCornerRadii(new float[]{
1161
+ PixelUtil.dp2px((float) array.getDouble(0)), PixelUtil.dp2px((float) array.getDouble(0)),
1162
+ PixelUtil.dp2px((float) array.getDouble(1)), PixelUtil.dp2px((float) array.getDouble(1)),
1163
+ PixelUtil.dp2px((float) array.getDouble(2)), PixelUtil.dp2px((float) array.getDouble(2)),
1164
+ PixelUtil.dp2px((float) array.getDouble(3)), PixelUtil.dp2px((float) array.getDouble(3)),
1165
+ });
1166
+ }
1167
+ if (map.containsKey("cornerRadii8")) {
1168
+ HippyArray array = map.getArray("cornerRadii8");
1169
+ if (array.size() != 8) {
1170
+ throw new IllegalArgumentException("cornerRadii8 size need 8");
1171
+ }
1172
+ float[] radii = new float[array.size()];
1173
+ for (int i = 0; i < radii.length; i++) {
1174
+ radii[i] = PixelUtil.dp2px((float) (array.getDouble(i)));
1175
+ }
1176
+ g.setCornerRadii(radii);
1177
+ }
1178
+ return g;
1179
+ }
1180
+
1181
+ @Override
1182
+ public boolean drawChild(Canvas canvas, View child, long drawingTime) {
1183
+ if (mBringToFrontOnFocus && child == getFocusedChild()) {
1184
+ return true;
1185
+ }
1186
+ if (overFlowViewIndex > -1 && overFlowViewIndex < getChildCount()) {
1187
+ final View v = getChildAt(overFlowViewIndex);
1188
+ if (child == v) {
1189
+ return true;
1190
+ }
1191
+ }
1192
+ return super.drawChild(canvas, child, drawingTime);
1193
+ }
1194
+
1195
+ //zhaopeng add
1196
+ private boolean mEnableChildFocusEvent = false;
1197
+ private HippyViewEvent mChildFocusEvent;
1198
+
1199
+ @Override
1200
+ public void setDispatchChildFocusEvent(boolean enable) {
1201
+ //
1202
+ this.mEnableChildFocusEvent = enable;
1203
+ }
1204
+
1205
+ // ChildOnScreenScroller childOnScreenScroller;
1206
+ int[] tempOut = new int[2];
1207
+
1208
+
1209
+
1210
+ @Override
1211
+ public boolean requestChildRectangleOnScreen(View child, Rect rectangle, boolean immediate) {
1212
+ //return super.requestChildRectangleOnScreen(child, rectangle, immediate);
1213
+ //int scroll = ChildOnScreenScroller.getScrollToPositionOffset(-1,this,child, RecyclerView.VERTICAL,getChildCount(), TVRecyclerView.REQUEST_CHILD_ON_SCREEN_TYPE_ANDROID,0);
1214
+ if(enableOverScrollY || enableOverScrollX){
1215
+ getChildRectangleOnScreenScrollAmount(this,child,rectangle,immediate,tempOut);
1216
+ int sy = enableOverScrollY ? tempOut[1] : 0;
1217
+ int sx = enableOverScrollX ? tempOut[0] : 0;
1218
+ Log.i(TAG,"requestChildRectangleOnScreen child:"+ExtendUtil.debugViewLite(child)+",sy:"+sy+",sx:"+sx+",immediate:"+immediate);
1219
+ if(sy != 0 || sx != 0){
1220
+ if(!immediate) {
1221
+ smoothScrollBy(sx, sy);
1222
+ }else{
1223
+ scrollBy(sx,sy);
1224
+ }
1225
+ return true;
1226
+ }else{
1227
+ return false;
1228
+ }
1229
+ }
1230
+ return super.requestChildRectangleOnScreen(child, rectangle, immediate);
1231
+ }
1232
+
1233
+ static int[] getChildRectangleOnScreenScrollAmount(View parent, View child, Rect rect, boolean immediate,int[] out) {
1234
+ // int[] out = new int[2];
1235
+ int parentLeft = parent.getPaddingLeft();
1236
+ int parentTop = parent.getPaddingTop();
1237
+ int parentRight = parent.getWidth() - parent.getPaddingRight();
1238
+ int parentBottom = parent.getHeight() - parent.getPaddingBottom();
1239
+ int childLeft = child.getLeft() + rect.left - child.getScrollX();
1240
+ int childTop = child.getTop() + rect.top - child.getScrollY();
1241
+ int childRight = childLeft + rect.width();
1242
+ int childBottom = childTop + rect.height();
1243
+ int offScreenLeft = Math.min(0, childLeft - parentLeft - parent.getScrollX());
1244
+ int offScreenTop = Math.min(0, childTop - parentTop - parent.getScrollY());
1245
+ int offScreenRight = Math.max(0, childRight - parentRight - parent.getScrollX());
1246
+ int offScreenBottom = Math.max(0, childBottom - parentBottom - parent.getScrollY());
1247
+ int dx;
1248
+ // if (this.getLayoutDirection() == 1) {
1249
+ // dx = offScreenRight != 0 ? offScreenRight : Math.max(offScreenLeft, childRight - parentRight);
1250
+ // } else {
1251
+ dx = offScreenLeft != 0 ? offScreenLeft : Math.min(childLeft - parentLeft, offScreenRight);
1252
+ // }
1253
+
1254
+ int dy = offScreenTop != 0 ? offScreenTop : Math.min(childTop - parentTop, offScreenBottom);
1255
+
1256
+ Log.d(HippyViewGroup.TAG,"childTop:"+child.getTop()+",rect:"+rect.top+",childScrollY:"+child.getScrollY()+",parentScrollY:"+parent.getScrollY());
1257
+ Log.d(HippyViewGroup.TAG,"getChildRectangleOnScreenScrollAmount dx : "+dx+",dy : "+dy+",offScreenLeft : "+offScreenLeft+",offScreenTop : "+offScreenTop+",offScreenRight : "+offScreenRight+",offScreenBottom : "+offScreenBottom+",childLeft : "+childLeft+",childTop : "+childTop+",childRight : "+childRight+",childBottom : "+childBottom+",parentLeft : "+parentLeft+",parentTop : "+parentTop+",parentRight : "+parentRight+",parentBottom : "+parentBottom);
1258
+ out[0] = dx;
1259
+ out[1] = dy;
1260
+ return out;
1261
+ }
1262
+
1263
+ @Override
1264
+ public void clearFocus() {
1265
+ super.clearFocus();
1266
+ if(LogUtils.isDebug()){
1267
+ Log.i(FocusDispatchView.TAG,"clearFocus this:"+ExtendUtil.debugViewLite(this));
1268
+ }
1269
+ }
1270
+
1271
+ @Override
1272
+ public void requestChildFocus(View child, View focused) {
1273
+ super.requestChildFocus(child, focused);
1274
+ if (mEnableChildFocusEvent) {
1275
+ if (mChildFocusEvent == null) {
1276
+ mChildFocusEvent = new HippyViewEvent(InternalExtendViewUtil.CHILD_FOCUS_EVENT_NAME);
1277
+ }
1278
+ InternalExtendViewUtil.sendEventOnRequestChildFocus(this, child, focused, mChildFocusEvent);
1279
+ }
1280
+ if(getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS) {
1281
+ LogAdapterUtils.log(getContext(), FocusDispatchView.TAG, "focus-> fail on BLOCK => " + ExtendUtil.debugViewLite(focused));
1282
+ }else{
1283
+ LogAdapterUtils.log(getContext(), FocusDispatchView.TAG, "focus-> " + ExtendUtil.debugViewLite(focused));
1284
+ }
1285
+ if (ExtendViewGroup.ROOT_TAG.equals(getTag(R.id.page_root_view))) {
1286
+ if(getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS){
1287
+ if(LogUtils.isDebug()) {
1288
+ Log.e(FocusDispatchView.TAG, "GLOBAL_FOCUS TO VIEW fail on root view FOCUS_BLOCK_DESCENDANTS:" + ExtendUtil.debugView(focused));
1289
+ }
1290
+ if (focused != null) {
1291
+ //fixme 20250729 这里当root被block后,会导致焦点请求失败,但是isFocused状态被记录,导致后续再也请求不了,所以这里clear一下
1292
+ focused.clearFocus();
1293
+ }
1294
+ return;
1295
+ }else{
1296
+ if(LogUtils.isDebug()) {
1297
+ Log.i(FocusDispatchView.TAG, "GLOBAL_FOCUS TO VIEW:" + ExtendUtil.debugView(focused));
1298
+ }
1299
+ }
1300
+ }
1301
+ // ExtendUtil.logView(FocusDispatchView.TAG,focused);
1302
+ if (focusMemoryEnable) {
1303
+ memoryFocused = focused;
1304
+ }
1305
+ if(isPageRoot() && mAutoFocusManager != null){
1306
+ mAutoFocusManager.onRequestChildFocus(child, focused);
1307
+ }
1308
+ //Log.d("DebugDivSelect", "requestChildFocus enableSelectOnFocus:"+enableSelectOnFocus+",requestChildFocus this :"+ExtendUtil.debugViewLite(this));
1309
+ if (enableSelectOnFocus) {
1310
+ changeSelectState(defaultSectionPosition, false);
1311
+ defaultSectionPosition = searchChildIndex(child);
1312
+ //Log.d("DebugDivSelect","searchChildIndex:"+child+",defaultSectionPosition:"+defaultSectionPosition);
1313
+ changeSelectState(defaultSectionPosition, true);
1314
+ }
1315
+ // getchild
1316
+
1317
+ postInvalidateDelayed(16);
1318
+ if(enableOverScrollY) {
1319
+ // Log.i(TAG, "enableOverScrollY : " + true + ",this:" + ExtendUtil.debugViewLite(this));
1320
+ }
1321
+ if(enableOverScrollX || enableOverScrollY) {
1322
+ View rectView = focused == null ? child : focused;
1323
+ this.mTempRect.set(0, 0, rectView.getWidth(), rectView.getHeight());
1324
+ requestChildRectangleOnScreen(rectView, this.mTempRect, true);
1325
+ }
1326
+ }
1327
+
1328
+ public int searchChildIndex(View child){
1329
+ if (child.getParent() != this) {
1330
+ return -1;
1331
+ }
1332
+ for(int i = 0; i < getChildCount();i ++){
1333
+ if(getChildAt(i)== child){
1334
+ return i;
1335
+ }
1336
+ }
1337
+ return -1;
1338
+ }
1339
+
1340
+ private Rect mTempRect = new Rect();
1341
+
1342
+
1343
+ @Override
1344
+ public View getHostView() {
1345
+ return this;
1346
+ }
1347
+
1348
+ @Override
1349
+ public void setVisibility(int visibility) {
1350
+ super.setVisibility(visibility);
1351
+ }
1352
+
1353
+
1354
+ private void stopListenGlobalFocusChange() {
1355
+ if (mOnGlobalFocusChangeListener != null) {
1356
+ getViewTreeObserver().removeOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
1357
+ mOnGlobalFocusChangeListener = null;
1358
+ }
1359
+ }
1360
+
1361
+ public void setListenGlobalFocusChange(boolean listenGlobalFocusChange) {
1362
+ isListenGlobalFocusChange = listenGlobalFocusChange;
1363
+ }
1364
+
1365
+ private void listenGlobalFocusChangeIfNeed() {
1366
+ stopListenGlobalFocusChange();
1367
+ if (isListenGlobalFocusChange) {
1368
+ mOnGlobalFocusChangeListener = new ViewTreeObserver.OnGlobalFocusChangeListener() {
1369
+ @Override
1370
+ public void onGlobalFocusChanged(View oldFocus, View newFocus) {
1371
+ if (LogUtils.isDebug()) {
1372
+ Log.d(TAG, "onGlobalFocusChanged hasFocus : " + hasFocus() + " this :" + this);
1373
+ }
1374
+ if (hasFocus()) {
1375
+ if (oldFocus == null) {
1376
+ //首次获得焦点
1377
+ notifyViewFocusChanged(true, false, null, newFocus, false);
1378
+ } else {
1379
+ //焦点在内部,但上一个view不属于内部
1380
+ final boolean isOldFocusDescendantOf = TVViewUtil.isViewDescendantOf(oldFocus, HippyViewGroup.this);
1381
+ if (!isOldFocusDescendantOf) {
1382
+ notifyViewFocusChanged(true, false, oldFocus, newFocus, false);
1383
+ }
1384
+ }
1385
+ } else {
1386
+ final boolean isNewFocusDescendantOf = TVViewUtil.isViewDescendantOf(newFocus, HippyViewGroup.this);
1387
+ if (LogUtils.isDebug()) {
1388
+ Log.d(TAG, "onGlobalFocusChanged hasFocus : " + hasFocus() + " isNewFocusDescendantOf : " + isNewFocusDescendantOf);
1389
+ }
1390
+ if (!isNewFocusDescendantOf) {
1391
+ //焦点丢失
1392
+ final boolean isOldFocusDescendantOf = TVViewUtil.isViewDescendantOf(oldFocus, HippyViewGroup.this);
1393
+
1394
+ if (isOldFocusDescendantOf) {
1395
+ notifyViewFocusChanged(false, true, oldFocus, newFocus, true);
1396
+ }
1397
+ }
1398
+ }
1399
+ }
1400
+ };
1401
+ getViewTreeObserver().addOnGlobalFocusChangeListener(mOnGlobalFocusChangeListener);
1402
+ }
1403
+ }
1404
+
1405
+ private boolean isListenGlobalFocusChange = false;
1406
+ private ViewTreeObserver.OnGlobalFocusChangeListener mOnGlobalFocusChangeListener;
1407
+
1408
+ boolean lastFocusState = false;
1409
+
1410
+ private void notifyViewFocusChanged(boolean hasFocus, boolean isOldFocusDescendantOf, View oldFocus, View focused, boolean loseFocus) {
1411
+ //
1412
+ Log.d(TAG, "notifyViewGroupFocusChanged lastFocusState != hasFocus:" + (lastFocusState != hasFocus) + ",loseFocus:" + loseFocus + ",isOldFocusDescendantOf:" + isOldFocusDescendantOf);
1413
+
1414
+ if (lastFocusState != hasFocus) {
1415
+ onViewFocusChanged(hasFocus, focused);
1416
+ lastFocusState = hasFocus;
1417
+ }
1418
+
1419
+
1420
+ }
1421
+
1422
+
1423
+
1424
+
1425
+ protected void onViewFocusChanged(boolean hasFocus, View focused) {
1426
+ //
1427
+ if (LogUtils.isDebug()) {
1428
+ Log.d(TAG, "onViewGroupFocusChanged hasFocus : " + hasFocus + " this :" + this);
1429
+ }
1430
+ LogUtils.d(TAG, "onViewGroupFocusChanged context:" + getHippyContext());
1431
+ if (getHippyContext() != null) {
1432
+ if (hasFocus) {
1433
+ TriggerTaskManagerModule.dispatchTriggerTask(this, "onFocusAcquired");
1434
+ } else {
1435
+ TriggerTaskManagerModule.dispatchTriggerTask(this, "onFocusLost");
1436
+ }
1437
+ }
1438
+ }
1439
+
1440
+
1441
+ private int triggerKeyEventCode = -1;
1442
+
1443
+ public void setTriggerKeyEvent(int keyCode) {
1444
+ this.triggerKeyEventCode = keyCode;
1445
+ }
1446
+
1447
+
1448
+ private void sendInterceptKeyJSEvent(KeyEvent event){
1449
+ if(interceptKeyJSEvent == null){
1450
+ interceptKeyJSEvent = new HippyViewEvent("onInterceptKeyEvent");
1451
+ }
1452
+ HippyMap map = new HippyMap();
1453
+ map.pushInt("keyCode",event.getKeyCode());
1454
+ map.pushInt("action",event.getAction());
1455
+ interceptKeyJSEvent.send(this,map);
1456
+ }
1457
+
1458
+ @Override
1459
+ public boolean dispatchKeyEvent(KeyEvent event) {
1460
+ if(interceptKeyEvent){
1461
+ Log.e(TAG,"dispatchKeyEventPreIme return on interceptKeyEvent this:"+this);
1462
+ sendInterceptKeyJSEvent(event);
1463
+ return true;
1464
+ }
1465
+ if(interceptKeyEvents != null){
1466
+ for(int i = 0; i < interceptKeyEvents.size(); i ++){
1467
+ int key = interceptKeyEvents.getInt(i);
1468
+ if(event.getKeyCode() == key){
1469
+ sendInterceptKeyJSEvent(event);
1470
+ Log.e(TAG,"dispatchKeyEventPreIme return on interceptKeyEvent keyCode:"+key+",this:"+this);
1471
+ return true;
1472
+ }
1473
+ }
1474
+ }
1475
+ if (triggerKeyEventCode == event.getKeyCode()) {
1476
+ if (TriggerTaskManagerModule.dispatchTriggerTask(this, "onDispatchKeyEvent")) {
1477
+ return true;
1478
+ }
1479
+ }
1480
+ return super.dispatchKeyEvent(event);
1481
+ }
1482
+
1483
+ private Rect clipOutset;
1484
+
1485
+ public void setClipOutset(int left, int top, int right, int bottom) {
1486
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
1487
+ if (clipOutset == null) {
1488
+ clipOutset = new Rect();
1489
+ }
1490
+ clipOutset.set(left, top, right, bottom);
1491
+ requestLayout();
1492
+ setClipChildren(false);
1493
+ }
1494
+ }
1495
+
1496
+
1497
+
1498
+
1499
+ Rect temp;
1500
+
1501
+ @Override
1502
+ protected void onLayout(boolean changed, int l, int t, int r, int b) {
1503
+ if (LogUtils.isDebug()) {
1504
+ Log.d(CustomLayoutView.TAG, "onLayout id: " + getId() + ",width:" + getWidth() + ",height:" + getHeight() + ",this:" + this + ",l:" + l + ",t:" + t);
1505
+ }
1506
+ super.onLayout(changed, l, t, r, b);
1507
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
1508
+ if (clipOutset != null) {
1509
+ if (temp == null) {
1510
+ temp = new Rect();
1511
+ }
1512
+ temp.set(-clipOutset.left, -clipOutset.top, getWidth() + clipOutset.right, getHeight() + clipOutset.bottom);
1513
+
1514
+ setClipBounds(temp);
1515
+ }
1516
+ }
1517
+ if(isPageRoot()){
1518
+ //fixme 临时适配非16:9适配
1519
+ final int tx = EngineRootView.getScreenTranslateX();
1520
+ final int ty = EngineRootView.getScreenTranslateY();
1521
+ if(tx != 0 || ty != 0) {
1522
+ for (int i = 0; i < getChildCount(); i++) {
1523
+ final View v = getChildAt(i);
1524
+ v.layout(l + tx, t + ty, r + tx, b + ty);
1525
+ }
1526
+ }
1527
+ }
1528
+ else if(changed){
1529
+ //Log.i(CustomLayoutView.TAG,"onLayout changed this:"+this);
1530
+ for(int i = 0; i < getChildCount(); i ++){
1531
+ final View v = getChildAt(i);
1532
+ if(v instanceof HippyViewGroup){
1533
+ final HippyViewGroup cv = (HippyViewGroup) v;
1534
+ if(cv.isFillParentEnabled){
1535
+ Log.e(CustomLayoutView.TAG,"onLayout changed child isFillParentEnabled true:"+cv);
1536
+ cv.layout(l,t,r,b);
1537
+ }
1538
+ }
1539
+ }
1540
+ }
1541
+ }
1542
+
1543
+
1544
+
1545
+
1546
+ @Override
1547
+ protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
1548
+ // if (LogUtils.isDebug()) {
1549
+ // Log.d(CustomLayoutView.TAG, "requestLayout id: " + getId() + ",MeasureWidth:" + getMeasuredWidth() + ",MeasureHeight:" + getMeasuredHeight() + ",this:" + this);
1550
+ // }
1551
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec);
1552
+ }
1553
+
1554
+ @Override
1555
+ public void requestLayout() {
1556
+ // if(needLayoutFromCustom && getParent() instanceof CustomLayoutView){
1557
+ // ((CustomLayoutView) getParent()).setLayoutRequestFromCustom(true);
1558
+ // }
1559
+ // if (LogUtils.isDebug() && getId() != -1) {
1560
+ // Log.d(CustomLayoutView.TAG, "requestLayout id: " + getId() + ",this:" + this);
1561
+ // }
1562
+ // requestLayoutCustom();
1563
+ super.requestLayout();
1564
+ // if(needLayoutFromCustom) {
1565
+ // RenderUtil.addUpdateLayout(this);
1566
+ // }
1567
+ }
1568
+
1569
+
1570
+ protected void onLayoutCustom() {
1571
+
1572
+ }
1573
+
1574
+ public void requestLayoutCustom() {
1575
+ needLayoutFromCustom = true;
1576
+ }
1577
+
1578
+
1579
+ private boolean needLayoutFromCustom = false;
1580
+
1581
+
1582
+ @Override
1583
+ public boolean isLayoutRequested() {
1584
+ boolean b = super.isLayoutRequested();
1585
+ // if (LogUtils.isDebug() && getId() != -1) {
1586
+ // Log.v(CustomLayoutView.TAG, "isLayoutRequested id: " + getId() + ",super return:" + b + ",isLayoutRequestFromCustom:" + needLayoutFromCustom);
1587
+ // }
1588
+ if (isLayoutRequestFromCustom()) {
1589
+ return false;
1590
+ }
1591
+ return b;
1592
+ }
1593
+
1594
+ @Override
1595
+ public void setLayoutRequestFromCustom(boolean b) {
1596
+ needLayoutFromCustom = b;
1597
+ }
1598
+
1599
+ @Override
1600
+ public boolean isLayoutRequestFromCustom() {
1601
+ return needLayoutFromCustom;
1602
+ }
1603
+
1604
+ @Override
1605
+ protected void drawableStateChanged() {
1606
+ super.drawableStateChanged();
1607
+ }
1608
+
1609
+
1610
+ /**
1611
+ * zhaopeng add
1612
+ */
1613
+
1614
+ public void setFocusScrollTarget(boolean enable) {
1615
+ this.isFocusScrollTarget = enable;
1616
+ }
1617
+
1618
+ public boolean isFocusScrollTarget() {
1619
+ return isFocusScrollTarget;
1620
+ }
1621
+
1622
+ private boolean isPageHidden = false;
1623
+
1624
+
1625
+ private boolean isFillParentEnabled = false;
1626
+
1627
+ public void setFillParentEnabled(boolean fillParentEnabled) {
1628
+ isFillParentEnabled = fillParentEnabled;
1629
+ }
1630
+
1631
+ protected void onPageHiddenChanged(boolean hidden) {
1632
+ this.isPageHidden = hidden;
1633
+ if (hidden) {
1634
+ stopListenGlobalFocusChange();
1635
+ } else {
1636
+ listenGlobalFocusChangeIfNeed();
1637
+ }
1638
+ }
1639
+
1640
+ @Override
1641
+ public boolean isPageHidden() {
1642
+ return isPageHidden;
1643
+ }
1644
+
1645
+ @Override
1646
+ public void changePageHidden(boolean hidden) {
1647
+ Log.i(TAG,"changePageHidden hidden:"+hidden+",this:"+ExtendUtil.debugViewLite(this));
1648
+ onPageHiddenChanged(hidden);
1649
+ for (int i = 0; i < getChildCount(); i++) {
1650
+ final View v = getChildAt(i);
1651
+ if (v instanceof ExtendViewGroup) {
1652
+ ((ExtendViewGroup) v).changePageHidden(hidden);
1653
+ }
1654
+ }
1655
+ }
1656
+
1657
+ @Override
1658
+ public void setId(int id) {
1659
+ super.setId(id);
1660
+ if( ExtendViewGroup.ROOT_TAG.equals(getTag(R.id.page_root_view))) {
1661
+ //在Context注册
1662
+ if(getContext() instanceof HippyInstanceContext){
1663
+ ((HippyInstanceContext) getContext()).registerPageRoot(id);
1664
+ }
1665
+ if(LogUtils.isDebug()) {
1666
+ Log.i(TAG, "setId :" + this + ",context:" + getContext());
1667
+ Log.e(AutoFocusManager.TAG, "rootView setId :" + this + ",context:" + getContext());
1668
+ }
1669
+ }
1670
+ }
1671
+
1672
+ protected void setAsRootView() {
1673
+ if(LogUtils.isDebug()) {
1674
+ Log.i(TAG, "setAsRootView :" + this + ",context:" + getContext());
1675
+ }
1676
+ setTag(R.id.page_root_view, ExtendViewGroup.ROOT_TAG);
1677
+ // setEnableMouse(true);
1678
+ }
1679
+
1680
+
1681
+ /**
1682
+ * 从View的Context(必须是HippyInstanceContext)中寻找RootView
1683
+ * @param context
1684
+ * @return
1685
+ */
1686
+ public static View findPageRootViewFromContext(Context context){
1687
+ return ExtendUtil.findPageRootViewFromContext(context);
1688
+ }
1689
+
1690
+ @SuppressLint("ResourceType")
1691
+ @Deprecated
1692
+ public static View findPageRootView(View v) {
1693
+ return ExtendUtil.findPageRootView(v);
1694
+ }
1695
+
1696
+ @Deprecated()
1697
+ public static View findRootViewFromParent(View v){
1698
+ return ExtendUtil.searchRootViewTraverse(v);
1699
+ }
1700
+
1701
+ @Override
1702
+ public void getState(@NonNull HippyMap map) {
1703
+ super.getState(map);
1704
+
1705
+ int focusIndex = -1;
1706
+ if (getFocusedChild() != null && getChildCount() > 0) {
1707
+ focusIndex = indexOfChild(getFocusedChild());
1708
+ }
1709
+ map.pushInt("focusChildIndex", focusIndex);
1710
+ map.pushInt("childCount", getChildCount());
1711
+ }
1712
+
1713
+ /**
1714
+ * zhaopeng add
1715
+ */
1716
+
1717
+ public void setShakeSelf(boolean shakeSelf) {
1718
+ this.shakeSelf = shakeSelf;
1719
+ }
1720
+
1721
+ //自动获取焦点的逻辑
1722
+ private AutoFocusManager mAutoFocusManager;
1723
+ public AutoFocusManager getAutoFocusManager(){
1724
+ if (mAutoFocusManager == null) {
1725
+ mAutoFocusManager = new AutoFocusManager(this);
1726
+ }
1727
+ return mAutoFocusManager;
1728
+ }
1729
+
1730
+ boolean isPageRoot(){
1731
+ return ExtendViewGroup.ROOT_TAG.equals(getTag(R.id.page_root_view));
1732
+ }
1733
+
1734
+ @Override
1735
+ public void onRequestAutofocus(View child, View target,int type) {
1736
+ if(LogUtils.isDebug()) {
1737
+ Log.d(AutoFocusManager.TAG, "--onRequestAutofocus child:" + child + ",target:" + ExtendUtil.debugView(target)+",blockFocus is :"+(getDescendantFocusability() == FOCUS_BLOCK_DESCENDANTS));
1738
+ }
1739
+ if(this.getVisibility() != View.VISIBLE){
1740
+ Log.e(AutoFocusManager.TAG,"onRequestAutofocus return on parent visibility != View.VISIBLE,"+ExtendUtil.debugView(this)+",target:"+ExtendUtil.debugView(target));
1741
+ return;
1742
+ }
1743
+ // if(getWidth() < 1 || getHeight() < 1){
1744
+ // Log.e(AutoFocusManager.TAG,"onRequestAutofocus return on parent size invalid "+ExtendUtil.debugView(this)+",target:"+ExtendUtil.debugView(target));
1745
+ // return;
1746
+ // }
1747
+
1748
+
1749
+
1750
+ if(isPageRoot()){
1751
+ if(LogUtils.isDebug()) {
1752
+ Log.e(AutoFocusManager.TAG, "onRequestAutofocus requestFocus on PageRoot");
1753
+ }
1754
+ //AutoFocusManager.globalRequestFocus(target);
1755
+ final AutoFocusManager af = AutoFocusManager.findAutoFocusManagerFromRoot(this);
1756
+ if (af != null) {
1757
+ af.requestGlobalRequestFocus(this,target,type);
1758
+ }else{
1759
+ Log.e(AutoFocusManager.TAG, "onRequestAutofocus requestFocus on PageRoot af is null");
1760
+ }
1761
+ }else {
1762
+ if (getParent() instanceof ExtendViewGroup) {
1763
+ ExtendViewGroup parent = (ExtendViewGroup) getParent();
1764
+ parent.onRequestAutofocus(this, target,type);
1765
+ } else {
1766
+ if(LogUtils.isDebug()) {
1767
+ Log.i(AutoFocusManager.TAG, "onRequestAutofocus parent is not a instance of ExtendViewGroup parent: " + getParent());
1768
+ }
1769
+ final AutoFocusManager af = AutoFocusManager.findAutoFocusManagerFromRoot(this);
1770
+ if (af != null) {
1771
+ af.requestGlobalRequestFocus(this,target,type);
1772
+ }else{
1773
+ Log.e(AutoFocusManager.TAG, "onRequestAutofocus requestFocus on PageRoot af is null");
1774
+ }
1775
+ }
1776
+ }
1777
+ }
1778
+
1779
+ public void enableFocusMemory(boolean enable) {
1780
+ // Log.i(TAG,"enableFocusMemory enable:"+enable+",this:"+ExtendUtil.debugView(this));
1781
+ this.focusMemoryEnable = enable;
1782
+ if (!enable) {
1783
+ memoryFocused = null;
1784
+ }
1785
+ }
1786
+
1787
+ public void notifyDialogDivVisibleChange(HippyViewGroup dialogDiv,boolean isShow){
1788
+
1789
+ }
1790
+
1791
+ public void beforeDialogDivVisibleChange(HippyViewGroup dialogDiv,boolean isShow){
1792
+
1793
+ }
1794
+
1795
+
1796
+ public void clearMemoryFocused(){
1797
+ memoryFocused = null;
1798
+ }
1799
+
1800
+ public FocusSearchHelper getFirstFocusHelper() {
1801
+ return mFocusSearchHelper;
1802
+ }
1803
+
1804
+
1805
+ @Override
1806
+ public void setDescendantFocusability(int focusability) {
1807
+ final int last = getDescendantFocusability();
1808
+ super.setDescendantFocusability(focusability);
1809
+ if(LogUtils.isDebug()) {
1810
+ if(focusability == FOCUS_BLOCK_DESCENDANTS) {
1811
+ Log.e(FocusDispatchView.TAG, "block Focus , this:" + ExtendUtil.debugViewLite(this));
1812
+ }else if(last == FOCUS_BLOCK_DESCENDANTS){
1813
+ Log.i(FocusDispatchView.TAG, "release block , this:" + ExtendUtil.debugViewLite(this));
1814
+ }
1815
+ }
1816
+ }
1817
+
1818
+ @Override
1819
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
1820
+ boolean b = false;
1821
+ View view = getFirstFocusHelper().findFirstFocusChildByDirection(direction);
1822
+ if (view != null) {
1823
+ b = view.requestFocus();
1824
+ if(LogUtils.isDebug()) {
1825
+ Log.i(FocusDispatchView.TAG, "!!!!!! div requestFocus by firstFocusHelper view " + ExtendUtil.debugViewLite(view) + ",this:" + ExtendUtil.debugViewLite(this));
1826
+ }
1827
+ }
1828
+ if(!b) {
1829
+ b = super.requestFocus(direction, previouslyFocusedRect);
1830
+ if(!b && LogUtils.isDebug()){
1831
+ final ViewParent blockedView = FocusUtils.findFocusBlockedParent(getParent());
1832
+ if(LogUtils.isDebug()) {
1833
+ Log.w(FocusDispatchView.TAG, "!!!!!! div requestFocus return " + false + ",this:" + ExtendUtil.debugViewLite(this));
1834
+ if (blockedView instanceof View) {
1835
+ Log.e(FocusDispatchView.TAG, "!!!!!! div requestFocus return by blockedView " + ExtendUtil.debugViewLite((View) blockedView));
1836
+ }
1837
+ }
1838
+ }
1839
+ }
1840
+ return b;
1841
+ }
1842
+
1843
+ @Override
1844
+ public boolean onHoverEvent(MotionEvent event) {
1845
+ return super.onHoverEvent(event);
1846
+ }
1847
+
1848
+ private int defaultSectionPosition = -1;
1849
+ /**
1850
+ * 设置选中的子view,注意此方法只在view已经显示出来以后调用才有效。
1851
+ *
1852
+ * @param position
1853
+ */
1854
+ public void setSelectChildPosition(int position, boolean changeTargetFocusChild) {
1855
+ //Log.i(TAG, "setSelectChildPosition position:" + position + " ,changeTargetFocusChild:" + changeTargetFocusChild + ",hasCode:" + hashCode() + ",enableSelectOnFocus:" + enableSelectOnFocus);
1856
+ final View selectedChild = findSelectedChild();
1857
+ if (selectedChild != null && selectedChild.isSelected()) {
1858
+ selectedChild.setSelected(false);
1859
+ }
1860
+ // if (changeTargetFocusChild) {
1861
+ // setTargetFocusChildPosition(position);
1862
+ // }
1863
+ this.defaultSectionPosition = position;
1864
+ if (!hasFocus() || !enableSelectOnFocus) {
1865
+ final View next = findViewByPosition(position);
1866
+ changeSelectState(next, true);
1867
+ }
1868
+ }
1869
+
1870
+ private View findViewByPosition(int position) {
1871
+ if (getChildCount() > position && position > -1) {
1872
+ return getChildAt(position);
1873
+ }
1874
+ return null;
1875
+ }
1876
+
1877
+ private boolean enableSelectOnFocus = false;
1878
+ // protected boolean enableFocusMemory = true;
1879
+
1880
+ public void setEnableSelectOnFocus(boolean enableSelectOnFocus) {
1881
+ this.enableSelectOnFocus = enableSelectOnFocus;
1882
+ Log.d("DebugDivSelect","setEnableSelectOnFocus flag:"+enableSelectOnFocus+",this:"+ExtendUtil.debugViewLite(this));
1883
+ }
1884
+
1885
+ public void clearSelectChild(){
1886
+ final View selectedChild = findSelectedChild() == null ? findViewByPosition(defaultSectionPosition) : findSelectedChild();
1887
+ // Log.i("CustomState","clearSelectChild selectedChild:"+ExtendUtil.debugViewLite(selectedChild)+" defaultSectionPosition:"+defaultSectionPosition+",singleSelectPosition:"+getControlProps().singleSelectPosition);
1888
+ if (selectedChild != null) {
1889
+ selectedChild.setSelected(false);
1890
+ }
1891
+ defaultSectionPosition = -1;
1892
+ }
1893
+
1894
+ public View findSelectedChild() {
1895
+ return findViewByPosition(defaultSectionPosition);
1896
+ }
1897
+
1898
+ //获取当前selection状态
1899
+ public int getSelectChildPosition() {
1900
+ return defaultSectionPosition;
1901
+ }
1902
+
1903
+
1904
+ void changeSelectState(final int position, boolean select) {
1905
+ final View child = findViewByPosition(position);
1906
+ //Log.i("DebugDivSelect","changeSelectState position:"+position+",select:"+select);
1907
+ if (child != null) {
1908
+ changeSelectState(child, select);
1909
+ }
1910
+ }
1911
+
1912
+ void changeSelectState(View child, boolean select) {
1913
+ // if(child != null && child != getFocusedChild()){
1914
+ if (child != null) {
1915
+ if (select) {
1916
+ if (child.isSelected()) {
1917
+ child.setSelected(false);
1918
+ }
1919
+ child.setSelected(true);
1920
+ } else {
1921
+ child.setSelected(false);
1922
+ }
1923
+ }
1924
+ }
1925
+
1926
+ @Override
1927
+ protected float getLeftFadingEdgeStrength() {
1928
+ return enableCustomFade ? mFadeRect.left : super.getLeftFadingEdgeStrength();
1929
+ }
1930
+
1931
+ @Override
1932
+ protected float getRightFadingEdgeStrength() {
1933
+ return enableCustomFade ? mFadeRect.right : super.getRightFadingEdgeStrength();
1934
+ }
1935
+
1936
+ @Override
1937
+ protected float getTopFadingEdgeStrength() {
1938
+ return enableCustomFade ? mFadeRect.top : super.getTopFadingEdgeStrength();
1939
+ }
1940
+
1941
+ @Override
1942
+ protected float getBottomFadingEdgeStrength() {
1943
+ return enableCustomFade ? mFadeRect.bottom : super.getBottomFadingEdgeStrength();
1944
+ }
1945
+
1946
+ private final RectF mFadeRect = new RectF(); //[left,right,top,bottom ]
1947
+ private boolean enableCustomFade = false;
1948
+ private ValueAnimator mFadeStartAnimator,mFadeEndAnimator;
1949
+
1950
+
1951
+ /**
1952
+ *
1953
+ * @param length 渐变长度
1954
+ * @param vertical 纵向或者横向
1955
+ * @param startOrEnd 开始位置或者是结束位置
1956
+ * @param duration 时间
1957
+ * @param showOrDismiss true表示显示,false表示隐藏
1958
+ */
1959
+ public void smoothShowFade(int length,boolean vertical,boolean startOrEnd,int duration,boolean showOrDismiss){
1960
+ enableCustomFade = true;
1961
+ // if(showOrDismiss){
1962
+ // Log.i("DebugFade", "+++smoothShow length:" + length + ",vertical:" + vertical + ",startOrEnd:" + startOrEnd + ",duration:" + duration );
1963
+ // }else {
1964
+ // Log.i("DebugFade", "---smoothDismiss length:" + length + ",vertical:" + vertical + ",startOrEnd:" + startOrEnd + ",duration:" + duration );
1965
+ // }
1966
+ setFadingEdgeLength(length);
1967
+ if(vertical){
1968
+ setVerticalFadingEdgeEnabled(length > 0);
1969
+ }else{
1970
+ setHorizontalFadingEdgeEnabled(length > 0);
1971
+ }
1972
+ float current = 0;
1973
+ if(startOrEnd) {
1974
+ current = vertical ? mFadeRect.top : mFadeRect.left;
1975
+ }else{
1976
+ current = vertical ? mFadeRect.bottom : mFadeRect.right;
1977
+ }
1978
+ float target = showOrDismiss ? 1f : 0f;
1979
+ if (current == target) {
1980
+ return;
1981
+ }
1982
+ ValueAnimator animator = showOrDismiss ? ValueAnimator.ofFloat(current, 1f) : ValueAnimator.ofFloat(current, 0f);
1983
+ animator.setDuration(duration);
1984
+ if(startOrEnd){
1985
+ if(mFadeStartAnimator != null){
1986
+ mFadeStartAnimator.cancel();
1987
+ }
1988
+ mFadeStartAnimator = animator;
1989
+ }else{
1990
+ if(mFadeEndAnimator != null){
1991
+ mFadeEndAnimator.cancel();
1992
+ }
1993
+ mFadeEndAnimator = animator;
1994
+ }
1995
+ animator.addUpdateListener(animation -> {
1996
+ float value = (float) animation.getAnimatedValue();
1997
+ // Log.v("DebugFade","smoothShow value:" + value);
1998
+ if (vertical) {
1999
+ //setTranslationY(startOrEnd ? -length * value : length * value);
2000
+ if(startOrEnd){
2001
+ mFadeRect.top = value;
2002
+ }else{
2003
+ mFadeRect.bottom = value;
2004
+ }
2005
+ } else {
2006
+ if(startOrEnd){
2007
+ mFadeRect.left = value;
2008
+ }else{
2009
+ mFadeRect.right = value;
2010
+ }
2011
+ }
2012
+ postInvalidate();
2013
+ });
2014
+ animator.start();
2015
+ invalidate();
2016
+ }
2017
+
2018
+ @Override
2019
+ public boolean dispatchTouchEvent(MotionEvent ev) {
2020
+ if(isPageRoot() ){
2021
+ // if(LogUtils.isDebug()){
2022
+ // Log.i("DebugClick","dispatchTouchEvent hasFocus:"+hasFocus()+",ev.getDevice().getSources():"+ev.getDevice().getSources()+",this:"+ExtendUtil.debugViewLite(this));
2023
+ // }
2024
+ if (hasFocus()) {
2025
+ InputDevice device = ev.getDevice();
2026
+ if (device != null) {
2027
+ if ((device.getSources() & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) {
2028
+ if (!FocusManagerModule.findGlobalFocusConfig(getContext()).enableFocusableTouchMode) {
2029
+ // if(LogUtils.isDebug()){
2030
+ // Log.i("DebugClick","clear Focus on Touch");
2031
+ // }
2032
+ clearFocus();
2033
+ }
2034
+ }
2035
+ }
2036
+
2037
+ }
2038
+ }
2039
+ return super.dispatchTouchEvent(ev);
2040
+ }
2041
+ }
2042
+