Android |获取视图组的所有子元素
Android |获取视图组的所有子元素,android,Android,getChildAt(i)on仅获取视图组的直接子级,是否可以访问所有子级而不执行嵌套循环?() 如果要获取所有子视图以及子视图组中的视图,必须递归执行,因为API中没有开箱即用的规定 private ArrayList<View> getAllChildren(View v) { if (!(v instanceof ViewGroup)) { ArrayList<View> viewArrayList = new ArrayList<V
getChildAt(i)
on仅获取视图组的直接子级,是否可以访问所有子级而不执行嵌套循环?()
如果要获取所有子视图以及子视图组中的视图,必须递归执行,因为API中没有开箱即用的规定
private ArrayList<View> getAllChildren(View v) {
if (!(v instanceof ViewGroup)) {
ArrayList<View> viewArrayList = new ArrayList<View>();
viewArrayList.add(v);
return viewArrayList;
}
ArrayList<View> result = new ArrayList<View>();
ViewGroup viewGroup = (ViewGroup) v;
for (int i = 0; i < viewGroup.getChildCount(); i++) {
View child = viewGroup.getChildAt(i);
ArrayList<View> viewArrayList = new ArrayList<View>();
viewArrayList.add(v);
viewArrayList.addAll(getAllChildren(child));
result.addAll(viewArrayList);
}
return result;
}
private ArrayList getAllChildren(视图v){
如果(!(视图组的v实例)){
ArrayList viewArrayList=新建ArrayList();
viewArrayList.add(v);
返回viewArrayList;
}
ArrayList结果=新建ArrayList();
ViewGroup ViewGroup=(ViewGroup)v;
对于(int i=0;i
这将为您提供一个包含层次结构中所有视图的ArrayList,然后您可以对其进行迭代
本质上,如果代码在层次结构中找到另一个视图组,然后返回要添加到更大的ArrayList中的ArrayList,则该代码会调用自身。在编写此答案时,接受的答案存在缺陷,因为它的结果中会包含重复项
对于那些难以理解递归的人,这里有一个非递归的替代方案。如果您意识到这也是一种广度优先的搜索方法,而不是另一个答案的深度优先方法,您将获得额外的分数
private List<View> getAllChildrenBFS(View v) {
List<View> visited = new ArrayList<View>();
List<View> unvisited = new ArrayList<View>();
unvisited.add(v);
while (!unvisited.isEmpty()) {
View child = unvisited.remove(0);
visited.add(child);
if (!(child instanceof ViewGroup)) continue;
ViewGroup group = (ViewGroup) child;
final int childCount = group.getChildCount();
for (int i=0; i<childCount; i++) unvisited.add(group.getChildAt(i));
}
return visited;
}
私有列表getAllChildrenBFS(视图v){
访问列表=新建ArrayList();
列表未访问=新建ArrayList();
未访问。添加(v);
而(!unvisited.isEmpty()){
查看子项=未访问。删除(0);
访问。添加(儿童);
如果(!(视图组的子实例))继续;
ViewGroup group=(ViewGroup)子级;
final int childCount=group.getChildCount();
对于(int i=0;i我已经以递归的方式重新实现了这个方法。不确定它是否比MH的快,但至少它没有重复
private List<View> getAllViews(View v) {
if (!(v instanceof ViewGroup) || ((ViewGroup) v).getChildCount() == 0) // It's a leaf
{ List<View> r = new ArrayList<View>(); r.add(v); return r; }
else {
List<View> list = new ArrayList<View>(); list.add(v); // If it's an internal node add itself
int children = ((ViewGroup) v).getChildCount();
for (int i=0;i<children;++i) {
list.addAll(getAllViews(((ViewGroup) v).getChildAt(i)));
}
return list;
}
}
私有列表GetAllView(视图v){
if(!(v instanceof ViewGroup)| |((ViewGroup)v).getChildCount()==0)//这是一个叶
{List r=new ArrayList();r.add(v);返回r;}
否则{
List List=new ArrayList();List.add(v);//如果是内部节点,则添加自身
int children=((视图组)v.getChildCount();
对于(int i=0;i我不知道它是否好。只需重写onViewAdded(View child)方法,并在列表中添加视图即可。请思考。由。这在编写自定义视图组时非常有用
将新的子视图添加到此视图组时调用。重写应始终调用super.onViewAdded
下面是我的(递归)解决方案,它按如下方式打印层次结构:
android.widget.LinearLayout children:2 id:-1
android.view.View id:2131624246
android.widget.RelativeLayout children:2 id:2131624247
android.support.v7.widget.AppCompatTextView id:2131624248
android.support.v7.widget.SwitchCompat id:2131624249
public static String getViewHierarcy(ViewGroup v) {
StringBuffer buf = new StringBuffer();
printViews(v, buf, 0);
return buf.toString();
}
private static String printViews(ViewGroup v, StringBuffer buf, int level) {
final int childCount = v.getChildCount();
v.getId();
indent(buf, level);
buf.append(v.getClass().getName());
buf.append(" children:");
buf.append(childCount);
buf.append(" id:"+v.getId());
buf.append("\n");
for (int i = 0; i < childCount; i++) {
View child = v.getChildAt(i);
if ((child instanceof ViewGroup)) {
printViews((ViewGroup) child, buf, level+1);
} else {
indent(buf, level+1);
buf.append(child.getClass().getName());
buf.append(" id:"+child.getId());
buf.append("\n");
}
}
return buf.toString();
}
private static void indent(StringBuffer buf, int level) {
for (int i = 0; i < level; i++) {
buf.append(" ");
}
}
fun ViewGroup.getAllChildren(): List<View> {
val children = ArrayList<View>()
for (i in 0 until this.childCount) {
children.add(this.getChildAt(i))
}
return children
}
android.widget.LinearLayout子项:2 id:-1
android.view.view id:21311624246
android.widget.RelativeLayout子项:2 id:21311624247
android.support.v7.widget.AppCompatTextView id:21311624248
android.support.v7.widget.SwitchCompat id:21311624249
公共静态字符串getViewHierarcy(视图组v){
StringBuffer buf=新的StringBuffer();
打印视图(v,buf,0);
返回buf.toString();
}
私有静态字符串打印视图(视图组v、StringBuffer buf、int级别){
final int childCount=v.getChildCount();
v、 getId();
缩进(buf,水平);
追加(v.getClass().getName());
buf.追加(“子项:”);
追加(儿童计数);
buf.append(“id:+v.getId());
buf.追加(“\n”);
for(int i=0;i
我最近遇到了同样的问题,并使用Kotlin的扩展函数解决了它,如下所示:
android.widget.LinearLayout children:2 id:-1
android.view.View id:2131624246
android.widget.RelativeLayout children:2 id:2131624247
android.support.v7.widget.AppCompatTextView id:2131624248
android.support.v7.widget.SwitchCompat id:2131624249
public static String getViewHierarcy(ViewGroup v) {
StringBuffer buf = new StringBuffer();
printViews(v, buf, 0);
return buf.toString();
}
private static String printViews(ViewGroup v, StringBuffer buf, int level) {
final int childCount = v.getChildCount();
v.getId();
indent(buf, level);
buf.append(v.getClass().getName());
buf.append(" children:");
buf.append(childCount);
buf.append(" id:"+v.getId());
buf.append("\n");
for (int i = 0; i < childCount; i++) {
View child = v.getChildAt(i);
if ((child instanceof ViewGroup)) {
printViews((ViewGroup) child, buf, level+1);
} else {
indent(buf, level+1);
buf.append(child.getClass().getName());
buf.append(" id:"+child.getId());
buf.append("\n");
}
}
return buf.toString();
}
private static void indent(StringBuffer buf, int level) {
for (int i = 0; i < level; i++) {
buf.append(" ");
}
}
fun ViewGroup.getAllChildren(): List<View> {
val children = ArrayList<View>()
for (i in 0 until this.childCount) {
children.add(this.getChildAt(i))
}
return children
}
fun ViewGroup.getAllChildren():列表{
val children=ArrayList()
for(在0中输入i,直到此.childCount){
添加(this.getChildAt(i))
}
返回儿童
}
适用于使用androidx和kotlin的患者
1-使用forEach{}
如果要遍历所有子视图,可以在任何视图组中使用预定义的kotlin扩展名forEach
。例如:
yourViewGroup.forEach{childView->
//对这个childView做些什么
}
2-在视图组中使用.children.toList
返回子视图列表
要返回视图列表
,可以使用函数子视图
返回序列
,然后使用toList()
将其转换为列表。示例:
val yourChildViewsList:List=yourViewGroup.children.toList()
只要一个视图组
封装了另一个视图组
和多个子视图,您的代码就保证在结果集中有重复项。我将让您自己去弄清楚原因。您很接近了,尽管结果中存在所有视图,但它也包含重复项。也许这就是您得到的结果?;)这段代码不会有很多视图组重复吗?因为viewArrayList.add(v)(表示视图组)在每次迭代中都会被调用。比