I will share my functional-style method with a filter, can be used with StreamSupport library.
@NonNull
public static <T> Function<View, Stream<T>> subViews(
@NonNull final Function<View, Optional<T>> filter
) {
return view -> RefStreams.concat(
// If current view comply target condition adds it to the result (ViewGroup too)
filter.apply(view).map(RefStreams::of).orElse(RefStreams.empty()),
// Process children if current view is a ViewGroup
ofNullable(view).filter(__ -> __ instanceof ViewGroup).map(__ -> (ViewGroup) __)
.map(viewGroup -> IntStreams.range(0, viewGroup.getChildCount())
.mapToObj(viewGroup::getChildAt)
.flatMap(subViews(filter)))
.orElse(RefStreams.empty()));
}
@NonNull
public static <T> Function<View, Optional<T>> hasType(@NonNull final Class<T> type) {
return view -> Optional.ofNullable(view).filter(type::isInstance).map(type::cast);
}
@NonNull
public static Function<View, Optional<View>> hasTag(@NonNull final String tag) {
return view -> Optional.ofNullable(view).filter(v -> Objects.equals(v.getTag(), tag));
}
Usage example:
Optional.ofNullable(navigationViewWithSubViews)
.map(subViews(hasType(NavigationView.class)))
.orElse(RefStreams.empty())
.forEach(__ -> __.setNavigationItemSelectedListener(this));