@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.
- package/package.json +1 -1
- package/rules/.clinerules +27 -4
- package/rules/.cursorrules +27 -4
- package/rules/.github/copilot-instructions.md +27 -4
- package/rules/.source/hippy/extend_views/CoverFlowHorizontalView.java +203 -0
- package/rules/.source/hippy/extend_views/CoverFlowVerticalView.java +203 -0
- package/rules/.source/hippy/extend_views/CoverFlowViewController.java +195 -0
- package/rules/.source/hippy/extend_views/EngineRootView.java +125 -0
- package/rules/.source/hippy/extend_views/ExtendTag.java +83 -0
- package/rules/.source/hippy/extend_views/FocusSearchHelper.java +124 -0
- package/rules/.source/hippy/extend_views/IRecyclerItemView.java +12 -0
- package/rules/.source/hippy/extend_views/JSEventHandleView.java +5 -0
- package/rules/.source/hippy/extend_views/MarqueeRelayManager.java +133 -0
- package/rules/.source/hippy/extend_views/MarqueeRelayTextView.java +211 -0
- package/rules/.source/hippy/extend_views/ProgressBarView.java +83 -0
- package/rules/.source/hippy/extend_views/ProgressBarViewController.java +145 -0
- package/rules/.source/hippy/extend_views/SeekBarView.java +104 -0
- package/rules/.source/hippy/extend_views/SeekBarViewController.java +218 -0
- package/rules/.source/hippy/extend_views/StateImageView.java +149 -0
- package/rules/.source/hippy/extend_views/StateImageViewController.java +34 -0
- package/rules/.source/hippy/extend_views/TVButtonView.java +314 -0
- package/rules/.source/hippy/extend_views/TVButtonViewController.java +89 -0
- package/rules/.source/hippy/extend_views/TVTextView.java +684 -0
- package/rules/.source/hippy/extend_views/TVViewActor.java +811 -0
- package/rules/.source/hippy/extend_views/TVViewActorHost.java +6 -0
- package/rules/.source/hippy/extend_views/TVViewActor/346/216/245/345/205/245.md +66 -0
- package/rules/.source/hippy/extend_views/TemplateUtil.java +336 -0
- package/rules/.source/hippy/extend_views/TextButtonNode.java +47 -0
- package/rules/.source/hippy/extend_views/TextViewController.java +377 -0
- package/rules/.source/hippy/extend_views/fastlist/CenterFlyInAnimator.java +96 -0
- package/rules/.source/hippy/extend_views/fastlist/ChildOnScreenScroller.java +548 -0
- package/rules/.source/hippy/extend_views/fastlist/ClonedViewTag.java +17 -0
- package/rules/.source/hippy/extend_views/fastlist/EventDeliverer.java +55 -0
- package/rules/.source/hippy/extend_views/fastlist/FastAdapter.java +4683 -0
- package/rules/.source/hippy/extend_views/fastlist/FastAdapterUtil.java +982 -0
- package/rules/.source/hippy/extend_views/fastlist/FastFlexNode.java +48 -0
- package/rules/.source/hippy/extend_views/fastlist/FastFlexView.java +873 -0
- package/rules/.source/hippy/extend_views/fastlist/FastFlexViewController.java +130 -0
- package/rules/.source/hippy/extend_views/fastlist/FastItemNode.java +67 -0
- package/rules/.source/hippy/extend_views/fastlist/FastItemView.java +306 -0
- package/rules/.source/hippy/extend_views/fastlist/FastItemViewController.java +106 -0
- package/rules/.source/hippy/extend_views/fastlist/FastListModule.java +95 -0
- package/rules/.source/hippy/extend_views/fastlist/FastListNode.java +90 -0
- package/rules/.source/hippy/extend_views/fastlist/FastListView.java +2466 -0
- package/rules/.source/hippy/extend_views/fastlist/FastListViewController.java +1038 -0
- 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
- package/rules/.source/hippy/extend_views/fastlist/FastPendingView.java +47 -0
- package/rules/.source/hippy/extend_views/fastlist/ItemDecorations.java +71 -0
- package/rules/.source/hippy/extend_views/fastlist/ItemStoreNode.java +64 -0
- package/rules/.source/hippy/extend_views/fastlist/ItemStoreView.java +13 -0
- package/rules/.source/hippy/extend_views/fastlist/ItemStoreViewController.java +45 -0
- package/rules/.source/hippy/extend_views/fastlist/ListItemHolder.java +7 -0
- package/rules/.source/hippy/extend_views/fastlist/ListViewControlProp.java +41 -0
- package/rules/.source/hippy/extend_views/fastlist/MouseRecycleView.java +509 -0
- package/rules/.source/hippy/extend_views/fastlist/OnFastItemClickListener.java +12 -0
- package/rules/.source/hippy/extend_views/fastlist/OnFastItemFocusChangeListener.java +9 -0
- package/rules/.source/hippy/extend_views/fastlist/OnFastScrollStateChangedListener.java +7 -0
- package/rules/.source/hippy/extend_views/fastlist/PendingListNode.java +18 -0
- package/rules/.source/hippy/extend_views/fastlist/PendingViewController.java +13 -0
- package/rules/.source/hippy/extend_views/fastlist/PostHandlerView.java +6 -0
- package/rules/.source/hippy/extend_views/fastlist/PostTaskHolder.java +20 -0
- package/rules/.source/hippy/extend_views/fastlist/ReplaceChildController.java +105 -0
- package/rules/.source/hippy/extend_views/fastlist/ReplaceChildView.java +312 -0
- package/rules/.source/hippy/extend_views/fastlist/TVListView.java +3692 -0
- package/rules/.source/hippy/extend_views/fastlist/TemplateCodeParser.java +247 -0
- package/rules/.source/hippy/extend_views/fastlist/Utils.java +572 -0
- package/rules/.source/hippy/extend_views/fastlist/ViewTag.java +317 -0
- package/rules/.source/hippy/extend_views/fastlist/VirtualListView.java +8 -0
- package/rules/.source/hippy/extend_views/fastlist/diff/FastListDataBindingHelper.java +320 -0
- package/rules/.source/hippy/extend_views/fastlist/diff/KeyDiffHelper.java +289 -0
- package/rules/.source/hippy/extend_views/fastlist/diff/NoKeyDiffHelper.java +278 -0
- package/rules/.source/hippy/extend_views/tag/FontTag.java +53 -0
- package/rules/.source/hippy/extend_views/tag/HtmlTag.java +191 -0
- package/rules/.source/hippy/extend_views/tag/HtmlTagHandler.java +185 -0
- package/rules/.source/hippy/extend_views/tag/SpanTag.java +160 -0
- package/rules/.source/hippy/extend_views/tag/TextFontSpan.java +102 -0
- package/rules/.source/hippy/extend_views/waterfall/Chunk.java +10 -0
- package/rules/.source/hippy/extend_views/waterfall/ChunkGroup.java +5 -0
- package/rules/.source/hippy/extend_views/waterfall/Section.java +4 -0
- package/rules/.source/hippy/extend_views/waterfall/Tabs.java +5 -0
- package/rules/.source/hippy/extend_views/waterfall/WaterfallUtils.java +26 -0
- package/rules/.source/hippy/hippy_uimanager/ControllerHolder.java +30 -0
- package/rules/.source/hippy/hippy_uimanager/ControllerManager.java +651 -0
- package/rules/.source/hippy/hippy_uimanager/ControllerRegistry.java +102 -0
- package/rules/.source/hippy/hippy_uimanager/ControllerUpdateManger.java +252 -0
- package/rules/.source/hippy/hippy_uimanager/CustomControllerHelper.java +425 -0
- package/rules/.source/hippy/hippy_uimanager/DiffUtils.java +526 -0
- package/rules/.source/hippy/hippy_uimanager/ExtendViewGroup.java +36 -0
- package/rules/.source/hippy/hippy_uimanager/HippyCustomViewCreator.java +29 -0
- package/rules/.source/hippy/hippy_uimanager/HippyGroupController.java +83 -0
- package/rules/.source/hippy/hippy_uimanager/HippyViewBase.java +27 -0
- package/rules/.source/hippy/hippy_uimanager/HippyViewController.java +2189 -0
- package/rules/.source/hippy/hippy_uimanager/HippyViewEvent.java +52 -0
- package/rules/.source/hippy/hippy_uimanager/IHippyZIndexViewGroup.java +24 -0
- package/rules/.source/hippy/hippy_uimanager/InternalExtendViewUtil.java +395 -0
- package/rules/.source/hippy/hippy_uimanager/ListItemRenderNode.java +143 -0
- package/rules/.source/hippy/hippy_uimanager/ListViewRenderNode.java +44 -0
- package/rules/.source/hippy/hippy_uimanager/MatrixUtil.java +470 -0
- package/rules/.source/hippy/hippy_uimanager/NativeGestureDispatcher.java +349 -0
- package/rules/.source/hippy/hippy_uimanager/NativeGestureProcessor.java +188 -0
- package/rules/.source/hippy/hippy_uimanager/PullFooterRenderNode.java +43 -0
- package/rules/.source/hippy/hippy_uimanager/PullHeaderRenderNode.java +43 -0
- package/rules/.source/hippy/hippy_uimanager/RenderManager.java +304 -0
- package/rules/.source/hippy/hippy_uimanager/RenderNode.java +533 -0
- package/rules/.source/hippy/hippy_uimanager/StateView.java +17 -0
- package/rules/.source/hippy/hippy_uimanager/TransformUtil.java +125 -0
- package/rules/.source/hippy/hippy_uimanager/ViewGroupDrawingOrderHelper.java +108 -0
- package/rules/.source/hippy/hippy_uimanager/ViewStateProvider.java +10 -0
- package/rules/.source/hippy/hippy_views/audioview/AudioPlayManager.java +457 -0
- package/rules/.source/hippy/hippy_views/audioview/AudioView.java +225 -0
- package/rules/.source/hippy/hippy_views/audioview/AudioViewController.java +135 -0
- package/rules/.source/hippy/hippy_views/common/CommonBackgroundDrawable.java +58 -0
- package/rules/.source/hippy/hippy_views/common/CommonBorder.java +37 -0
- package/rules/.source/hippy/hippy_views/custom/HippyCustomPropsController.java +61 -0
- package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerListAdapter.java +399 -0
- package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerView.java +378 -0
- package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerViewController.java +187 -0
- package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerViewHolder.java +39 -0
- package/rules/.source/hippy/hippy_views/hippylist/HippyRecyclerViewWrapper.java +134 -0
- package/rules/.source/hippy/hippy_views/hippylist/NodePositionHelper.java +55 -0
- package/rules/.source/hippy/hippy_views/hippylist/PreloadHelper.java +54 -0
- package/rules/.source/hippy/hippy_views/hippylist/PullFooterEventHelper.java +61 -0
- package/rules/.source/hippy/hippy_views/hippylist/PullHeaderEventHelper.java +127 -0
- package/rules/.source/hippy/hippy_views/hippylist/RecyclerViewEventHelper.java +394 -0
- package/rules/.source/hippy/hippy_views/image/HippyContentDrawable.java +113 -0
- package/rules/.source/hippy/hippy_views/image/HippyImageView.java +1608 -0
- package/rules/.source/hippy/hippy_views/image/HippyImageViewController.java +382 -0
- package/rules/.source/hippy/hippy_views/image/IImageStateListener.java +7 -0
- package/rules/.source/hippy/hippy_views/list/ChildOnScreenScroller.java +255 -0
- package/rules/.source/hippy/hippy_views/list/HippyListAdapter.java +647 -0
- package/rules/.source/hippy/hippy_views/list/HippyListItemView.java +162 -0
- package/rules/.source/hippy/hippy_views/list/HippyListItemViewController.java +45 -0
- package/rules/.source/hippy/hippy_views/list/HippyListView.java +915 -0
- package/rules/.source/hippy/hippy_views/list/HippyListViewController.java +622 -0
- package/rules/.source/hippy/hippy_views/list/HippyRecycler.java +31 -0
- package/rules/.source/hippy/hippy_views/list/IRecycleItemTypeChange.java +23 -0
- package/rules/.source/hippy/hippy_views/list/ItemDecorations.java +70 -0
- package/rules/.source/hippy/hippy_views/list/NegativeLongKeyFlinger.java +156 -0
- package/rules/.source/hippy/hippy_views/list/NodeHolder.java +34 -0
- package/rules/.source/hippy/hippy_views/list/RecycleViewFlinger.java +126 -0
- package/rules/.source/hippy/hippy_views/list/TVRecyclerView.java +2070 -0
- package/rules/.source/hippy/hippy_views/list/TVSingleLineListView.java +15 -0
- package/rules/.source/hippy/hippy_views/modal/HippyModalHostManager.java +102 -0
- package/rules/.source/hippy/hippy_views/modal/HippyModalHostView.java +597 -0
- package/rules/.source/hippy/hippy_views/modal/ModalHostHelper.java +46 -0
- package/rules/.source/hippy/hippy_views/modal/ModalStyleNode.java +34 -0
- package/rules/.source/hippy/hippy_views/modal/RequestCloseEvent.java +32 -0
- package/rules/.source/hippy/hippy_views/modal/ShowEvent.java +31 -0
- package/rules/.source/hippy/hippy_views/navigator/Navigator.java +126 -0
- package/rules/.source/hippy/hippy_views/navigator/NavigatorController.java +120 -0
- package/rules/.source/hippy/hippy_views/refresh/HippyPullFooterView.java +47 -0
- package/rules/.source/hippy/hippy_views/refresh/HippyPullFooterViewController.java +65 -0
- package/rules/.source/hippy/hippy_views/refresh/HippyPullHeaderView.java +39 -0
- package/rules/.source/hippy/hippy_views/refresh/HippyPullHeaderViewController.java +104 -0
- package/rules/.source/hippy/hippy_views/refresh/RefreshWrapper.java +237 -0
- package/rules/.source/hippy/hippy_views/refresh/RefreshWrapperController.java +62 -0
- package/rules/.source/hippy/hippy_views/refresh/RefreshWrapperItemController.java +39 -0
- package/rules/.source/hippy/hippy_views/refresh/RefreshWrapperItemView.java +26 -0
- package/rules/.source/hippy/hippy_views/scroll/HippyHorizontalScrollView.java +500 -0
- package/rules/.source/hippy/hippy_views/scroll/HippyOnScrollHelper.java +39 -0
- package/rules/.source/hippy/hippy_views/scroll/HippyScrollView.java +46 -0
- package/rules/.source/hippy/hippy_views/scroll/HippyScrollViewController.java +178 -0
- package/rules/.source/hippy/hippy_views/scroll/HippyScrollViewEventHelper.java +92 -0
- package/rules/.source/hippy/hippy_views/scroll/HippyVerticalScrollView.java +522 -0
- package/rules/.source/hippy/hippy_views/text/HippyTextView.java +512 -0
- package/rules/.source/hippy/hippy_views/text/HippyTextViewController.java +77 -0
- package/rules/.source/hippy/hippy_views/textinput/HippyTextInput.java +668 -0
- package/rules/.source/hippy/hippy_views/textinput/HippyTextInputController.java +528 -0
- package/rules/.source/hippy/hippy_views/textinput/TextInputNode.java +115 -0
- package/rules/.source/hippy/hippy_views/videoview/APEZProvider.java +287 -0
- package/rules/.source/hippy/hippy_views/videoview/APKExpansionSupport.java +82 -0
- package/rules/.source/hippy/hippy_views/videoview/PivotPoint.java +13 -0
- package/rules/.source/hippy/hippy_views/videoview/ScalableType.java +34 -0
- package/rules/.source/hippy/hippy_views/videoview/ScalableVideoView.java +265 -0
- package/rules/.source/hippy/hippy_views/videoview/ScaleManager.java +191 -0
- package/rules/.source/hippy/hippy_views/videoview/Size.java +19 -0
- package/rules/.source/hippy/hippy_views/videoview/VideoHippyView.java +917 -0
- package/rules/.source/hippy/hippy_views/videoview/VideoHippyViewController.java +236 -0
- package/rules/.source/hippy/hippy_views/videoview/ZipResourceFile.java +427 -0
- package/rules/.source/hippy/hippy_views/view/CardRootView.java +28 -0
- package/rules/.source/hippy/hippy_views/view/CustomLayoutView.java +10 -0
- package/rules/.source/hippy/hippy_views/view/CustomNodeView.java +5 -0
- package/rules/.source/hippy/hippy_views/view/DialogViewGroup.java +113 -0
- package/rules/.source/hippy/hippy_views/view/HippyViewGroup.java +2042 -0
- package/rules/.source/hippy/hippy_views/view/HippyViewGroupController.java +583 -0
- package/rules/.source/hippy/hippy_views/view/WindowRoot.java +5 -0
- package/rules/.source/hippy/hippy_views/viewpager/HippyViewPager.java +308 -0
- package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerAdapter.java +148 -0
- package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerController.java +246 -0
- package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerItem.java +27 -0
- package/rules/.source/hippy/hippy_views/viewpager/HippyViewPagerItemController.java +42 -0
- package/rules/.source/hippy/hippy_views/viewpager/ViewPagerPageChangeListener.java +114 -0
- package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageItemExposureEvent.java +40 -0
- package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageScrollEvent.java +43 -0
- package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageScrollStateChangedEvent.java +42 -0
- package/rules/.source/hippy/hippy_views/viewpager/event/HippyPageSelectedEvent.java +42 -0
- package/rules/.source/hippy/hippy_views/webview/HippyWebView.java +160 -0
- package/rules/.source/hippy/hippy_views/webview/HippyWebViewBridge.java +20 -0
- package/rules/.source/hippy/hippy_views/webview/HippyWebViewController.java +103 -0
- package/rules/.source/hippy/hippy_views/webview/HippyWebViewInner.java +77 -0
- package/rules/.windsurfrules +27 -4
- package/rules/AGENTS.md +27 -4
- package/rules/CLAUDE.md +27 -3
- 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
|
+
|