Про новый SwipeRefreshLayout из библиотеки Android support на Хабре уже писали, да и Google любезно выдаёт множество ссылок на подобные примеры. Их всех объединяет одно — в SwipeRefreshLayout добавляется единственное TextView или ListView, и через минуту разработчик с умилением глядит на работающую анимацию. А если нам интерфейс чуть посложнее надо?
Итак, у нас есть Activity с двумя элементами: сверху — панель фильтра, снизу — некое View (лишние теги удалены):
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <fragment android:layout_width="match_parent" android:layout_height="wrap_content" /> <com.mycompany.MyView android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout>
Нам всего-то нужно заменить LinearLayout на SwipeRefreshLayout. Точнее, просто заменить не получится — SwipeRefreshLayout позволяет иметь только один вложенный элемент. Давайте просто обернём LinearLayout в SwipeRefreshLayout:
<android.support.v4.widget.SwipeRefreshLayout android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <fragment android:layout_width="match_parent" android:layout_height="wrap_content" /> <com.mycompany.MyView android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </android.support.v4.widget.SwipeRefreshLayout>
Запускаем — работает! Правда, как-то странно работает: индикатор обновления то не появляется, то пропадает.
Материмся, гуглим, изучаем опыт предыдущих поколений. Оказывается, в SwipeRefreshLayout что попало класть нельзя. ScrollView можно, GridView можно, ListView можно, а больше ничего и нельзя. ListView и GridView нам совсем не подходят, а вот ScrollView можно попробовать. Оборачиваем наш многострадальный LinearLayout в ScrollView:
<android.support.v4.widget.SwipeRefreshLayout android:layout_width="match_parent" android:layout_height="match_parent" > <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <fragment android:layout_width="match_parent" android:layout_height="wrap_content" /> <com.mycompany.MyView android:layout_width="match_parent" android:layout_height="match_parent" /> </LinearLayout> </ScrollView> </android.support.v4.widget.SwipeRefreshLayout>
Обращаем внимание — Lint тут же требует изменить android:layout_height с match_parent на wrap_content у вложенных в ScrollView элементов.
Запускаем, и… видим только панель фильтра. А где же нижний View? А нет его. Точнее, он есть, но мы его не видим. Раньше LinearLayout растягивал его на всё свободное пространство благодаря match_parent, но теперь-то мы внутри ScrollView! А ScrollView потому и ScrollView, что никого внутри себя растягивать не собирается, потому что его содержимое может выходить за пределы самого ScrollView.
Выход — наше нижнее MyView должно само себя посчитать, то есть определить свою высоту, основываясь на высоте родительского Activity:
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ViewParent llp = getParent(); // LinearLayout View swp = (View) llp.getParent(); // ScrollView View srlp = (View) swp.getParent(); // SwipeRefreshLayout int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); int measuredHeight = srlp.getMeasuredHeight(); int orientation = getResources().getConfiguration().orientation; if (orientation == Configuration.ORIENTATION_PORTRAIT) { View filter = swp.findViewById(R.id.frFilter); int fh = filter.getMeasuredHeight(); measuredHeight -= fh; } setMeasuredDimension(measuredWidth, measuredHeight); }
Очень некрасивое решение. Зато работает. Гламурных всем анимаций!
ссылка на оригинал статьи http://habrahabr.ru/post/256947/
Добавить комментарий