Ответ 1
Столкнулся с той же проблемой. Мое решение -
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
});
У меня очень простой макет, но когда я вызываю setRefreshing(true)
в onActivityCreated()
моего фрагмента, он не отображается первоначально.
Это только показывает, когда я делаю попытку для обновления. Любые идеи, почему он не отображается вначале?
Фрагмент xml:
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
</RelativeLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
Код фрагмента:
public static class LinkDetailsFragment extends BaseFragment implements SwipeRefreshLayout.OnRefreshListener {
@InjectView(R.id.swipe_container)
SwipeRefreshLayout mSwipeContainer;
public static LinkDetailsFragment newInstance(String subreddit, String linkId) {
Bundle args = new Bundle();
args.putString(EXTRA_SUBREDDIT, subreddit);
args.putString(EXTRA_LINK_ID, linkId);
LinkDetailsFragment fragment = new LinkDetailsFragment();
fragment.setArguments(args);
return fragment;
}
public LinkDetailsFragment() {
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mSwipeContainer.setOnRefreshListener(this);
mSwipeContainer.setColorScheme(android.R.color.holo_blue_bright,
android.R.color.holo_green_light,
android.R.color.holo_orange_light,
android.R.color.holo_red_light);
mSwipeContainer.setRefreshing(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.fragment_link_details, container, false);
ButterKnife.inject(this, rootView);
return rootView;
}
@Override
public void onRefresh() {
// refresh
}
}
Столкнулся с той же проблемой. Мое решение -
mSwipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
});
Это старые обходные пути.
Это использовалось для более ранней версии android.support.v4
, но из версии 21.0.0 она не работает и все еще существует с android.support.v4:21.0.3
, выпущенной в 10-12 декабря 2014 года и это причина.
Индикатор SwipeRefreshLayout не появляется, когда setRefreshing(true)
вызывается перед SwipeRefreshLayout.onMeasure()
Обход проблемы:
вызывая setProgressViewOffset()
на SwipeRefreshLayout
, который отменяет кругное представление макета, вызывающее немедленное вызов SwipeRefreshLayout.onMeasure()
.
mSwipeRefreshLayout.setProgressViewOffset(false, 0,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics()));
mSwipeRefreshLayout.setRefreshing(true);
ОБНОВЛЕНИЕ Улучшение обходного пути
Потому что панель действий может стать тоньше при изменении ориентации или вручную задать размер панели действий. Мы устанавливаем смещение в пикселях от вершины этого представления, при котором счетчик прогресса должен прибыть в reset после успешного жестового перехода к текущему размеру панели действий.
TypedValue typed_value = new TypedValue();
getActivity().getTheme().resolveAttribute(android.support.v7.appcompat.R.attr.actionBarSize, typed_value, true);
mSwipeRefreshLayout.setProgressViewOffset(false, 0, getResources().getDimensionPixelSize(typed_value.resourceId));
ОБНОВЛЕНИЕ 20 ноября 2014 года
Если вам не очень важно, чтобы ваше приложение отображало SwipeRefreshLayout после запуска представления. Вы можете просто опубликовать его в любое время в будущем, используя обработчики или любую вещь, которую вы хотите.
в качестве примера.
handler.postDelayed(new Runnable() {
@Override
public void run() {
mSwipeRefreshLayout.setRefreshing(true);
}
}, 1000);
или как упоминалось в ответе Владимира Байдалки.
Вот issue в трекере по проблеме проблем с Android. Пожалуйста, поддержите его, чтобы показать им, что нам нужно, чтобы это было исправлено.
Мое решение - переопределить SwipeRefreshLayout
:
public class MySwipeRefreshLayout extends SwipeRefreshLayout {
private boolean mMeasured = false;
private boolean mPreMeasureRefreshing = false;
public MySwipeRefreshLayout(final Context context) {
super(context);
}
public MySwipeRefreshLayout(final Context context, final AttributeSet attrs) {
super(context, attrs);
}
@Override
public void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!mMeasured) {
mMeasured = true;
setRefreshing(mPreMeasureRefreshing);
}
}
@Override
public void setRefreshing(final boolean refreshing) {
if (mMeasured) {
super.setRefreshing(refreshing);
} else {
mPreMeasureRefreshing = refreshing;
}
}
}
mRefreshLayout.getViewTreeObserver()
.addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
mRefreshLayout
.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
mRefreshLayout.setRefreshing(true);
}
});
В библиотеке поддержки Android 24.2.0 проблема должна быть решена! https://developer.android.com/topic/libraries/support-library/revisions.html#24-2-0-bugfixes
Основываясь на ответе Владимира Байдалки, это всего лишь небольшая идея, которая поможет вам сохранить код чистым. Он заслуживает того, что я верю: вы сможете легко отменить поведение при отправке на прямой вызов метода после исправления ошибки.
Напишите класс утилиты, например:
public class Utils
{
private Utils()
{
}
public static void setRefreshing(final SwipeRefreshLayout swipeRefreshLayout, final boolean isRefreshing)
{
// From Guava, or write your own checking code
checkNonNullArg(swipeRefreshLayout);
swipeRefreshLayout.post(new Runnable()
{
@Override
public void run()
{
swipeRefreshLayout.setRefreshing(isRefreshing);
}
});
}
}
В коде замените mSwipeContainer.setRefreshing(isRefreshing)
на Utils.setRefreshing(mSwipeContainer, isRefreshing)
: теперь только одна точка в коде должна быть изменена после исправления ошибки, класса Utils
. Затем этот метод также может быть вложен (и удален из Utils
).
Обычно не будет заметной визуальной разницы. Имейте в виду, что ожидающее обновление может поддерживать ваши старые экземпляры Activity
, удерживая SwipeRefreshLayout
в своих иерархиях представлений. Если это вызывает беспокойство, настройте метод на использование WeakReference
s, но обычно вы не блокируете поток пользовательского интерфейса в любом случае и, таким образом, задерживаете gc только на пару миллисекунд.
Также вы можете вызвать этот метод до setRefreshing..
swipeRefreshLayout.measure(View.MEASURED_SIZE_MASK,View.MEASURED_HEIGHT_STATE_SHIFT);
swipeRefreshLayout.setRefreshing(true);
Это работает для меня.
Я использовал AppCompat Library com.android.support:appcompat-v7:21.0.3
, используя тот же подход, и он сработал. Таким образом, вы обновляете версию этой библиотеки.
Совет: RelativeLayout
не поддерживает ориентацию, это атрибут для LinearLayout
.
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ViewGroup view = (ViewGroup) inflater.inflate(R.layout.license_fragment,
container, false);ButterKnife.inject(this, view);
// Setting up Pull to Refresh
swipeToRefreshLayout.setOnRefreshListener(this);
// Indicator colors for refresh
swipeToRefreshLayout.setColorSchemeResources(R.color.green,
R.color.light_green);
}
Формат XML:
<android.support.v4.widget.SwipeRefreshLayout>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_margin_vertical"
android:paddingTop="@dimen/activity_margin_vertical">
<!-- Content -->
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
В дополнение к Владимиру Байдалке также используйте следующий код:
swipeContainer.post(new Runnable() {
@Override
public void run() {
swipeContainer.setRefreshing(false);
}
});
Объяснение
Я реализовал решение, данное Владимиром Байдалкой (используя фрагменты), но после того, как swipeReferesh запустил его, он никогда не исчезал даже при вызове swipeContainer.setRefreshing(false);
поэтому пришлось реализовать приведенный выше код, который решил мою проблему.
больше идей, почему это происходит, приветствуются.
Привет,
'com.android.support:appcompat-v7:22.2.1'
@niks.stack В ответ на его ответ я покажу следующее колесо после onLayout()
. Когда я использовал его непосредственно после onMeasure()
, он не соблюдал некоторые смещения, но использовал его после onLayout()
.
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
if (!mLaidOut) {
mLaidOut = true;
setRefreshing(mPreLayoutRefreshing);
}
}
@Override
public void setRefreshing(boolean refreshing) {
if (mLaidOut) {
super.setRefreshing(refreshing);
} else {
mPreLayoutRefreshing = refreshing;
}
}
Мое решение (без поддержки v7) -
TypedValue typed_value = new TypedValue();
getTheme().resolveAttribute(android.R.attr.actionBarSize, typed_value, true);
swipeLayout.setProgressViewOffset(false, 0, getResources().getDimensionPixelSize(typed_value.resourceId));
if(!swipeLayout.isEnabled())
swipeLayout.setEnabled(true);
swipeLayout.setRefreshing(true);
Im using 'com.android.support:appcompat-v7:23.1.1'
swipeRefreshLayout.post(new Runnable() {
@Override
public void run() {
swipeRefreshLayout.setRefreshing(true);
getData();
}
});
ранее я использовал swipeRefreshLayout.setRefreshing(true);
внутри getData()
, поэтому он не работал.
Я не знаю, почему его не работает внутри метода.
Хотя я использовал swipeRefreshLayout.setRefreshing(true);
только один раз в своем фрагменте.
Другим обходным решением является создание нового элемента управления и создание из SwipeRefreshLayout. Переопределите функцию OnMeasure и снова включите обновление, если обновление активировано. Я использую это решение в проекте xamarin, и он работает хорошо. Здесь пример С# -Code:
class MySwipeRefreshLayout : SwipeRefreshLayout
{
/// <summary>
/// used to indentify, if measure was called for the first time
/// </summary>
private bool m_MeasureCalled;
public MvxSwipeRefreshLayout(Context context, IAttributeSet attrs)
: base(context, attrs)
{
}
public MvxSwipeRefreshLayout(Context context)
: base(context)
{
}
public override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
if (!m_MeasureCalled)
{
//change refreshing only one time
m_MeasureCalled = true;
if (Refreshing)
{
Refreshing = false;
Refreshing = true;
}
}
}
}