下面列出了怎么用android.view.ViewParent的API类实例代码及写法,或者点击链接到github查看源代码。
@Override
protected void onDestroy() {
if (mWebView != null) {
// 如果先调用destroy()方法,则会命中if (isDestroyed()) return;这一行代码,需要先onDetachedFromWindow(),再
// destory()
ViewParent parent = mWebView.getParent();
if (parent != null) {
((ViewGroup) parent).removeView(mWebView);
}
mWebView.stopLoading();
// 退出时调用此方法,移除绑定的服务,否则某些特定系统会报错
mWebView.getSettings().setJavaScriptEnabled(false);
mWebView.clearHistory();
mWebView.clearView();
mWebView.removeAllViews();
mWebView.destroy();
}
super.onDestroy();
AnalysysAgent.resetHybridModel(mContext, mWebView);
}
/**
* Returns a matcher that matches {@link View}s based on the given parent type.
*
* @param parentMatcher the type of the parent to match on
*/
public static Matcher<View> isChildOfA(final Matcher<View> parentMatcher) {
return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("is child of a: ");
parentMatcher.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
final ViewParent viewParent = view.getParent();
if (!(viewParent instanceof View)) {
return false;
}
if (parentMatcher.matches(viewParent)) {
return true;
}
return false;
}
};
}
public StatusProvider(Context context, String status, View contentView, OnStatusViewCreateCallback callback){
this.mContext = context;
this.status = status;
this.contentView = contentView;
this.callback = callback;
if(contentView == null){
throw new RuntimeException("contentView不能为null");
}
ViewParent p = this.contentView.getParent();
if(p instanceof FrameLayout){
this.container = (FrameLayout) p;
}else{
throw new RuntimeException(contentView.getClass().getName() + "必须作为FrameLayout的子元素");
}
}
private Rect getRect(View view) {
Rect rect = new Rect();
rect.top = view.getTop();
rect.left = view.getLeft();
rect.right = view.getRight();
rect.bottom = view.getBottom();
ViewParent viewParent = view.getParent();
if (viewParent != null) {
if (viewParent instanceof ViewGroup) {
Rect prect = getRect((ViewGroup) viewParent);
rect.top += prect.top;
rect.left += prect.left;
rect.right += prect.left;
rect.bottom += prect.top;
}
}
return rect;
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
// Add an OnOffsetChangedListener if possible
final ViewParent parent = getParent();
if (parent instanceof AppBarLayout) {
// Copy over from the ABL whether we should fit system windows
ViewCompat.setFitsSystemWindows(this, ViewCompat.getFitsSystemWindows((View) parent));
if (onOffsetChangedListener == null) {
onOffsetChangedListener = new OffsetUpdateListener();
}
((AppBarLayout) parent).addOnOffsetChangedListener(onOffsetChangedListener);
// We're attached, so lets request an inset dispatch
ViewCompat.requestApplyInsets(this);
}
}
private boolean intersectVisibleToUser(Rect localRect) {
if (localRect == null || localRect.isEmpty() || this.mView.getWindowVisibility() != 0) {
return false;
}
ViewParent viewParent = this.mView.getParent();
while (viewParent instanceof View) {
View view = (View) viewParent;
if (ViewCompat.getAlpha(view) <= 0.0f || view.getVisibility() != 0) {
return false;
}
viewParent = view.getParent();
}
if (viewParent == null || !this.mView.getLocalVisibleRect(this.mTempVisibleRect)) {
return false;
}
return localRect.intersect(this.mTempVisibleRect);
}
private void performAdapterViewItemClick(MotionEvent e) {
ViewParent t = getParent();
Log.d(TAG, "performAdapterViewItemClick()");
while (t != null) {
if (t instanceof AdapterView) {
@SuppressWarnings("rawtypes")
AdapterView view = (AdapterView) t;
int p = view.getPositionForView(ZSwipeItem.this);
if (p != AdapterView.INVALID_POSITION
&& view.performItemClick(
view.getChildAt(p
- view.getFirstVisiblePosition()), p,
view.getAdapter().getItemId(p)))
return;
} else {
if (t instanceof View && ((View) t).performClick())
return;
}
t = t.getParent();
}
}
public static org.hamcrest.Matcher<View> childAtPosition(
final org.hamcrest.Matcher<View> parentMatcher, final int position) {
return new TypeSafeMatcher<View>() {
@Override
public void describeTo(Description description) {
description.appendText("Child at position " + position + " in parent ");
parentMatcher.describeTo(description);
}
@Override
public boolean matchesSafely(View view) {
ViewParent parent = view.getParent();
return parent instanceof ViewGroup && parentMatcher.matches(parent)
&& view.equals(((ViewGroup) parent).getChildAt(position));
}
};
}
private boolean shouldInheritContext(ViewParent parent) {
if (parent == null) {
// The initial parent is null so just return false
return false;
}
final View windowDecor = mAppCompatActivity.getWindow().getDecorView();
while (true) {
if (parent == null) {
// Bingo. We've hit a view which has a null parent before being terminated from
// the loop. This is (most probably) because it's the root view in an inflation
// call, therefore we should inherit. This works as the inflated layout is only
// added to the hierarchy at the end of the inflate() call.
return true;
} else if (parent == windowDecor || !(parent instanceof View)
|| ViewCompat.isAttachedToWindow((View) parent)) {
// We have either hit the window's decor view, a parent which isn't a View
// (i.e. ViewRootImpl), or an attached view, so we know that the original parent
// is currently added to the view hierarchy. This means that it has not be
// inflated in the current inflate() call and we should not inherit the context.
return false;
}
parent = parent.getParent();
}
}
@Override
public void setAttached(final View view, final boolean isAttached) {
Native.system().runOnEventThread(() -> {
ViewParent parent = view.getParent();
boolean isAttachedNow = parent != null;
if (isAttached == isAttachedNow)
return;
ActivityLifecycleListener listener = ((AndroidNativeWidget) view).getLifecycleListener();
if (isAttachedNow) {
MainView.current.removeView(view);
if (listener != null) {
MainActivity.current.getStateListener().unregister(listener);
listener.onPause();
listener.onDestroy();
}
} else {
MainView.current.addView(view);
if (listener != null) {
MainActivity.current.getStateListener().register(listener);
listener.onCreate(MainActivity.current.getInstanceState());
listener.onResume();
}
}
// AndroidGraphicsBridge.mainview.bringToFront();
});
}
private void settleToStatePendingLayout(@State int state) {
final V child = viewRef.get();
if (child == null) {
return;
}
// Start the animation; wait until a pending layout if there is one.
ViewParent parent = child.getParent();
if (parent != null && parent.isLayoutRequested() && ViewCompat.isAttachedToWindow(child)) {
final int finalState = state;
child.post(
new Runnable() {
@Override
public void run() {
settleToState(child, finalState);
}
});
} else {
settleToState(child, state);
}
}
@Override
public void onChildViewAdded(final View parent, final View child) {
Log.d(TAG, "child is added: " + child);
ViewParent scrollView = parent.getParent();
if (scrollView != null && scrollView instanceof ScrollView) {
((ScrollView) scrollView).fullScroll(FOCUS_DOWN);
}
if (getLayoutTransition() != null) {
View view = child.findViewById(R.id.card_actionarea);
if (view != null)
view.setAlpha(0.f);
}
}
@Override
public void onFragmentDestroy() {
super.onFragmentDestroy();
AndroidUtilities.cancelRunOnUIThread(typingRunnable);
webView.setLayerType(View.LAYER_TYPE_NONE, null);
typingRunnable = null;
try {
ViewParent parent = webView.getParent();
if (parent != null) {
((FrameLayout) parent).removeView(webView);
}
webView.stopLoading();
webView.loadUrl("about:blank");
webView.destroy();
webView = null;
} catch (Exception e) {
FileLog.e(e);
}
}
@Test
public void onAppear_CalledAtMostOnce() {
ViewController spy = spy(uut);
Shadows.shadowOf(spy.getView()).setMyParent(mock(ViewParent.class));
Assertions.assertThat(spy.getView()).isShown();
spy.getView().getViewTreeObserver().dispatchOnGlobalLayout();
spy.getView().getViewTreeObserver().dispatchOnGlobalLayout();
spy.getView().getViewTreeObserver().dispatchOnGlobalLayout();
verify(spy, times(1)).onViewAppeared();
}
/**
* Expands the {@link FlexibleToolbarLayout}.
* This will only have an effect if the {@link FlexibleToolbarLayout}
* is used as a child of {@link AppBarLayout}.
*/
public void expand() {
// Passes call to AppBarLayout if possible
ViewParent parent = getParent();
if (parent instanceof AppBarLayout) {
((AppBarLayout) parent).setExpanded(true);
}
}
@SuppressLint("MissingSuperCall")
@Override
protected void onBindDialogView(@NonNull View view) {
EditText editText = mEditText;
editText.setText(getText());
// Initialize cursor to end of text
if (editText.getText().length() > 0)
editText.setSelection(editText.length());
ViewParent oldParent = editText.getParent();
if (oldParent != view) {
if (oldParent != null)
((ViewGroup) oldParent).removeView(editText);
onAddEditTextToDialogView(view, editText);
}
}
public static boolean isInScrollingContainer(ViewParent p) {
while (p != null && p instanceof ViewGroup) {
if (((ViewGroup) p).shouldDelayChildPressedState()) {
return true;
}
p = p.getParent();
}
return false;
}
public boolean isInScrollingContainer() {
ViewParent p = getParent();
while (p != null && p instanceof ViewGroup) {
if (((ViewGroup) p).shouldDelayChildPressedState()) {
return true;
}
p = p.getParent();
}
return false;
}
public static boolean isShown(View mContentLayout) {
if (!mContentLayout.isShown())
return false;
ViewParent parent = mContentLayout.getParent();
do {
if (parent instanceof View && !((View) parent).isShown())
return false;
else
System.out.println(parent.getClass());
} while ((parent = parent.getParent()) != null);
return true;
}
static void offsetTopAndBottom(View view, int offset) {
view.offsetTopAndBottom(offset);
ViewParent parent = view.getParent();
if (parent instanceof View) {
tickleInvalidationFlag((View) parent);
}
}
public static void removeSelfFromParent(View v){
if(v!=null){
ViewParent parent = v.getParent();
if(parent!=null && parent instanceof ViewGroup){
ViewGroup group=(ViewGroup) parent;
group.removeView(v);
}
}
}
private static List<Boolean> setAncestralClipping(
@NonNull View view, boolean clipChildren, List<Boolean> was) {
if (view instanceof ViewGroup) {
ViewGroup group = (ViewGroup) view;
was.add(group.getClipChildren());
group.setClipChildren(clipChildren);
}
ViewParent parent = view.getParent();
if (parent != null && parent instanceof ViewGroup) {
setAncestralClipping((ViewGroup) parent, clipChildren, was);
}
return was;
}
/**
* 是否请求当前view的父view不要拦截事件
*
* @param view
* @param disallowIntercept true-请求父view不要拦截,false-父view可以拦截
*/
public static void requestDisallowInterceptTouchEvent(View view, boolean disallowIntercept)
{
final ViewParent parent = view.getParent();
if (parent != null)
parent.requestDisallowInterceptTouchEvent(disallowIntercept);
}
/**
* Determines if any of the provided {@link View}'s and {@link AccessibilityNodeInfoCompat}'s
* ancestors can receive accessibility focus
*
* @param view The {@link View} to evaluate
* @param node The {@link AccessibilityNodeInfoCompat} to evaluate
* @return {@code true} if an ancestor of may receive accessibility focus
*/
public static boolean hasFocusableAncestor(
@Nullable AccessibilityNodeInfoCompat node, @Nullable View view) {
if (node == null || view == null) {
return false;
}
final ViewParent parentView = ViewCompat.getParentForAccessibility(view);
if (!(parentView instanceof View)) {
return false;
}
final AccessibilityNodeInfoCompat parentNode = createNodeInfoFromView((View) parentView);
try {
if (parentNode == null) {
return false;
}
if (areBoundsIdenticalToWindow(parentNode, (View) parentView)
&& parentNode.getChildCount() > 0) {
return false;
}
if (isAccessibilityFocusable(parentNode, (View) parentView)) {
return true;
}
if (hasFocusableAncestor(parentNode, (View) parentView)) {
return true;
}
} finally {
if (parentNode != null) {
parentNode.recycle();
}
}
return false;
}
private static void removeViewFromParent(@Nullable View view) {
if (view == null) {
return;
}
ViewParent parent = view.getParent();
if (parent instanceof ViewGroup) {
((ViewGroup) parent).removeView(view);
}
}
private AdapterView getAdapterView() {
ViewParent t = getParent();
if (t instanceof AdapterView) {
return (AdapterView) t;
}
return null;
}
/**
* Sets the Empty View to be used by the Adapter View.
* <p/>
* We need it handle it ourselves so that we can Pull-to-Refresh when the
* Empty View is shown.
* <p/>
* Please note, you do <strong>not</strong> usually need to call this method
* yourself. Calling setEmptyView on the AdapterView will automatically call
* this method and set everything up. This includes when the Android
* Framework automatically sets the Empty View based on it's ID.
*
* @param newEmptyView - Empty View to be used
*/
public final void setEmptyView(View newEmptyView) {
FrameLayout refreshableViewWrapper = getRefreshableViewWrapper();
if (null != newEmptyView) {
// New view needs to be clickable so that Android recognizes it as a
// target for Touch Events
newEmptyView.setClickable(true);
ViewParent newEmptyViewParent = newEmptyView.getParent();
if (null != newEmptyViewParent && newEmptyViewParent instanceof ViewGroup) {
((ViewGroup) newEmptyViewParent).removeView(newEmptyView);
}
// We need to convert any LayoutParams so that it works in our
// FrameLayout
FrameLayout.LayoutParams lp = convertEmptyViewLayoutParams(newEmptyView.getLayoutParams());
if (null != lp) {
refreshableViewWrapper.addView(newEmptyView, lp);
} else {
refreshableViewWrapper.addView(newEmptyView);
}
}
if (mRefreshableView instanceof EmptyViewMethodAccessor) {
((EmptyViewMethodAccessor) mRefreshableView).setEmptyViewInternal(newEmptyView);
} else {
mRefreshableView.setEmptyView(newEmptyView);
}
mEmptyView = newEmptyView;
}
private static View findBottomSheetParent(final View view) {
View current = view;
while (current != null) {
final ViewGroup.LayoutParams params = current.getLayoutParams();
if (params instanceof CoordinatorLayout.LayoutParams && ((CoordinatorLayout.LayoutParams) params).getBehavior() instanceof ViewPagerBottomSheetBehavior) {
return current;
}
final ViewParent parent = current.getParent();
current = parent == null || !(parent instanceof View) ? null : (View) parent;
}
return null;
}
void update(View item, View header, Drawable divider, int dividerHeight) {
//every wrapperview must have a list item
if (item == null) {
throw new NullPointerException("List view item must not be null.");
}
//only remove the current item if it is not the same as the new item. this can happen if wrapping a recycled view
if (this.mItem != item) {
removeView(this.mItem);
this.mItem = item;
final ViewParent parent = item.getParent();
if(parent != null && parent != this) {
if(parent instanceof ViewGroup) {
((ViewGroup) parent).removeView(item);
}
}
addView(item);
}
//same logik as above but for the header
if (this.mHeader != header) {
if (this.mHeader != null) {
removeView(this.mHeader);
}
this.mHeader = header;
if (header != null) {
addView(header);
}
}
if (this.mDivider != divider) {
this.mDivider = divider;
this.mDividerHeight = dividerHeight;
invalidate();
}
}
private void performAdapterViewItemClick() {
if (getOpenStatus() != Status.Close) return;
ViewParent t = getParent();
if (t instanceof AdapterView) {
AdapterView view = (AdapterView) t;
int p = view.getPositionForView(SwipeViewLayout.this);
if (p != AdapterView.INVALID_POSITION) {
view.performItemClick(view.getChildAt(p - view.getFirstVisiblePosition()), p, view
.getAdapter().getItemId(p));
}
}
}