Перечислять / повторять все представления в Activity? - PullRequest
15 голосов
/ 02 февраля 2011

Есть ли способ перебрать все представления в вашей активности? Что-то вроде:

<pre>Iterator it = getViewIterator(); ...

Это вообще существует?

Ответы [ 7 ]

17 голосов
/ 02 февраля 2011

Если у вас есть все ваши представления в LinearLayout или другом container, который расширяет ViewGroup, вы можете использовать функции getChildCount() и getChildAt(int) и выполнять итерацию по всем
содержащимся представлениям.

Надеюсь, это поможет.

8 голосов
/ 10 июля 2013

Предполагая, что под "всеми представлениями в вашей деятельности" вы подразумеваете каждое представление в иерархии, в Android нет такого Iterator или чего-либо такого, что позволяло бы вам выполнять итерации по всем представлениям.

ViewGroup s имеют getChildCount и getChildAt методы, но они о прямых потомках ViewGroup. Итак, вам нужно будет посетить каждого ребенка и проверить, является ли он ViewGroup, и так далее. Короче говоря, я хотел, чтобы такая функция находила все представления, которые соответствуют определенному тегу (findViewWithTag возвращает только первое). Вот класс, который может повторять все представления:

public class LayoutTraverser {

    private final Processor processor;


    public interface Processor {
        void process(View view);
    }

    private LayoutTraverser(Processor processor) {
        this.processor = processor;
    }

    public static LayoutTraverser build(Processor processor) {
        return new LayoutTraverser(processor);
    }

    public View traverse(ViewGroup root) {
        final int childCount = root.getChildCount();

        for (int i = 0; i < childCount; ++i) {
            final View child = root.getChildAt(i);

            if (child instanceof ViewGroup) {
                traverse((ViewGroup) child);
            }
        }
        return null;
    }
}

Используйте это так:

LayoutTraverser.build(new LayoutTraverser.Processor() {
  @Override
  public void process(View view) {
    // do stuff with the view
  }
}).traverse(viewGroup);
1 голос
/ 14 апреля 2016

Вот мой пример, основанный на ответе Гарри Джой .Он перебирает все иерархии родительского элемента ViewGroup, чтобы увидеть, является ли какое-либо из представлений где-либо внутри него Button:

private boolean doesViewGroupContainButton(ViewGroup parentView) {

        int numChildViews = parentView.getChildCount();
        for (int i = 0; i < numChildViews; i++) {
            View childView = parentView.getChildAt(i);
            if (childView instanceof ViewGroup) {
                if (doesViewContainButton((ViewGroup)childView)) {
                    return true;
                }
            }
            else if (childView instanceof Button) {
                return true;
            }
        }
        return false;

    }
1 голос
/ 02 февраля 2011

Активность Обычно содержит один основной контейнер макетов, в который помещаются все другие виды.Используя ссылку на основной макет контейнера.Пройдите через его дочерний элемент (используйте getChild (postion), getchildcount () и т. Д.).и если какой-либо дочерний элемент сам по себе является контейнером, примените к нему ту же функцию. Это похоже на обход древовидной структуры

0 голосов
/ 14 мая 2019

RX Java решение

    public static Observable<View> iterate(@NonNull View root) {
        return Observable.create(emitter -> {
            iterate(root, emitter);
            emitter.onComplete();
        });
    }

    private static void iterate(@NonNull View view, @NonNull ObservableEmitter<View> emitter) {
        emitter.onNext(view);
        if (view instanceof ViewGroup) {
            ViewGroup viewGroup = (ViewGroup) view;
            for (int i = 0; i < viewGroup.getChildCount(); i++) {
                iterate(viewGroup.getChildAt(i), emitter);
            }
        }
    }
0 голосов
/ 23 марта 2017

Если вы хотите избежать уродливости для (int i = 0; ....), вы можете использовать статическую оболочку

public class Tools
{
    public static Iterable<View> getChildViews(final ViewGroup view)
    {
        return new Iterable<View>()
        {
            int i = -1;

            @NonNull
            @Override
            public Iterator<View> iterator()
            {
                return new Iterator<View>()
                {
                    int i = -1;
                    @Override
                    public boolean hasNext()
                    {
                        return i < view.getChildCount();
                    }

                    @Override
                    public View next()
                    {
                        return view.getChildAt(++i);
                    }
                };
            }

        };
    }
}

и использовать ее так же, как

for (View view :  Tools.getChildViews(viewGroup))

конечно, это немного менее эффективно, так как вы создаете новый объект Iteratable при каждой итерации, но вы можете использовать этот более эффективный алгоритм, если хотите.

0 голосов
/ 02 февраля 2011

Если вам действительно нужен итератор, в API нет ничего подобного. Вам придется написать свою собственную, основанную на логике, которую предлагают Гарри Джой и Джаванатор.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...