In this post, we won’t delve into the process of customizing a ViewGroup since there are many excellent guides available for that purpose. Instead, I’ll highlight a trap in a crucial function within ViewGroup that is often overlooked by many developers.
The crucial function in ViewGroup
is shouldDelayChildPressedState()
. Let’s expoler it intended use.
The Function
public boolean shouldDelayChildPressedState() {
return true;
}
In class ViewGroup
, the default implementation return true
. As it’s named, the pressed state should be delayed for children or descendants of this ViewGroup. It is invoked by isInScrollingContainer()
in ViewGroup
.
public boolean isInScrollingContainer() {
ViewParent p = getParent();
while (p != null && p instanceof ViewGroup) {
if (((ViewGroup) p).shouldDelayChildPressedState()) {
return true;
}
p = p.getParent();
}
return false;
}
This function checks whether its parents are a scrolling container or not. It is invoked in the View
’s touch event logic.
public boolean onTouchEvent(MotionEvent event) {
...
switch (action) {
case MotionEvent.ACTION_DOWN:
if (isInScrollingContainer()) { // <----
postDelayed(mPendingCheckForTap,
ViewConfiguration.getTapTimeout());
} else {
setPressed(true, x, y);
}
break;
}
...
}
As I mentioned before, when the view that has been touch is inside a scrolling container, it will delay the pressed feedback for a short period.
The short period refers to ViewConfiguration.getTapTimeout()
, the value of which is 100ms
The Trap
Regardless of when you touch the view, it will introduce a 100ms delay to verify the pressed state.
OK, 100ms is a short duration for a single view, but it can become a significant factor when you prioritize app performance with a large number of views.
So, we do not need this 100ms delay if the ViewGroup
is not scrollable, that means implementation of shouldDelayChildPressedState
should return false
.
The trap lies in the default implementation, which returns true, and surprisingly, there are no official guides that mention it. It’s easy to overlooked this.
The implementations of ViewGroup’s non-scrollable subclasses, such as FrameLayout
or LinearLayout
, return false.
I prefer to use these subclasses for customizing rather than using ViewGroup
directly to avoid these unexpected traps.