SwipeRefreshLayout setRefreshing()最初没有显示指标

我有一个非常简单的布局,但是当我在片段的onActivityCreated()中调用setRefreshing(true)时,它不会最初显示。

它只显示当我做拉刷新。 任何想法,为什么最初没有显示?

片段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 } } 

面临同样的问题。 我的解决scheme

 mSwipeRefreshLayout.post(new Runnable() { @Override public void run() { mSwipeRefreshLayout.setRefreshing(true); } }); 

请参阅Volodymyr Baydalka的回答。

这些是旧的解决方法。

过去在早期版本的android.support.v4 ,但从版本21.0.0开始,它不工作,仍然存在与2014年12月10日至12日发布的android.support.v4:21.0.3是原因。

当在setRefreshing(true)之前调用setRefreshing(true)时,SwipeRefreshLayout指示符不会出现。

解决方法:

调用SwipeRefreshLayout上的setProgressViewOffset() ,导致立即调用SwipeRefreshLayout.onMeasure()的布局的圆视图SwipeRefreshLayout.onMeasure()

 mSwipeRefreshLayout.setProgressViewOffset(false, 0, (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, getResources().getDisplayMetrics())); mSwipeRefreshLayout.setRefreshing(true); 

更新更好的解决方法

由于方向更改时操作栏可能会变薄,或者您已经手动设置了操作栏大小。 我们从这个视图的顶部以像素为单位设置偏移,在成功的轻扫手势之后,进度微调器应该重置为当前的操作栏大小。

 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)); 

更新2014年11月20日

如果视图开始后,您的应用显示SwipeRefreshLayout并不是非常重要。 您可以使用处理程序或任何您想要的方式将其发布到将来的某个时间。

举个例子。

 handler.postDelayed(new Runnable() { @Override public void run() { mSwipeRefreshLayout.setRefreshing(true); } }, 1000); 

或者像Volodymyr Baydalka的回答中提到的那样。

这是Android问题跟踪器中的问题。 请注意,让他们知道我们需要修理。

我的解决scheme是重写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); } }); 

基于Volodymyr Baydalka的回答 ,这只是一个小小的想法,可以帮助您保持代码清洁。 它值得一个post,我相信:一旦bug被修复,你将能够很容易地恢复从发布到直接方法调用的行为。

编写一个实用程序类,如:

 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); } }); } } 

在你的代码中,通过Utils.setRefreshing(mSwipeContainer, isRefreshing)replacemSwipeContainer.setRefreshing(isRefreshing) :现在只要修复了一个bug,即Utils类,代码中只有一个点需要修改。 该方法也可以内联(并从Utils删除)。

通常没有明显的视觉差异。 请记住,挂起的刷新可以使您的旧Activity实例保持ActivitySwipeRefreshLayout在其视图层次结构中保留SwipeRefreshLayout 。 如果这是一个问题,请调整使用WeakReference的方法,但通常情况下,您不会阻塞UI线程,因此延迟gc只需几毫秒。

你也可以在setRefreshing之前调用这个方法。

  swipeRefreshLayout.measure(View.MEASURED_SIZE_MASK,View.MEASURED_HEIGHT_STATE_SHIFT); swipeRefreshLayout.setRefreshing(true); 

它为我工作。

我用AppCompat库com.android.support:appcompat-v7:21.0.3 ,使用相同的方法,它的工作。 所以,你更新那个库的版本。

build议: 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> 

除了Volodymyr Baydalka之外,还使用以下代码:

 swipeContainer.post(new Runnable() { @Override public void run() { swipeContainer.setRefreshing(false); } }); 

解释我实现了Volodymyr Baydalka(使用片段)给出的解决scheme,但是在swipeReferesh开始之后,即使调用swipeContainer.setRefreshing(false);也永远不会消失swipeContainer.setRefreshing(false); 所以不得不执行上面给出的代码来解决我的问题。 任何更多的想法,为什么发生这是最受欢迎。

问候,

'com.android.support:appcompat-v7:22.2.1'

@ niks.stack回应他的回答,我会在onLayout()完成后显示进度轮。 当我在onMeasure()之后直接使用它时,它不会onLayout()一些偏移量,但在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; } } 

我的解决scheme(不支持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); 

即时通讯使用'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创build一个新的控件和派生器。 如果激活刷新,则覆盖OnMeasure函数并再次切换刷新。 我在一个xamarin项目中使用这个解决scheme,它运作良好。 这里有一些示例C#代码:

 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; } } } }