![](/img/trans.png)
[英]Android VideoView: video goes black after being removed from parent view
[英]android on view removed from parent
在子布局(視圖)上是否有從父視圖中刪除視圖時的回調? 視圖完成后,我需要回收一些圖像。 我一直在網上四處尋找該怎么做,但還沒有找到任何有用的東西。
我也一直在尋找這樣的東西。 我能找到的最好的是 View.OnAttachStateChangeListener。 我懷疑它是否理想,因為它是從窗口添加和刪除視圖時的回調 - 不是父級,但它足以滿足我的需要。
您可以在自定義View
代碼中覆蓋onDetachedFromWindow
,而不是注冊新的偵聽器。
我掉進了馬爾默所說的那個陷阱:)
@Override
protected void onDetachedFromWindow() { I want to do something here, sometimes called sometimes not!!}
protected void onAttachedToWindow() {It is working fine, always}
此代碼位於CustomView
。
調用代碼為:
contentHolder.removeAllViews();
// ... init my CustomView ...
contentHolder.addView(myCustomView);
contentHolder.requestLayout();// useless, not need
contentHolder.invalidate();// useless, not need
要了解為什么不起作用,您必須進入 Android API:
public void removeAllViews() {
removeAllViewsInLayout();
requestLayout();
invalidate(true);
}
public void removeAllViewsInLayout() {
final int count = mChildrenCount;
if (count <= 0) {
return;
}
final View[] children = mChildren;
mChildrenCount = 0;
final View focused = mFocused;
final boolean detach = mAttachInfo != null;
boolean clearChildFocus = false;
needGlobalAttributesUpdate(false);
for (int i = count - 1; i >= 0; i--) {
final View view = children[i];
if (mTransition != null) {
mTransition.removeChild(this, view);
}
if (view == focused) {
view.unFocus(null);
clearChildFocus = true;
}
view.clearAccessibilityFocus();
cancelTouchTarget(view);
cancelHoverTarget(view);
if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
addDisappearingView(view);
} else if (detach) {
view.dispatchDetachedFromWindow();
}
if (view.hasTransientState()) {
childHasTransientStateChanged(view, false);
}
dispatchViewRemoved(view);
view.mParent = null;
children[i] = null;
}
if (clearChildFocus) {
clearChildFocus(focused);
if (!rootViewRequestFocus()) {
notifyGlobalFocusCleared(focused);
}
}
}
關鍵在這里:
if (view.getAnimation() != null ||
(mTransitioningViews != null && mTransitioningViews.contains(view))) {
所以,如果你有動畫(在 1 種情況下我有,在 9 種情況下沒有)它不會調用onDetachedFromWindow()
並且它會弄亂整個 UI :)
public void endViewTransition(View view) {
if (mTransitioningViews != null) {
mTransitioningViews.remove(view);
final ArrayList<View> disappearingChildren = mDisappearingChildren;
if (disappearingChildren != null && disappearingChildren.contains(view)) {
disappearingChildren.remove(view);
if (mVisibilityChangingChildren != null &&
mVisibilityChangingChildren.contains(view)) {
mVisibilityChangingChildren.remove(view);
} else {
if (view.mAttachInfo != null) {
view.dispatchDetachedFromWindow();
}
if (view.mParent != null) {
view.mParent = null;
}
}
invalidate();
}
}
}
同樣在某些情況下,即使有動畫也會被調用。 addDisappearingView(view);
接受的答案建議是這樣的:
addOnAttachStateChangeListener(new OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
}
@Override
public void onViewDetachedFromWindow(View v) {
System.out.println("MyCustomView.onViewDetachedFromWindow");
}
});
可悲的是動畫不會打印所需的文本。
來自 android.view.ViewGroup API 的一些重要代碼:
void dispatchViewRemoved(View child) {
onViewRemoved(child);
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(this, child);
}
}
public void onViewRemoved(View child) {
}
因此,您可以為此方法覆蓋您的RelativeLayout
。 我的動畫是無限動畫,不會很快調用任何方法!
如果您有無限動畫,正確的方法是編寫此代碼,當您調用刪除所有視圖時:
if(contentHolder.getChildCount() > 0 ){
View child0 = contentHolder.getChildAt(0);
Animation animation = child0.getAnimation();
if(animation != null) {
animation.cancel();
child0.clearAnimation();
}
}
contentHolder.removeAllViews();
現在它將被稱為protected void onDetachedFromWindow()
!
Android KTX (Core KTX)庫為此提供了一個很好的解決方案。
您將需要此依賴項:androidx.core:core-ktx:1.3.0
然后,您可以調用函數“doOnDetach”來表示您希望在從窗口中刪除視圖時運行一些代碼(一次):
fun myInitCode() {
...
myView.doOnDetach(this::doOnMyViewDetachFromWindow)
...
}
fun doOnMyViewDetachFromWindow(view: View) {
... put your image cleanup code here ...
}
您可以將 lambda 傳遞給“doOnDetach”,但如上所示的方法引用可能更清晰,具體取決於您必須執行的工作量。
doOnDetach 的描述如下:
androidx.core.view ViewKt.class public inline fun View.doOnDetach( crossinline action: (View) → Unit ): Unit
當此視圖與窗口分離時執行給定的操作。 如果視圖未附加到窗口,則操作將立即執行,否則將在視圖與其當前窗口分離后執行操作。 該操作只會被調用一次,然后將刪除所有偵聽器。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.