вторник, 16 апреля 2013 г.

Android: настоящий wrap_content по ширине для ListView

По умолчанию список (ListView) в Android растягивается на всю ширину контейнера. Иногда это бывает не слишком удобно и хочется сделать так, чтобы он занимал ширину строго по содержимому. Как же быть?

Начинающий разработчик воскликнет: "Элементарно! Выставим для ширины значение "wrap_content" и все станет шоколадно!" Я сегодня сказал так же. И даже сделал. Но ничего не сработало.

Как обычно ответ нашелся на stack overflow. Самый популярный ответ говорил, что ничего сделать нельзя. Ведь элементов списка может быть несколько миллионов и на вычисление ширины может уйти несколько часов. Но если промотать ветку до конца, то там обнаружится вполне себе рабочее решение, которое отлично работает для небольшого списка. Единственное, что мне там не понравилось - так это не очень удобные параметры для вызова извне. Поэтому я доработал код до обертки, которую удобно вызывать:
public class ViewUtils {
    private static int getWidestView(Context context, Adapter adapter) {
        int maxWidth = 0;
        View view = null;
        FrameLayout fakeParent = new FrameLayout(context);
        for (int i = 0, count = adapter.getCount(); i < count; i++) {
            view = adapter.getView(i, view, fakeParent);
            view.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
            int width = view.getMeasuredWidth();
            if (width > maxWidth) {
                maxWidth = width;
            }
        }
        return maxWidth;
    }

    public static void setListViewWidthByContent(ListView listView) {
        listView.getLayoutParams().width = (int) (getWidestView(listView.getContext(),
                listView.getAdapter()) * 1.05);
    }
}

2 комментария:

Евгений Василенко комментирует...

У меня вопрос насчёт того, когда этот метод вызвать?

vylgin комментирует...

Большое спасибо за этот трюк!