2012-09-03 173 views

回答

7

我一直在尋找這樣的事情。我能找到的最好的是View.OnAttachStateChangeListener。我懷疑它是否理想,因爲它是從窗口中刪除視圖時添加的視圖的回調 - 不是父視圖,但足以滿足我的需求。

+0

API 10上的東西嗎? –

4

您可以在自定義View代碼中覆蓋onDetachedFromWindow而不是註冊新偵聽器。

1

我墜入陷阱什麼MARMOR說:)

@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(),會搞砸整個用戶界面:)

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()