Reputation: 2948
I have a View that needs to detect when it's being attached to its parent view.
In a ViewGroup
I have the OnHierarchyChangeListener
which allows me to know when a child view is being added / removed, but I need the opposite thing.
Upvotes: 16
Views: 18671
Reputation: 3742
If you are using kotlin you can use doOnAttach
extension function on View
.
view.doOnAttach {
// TODO: Your view has a parent, you can use it now.
(view.parent as ViewGroup)?.yourAction()
}
Upvotes: 3
Reputation: 4869
Solution without having to create a custom view
If the View is one you can't or don't want to modify, you can use View.addOnAttachStateChangeListener to get hooks when the view is attached to the view hierarchy and when it is detached from the view hierarchy.
Something like:
Kotlin
view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
override fun onViewAttachedToWindow(v: View) {
// Do stuff when view has been attached to window
}
override fun onViewDetachedFromWindow(v: View) {
// Do stuff when view has been detached from window
}
})
Java
view.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
@Override
public void onViewAttachedToWindow(View v) {
// Do stuff when view has been attached to window
}
@Override
public void onViewDetachedFromWindow(View v) {
// Do stuff when view has been detached from window
}
});
Upvotes: 3
Reputation: 3150
You can look at this problem in a different angle, if you monitor the parents for attached views by implementing method onViewAdded.
Example:
public class LayoutInvokeChildAdded extends RelativeLayout {
private OnDoneListener onDoneListener;
public LayoutInvokeChildAdded(Context context) {
super(context);
}
public LayoutInvokeChildAdded(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LayoutInvokeChildAdded(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public void onViewAdded(View child) {
super.onViewAdded(child);
if (onDoneListener != null)
onDoneListener.onDone(childe);
}
public void setOnDoneListener(OnDoneListener onDoneListener) {
this.onDoneListener = onDoneListener;
}
}
Upvotes: 0
Reputation: 958
I think if you need that kind of control it may be best to make it a fragment. That way you get access to a much more granular lifecycle.
Upvotes: 0
Reputation: 3938
Well, you have the view in OnHierarchyChangeListener, so I would suppose that you could add a callback to your views (by subclassing them with an interface) and call it from OnHierarchyChangeListener. This way, your views will be called at the same time that the OnHierarchyChangeListener is called.
However, I won't be surprised that when this happens, that many properties of your views like their dimensions might not be defined yet.
Upvotes: 0
Reputation: 12717
You can create custom view and do your stuff in its onAttachedToWindow
public class CustomView extends View {
public CustomView(Context context) {
super(context);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Log.d("CustomView", "onAttachedToWindow called for " + getId());
Toast.makeText(getContext(), "added", 1000).show();
}
}
[EDIT 1]
you can ensure that your customview added to correct viewgroup which you want
@Override
protected void onAttachedToWindow() {
// TODO Auto-generated method stub
super.onAttachedToWindow();
if(((View)getParent()).getId()== R.id.relativelayout2)
{
Log.d("CustomView","onAttachedToWindow called for " + getId());
Toast.makeText(context, "added", 1000).show();
}
}
Upvotes: 19