1.用递归的方式实现
public int traverseViewGroup ( View view) {
int viewCount = 0 ;
if ( null == view) {
return 0 ;
}
if ( view instanceof ViewGroup ) {
for ( int i = 0 ; i < ( ( ViewGroup) view) . getChildCount ( ) ; i++ ) {
View child = ( ( ViewGroup) view) . getChildAt ( i) ;
if ( child instanceof ViewGroup ) {
viewCount += traverseViewGroup ( ( ( ViewGroup) view) . getChildAt ( i) ) ;
} else {
viewCount++ ;
}
}
} else {
viewCount++ ;
}
return viewCount;
}
2.用非递归方式实现
public int traverseViewGroup ( View view) {
int viewCount = 0 ;
if ( null == view) {
return 0 ;
}
if ( view instanceof ViewGroup ) {
ViewGroup viewGroup = ( ViewGroup) view;
LinkedList< ViewGroup> linkedList = new LinkedList < > ( ) ;
linkedList. add ( viewGroup) ;
while ( ! linkedList. isEmpty ( ) ) {
ViewGroup current = linkedList. removeFirst ( ) ;
viewCount++ ;
for ( int i = 0 ; i < current. getChildCount ( ) ; i++ ) {
if ( current. getChildAt ( i) instanceof ViewGroup ) {
linkedList. addLast ( ( ViewGroup) current. getChildAt ( i) ) ;
} else {
viewCount++ ;
}
}
}
} else {
viewCount++ ;
}
return viewCount;
}
获取当前Activity的所有子View
@Override
protected void onCreate ( Bundle savedInstanceState) {
super . onCreate ( savedInstanceState) ;
setContentView ( R. layout. activity_main) ;
View decorView = this . getWindow ( ) . getDecorView ( ) ;
List< View> list = getAllChildViews ( decorView) ;
}
private List< View> getAllChildViews ( View view) {
List< View> allChildren = new ArrayList < View> ( ) ;
if ( view instanceof ViewGroup ) {
ViewGroup vp = ( ViewGroup) view;
for ( int i = 0 ; i < vp. getChildCount ( ) ; i++ ) {
View childView = vp. getChildAt ( i) ;
allChildren. add ( childView) ;
allChildren. addAll ( getAllChildViews ( childView) ) ;
}
}
return allChildren;
}
问题:两个View如何找到第一个父View?
先确定两个View中,其中一个View是否包含在另外一个View的View树中,如果包含,那么两个View的第一个父View就是这两个View的其中一个View。
代码:
View target1 = new View ( this ) ;
View target2 = new View ( this ) ;
boolean hasTarget1 = false ;
boolean hasTarget2 = false ;
@Override
protected void onCreate ( Bundle savedInstanceState) {
super . onCreate ( savedInstanceState) ;
setContentView ( R. layout. activity_main) ;
getAllChildViews1 ( target1) ;
getAllChildViews2 ( target2) ;
if ( hasTarget1) {
view2是view1和view2的第一个父view
}
if ( hasTarget2) {
view1是view1和view2的第一个父view
}
}
private List< View> getAllChildViews1 ( View view) {
List< View> allChildren = new ArrayList < View> ( ) ;
if ( view instanceof ViewGroup ) {
ViewGroup vp = ( ViewGroup) view;
for ( int i = 0 ; i < vp. getChildCount ( ) ; i++ ) {
View childView = vp. getChildAt ( i) ;
if ( childView == target2) {
hasTarget2 = true ;
}
allChildren. add ( childView) ;
allChildren. addAll ( getAllChildViews ( childView) ) ;
}
}
return allChildren;
}
private List< View> getAllChildViews2 ( View view) {
List< View> allChildren = new ArrayList < View> ( ) ;
if ( view instanceof ViewGroup ) {
ViewGroup vp = ( ViewGroup) view;
for ( int i = 0 ; i < vp. getChildCount ( ) ; i++ ) {
View childView = vp. getChildAt ( i) ;
if ( childView == target1) {
hasTarget1 = true ;
}
allChildren. add ( childView) ;
allChildren. addAll ( getAllChildViews ( childView) ) ;
}
}
return allChildren;
}
如果这两个View互不包含,那就去这两个View的父View树中寻找第一个公共节点View。
View view1 = new View ( this ) ;
View view2 = new View ( this ) ;
List< View> viewParent1 = getAllParent ( view1) ;
List< View> viewParent2 = getAllParent ( view2) ;
int len1 = viewParent1. size ( ) ;
int len2 = viewParent2. size ( ) ;
int length = Math. min ( len1, len2) ;
View result = null;
for ( int i = 0 ; i < length; i++ ) {
for ( int j = 0 ; j < length; j++ ) {
if ( viewParent1. get ( i) == viewParent2. get ( j) ) {
result = viewParent1. get ( i) ;
return ;
}
}
}
private List< View> getAllParent ( View view) {
List< View> allParent = new ArrayList < View> ( ) ;
if ( view. getParent ( ) != null) {
ViewGroup viewGroup = ( ViewGroup) view. getParent ( ) ;
allParent. add ( viewGroup) ;
allParent. addAll ( getAllParent ( viewGroup) ) ;
}
return allParent;
}
补充:view.getParent()与view.getRootView()
getParent就是获取view的父亲节点,而getRootView是寻找当前的view层次中处在最顶层的view,可理解为找出该view实例所在的view层次的根view。 如果这个view文件只是一个activity.setContentView时所引用的一个view。 1.当view处于xml文件的根节点时,通过getParent到的view都是它身。 2当view处于xml的非根节点时,通过getParent获得的是view的父亲节点。 3.无论处于xml的根节点还是子节点,通过getRootView获得的都是当前Activity的DecorView 区别于上面的情况,如果这个view处于Fregment中 1.当view处于xml文件的根节点时,通过getParent获得的是null 2.当view处于非根节点时,通过getParent获得的是它的父亲节点 3.无论处于xml的根节点还是子节点,通过getRootView获取的都是它本身。