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

时间:2014-11-11 06:11:33

标签: android swiperefreshlayout

我的布局非常简单但是当我在片段的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
    }
}

14 个答案:

答案 0 :(得分:303)

面对同样的问题。我的解决方案 -

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

答案 1 :(得分:100)

请参阅Volodymyr Baydalka的答案。

这些是旧的解决方法。

过去曾在早期版本的android.support.v4上工作,但从版本21.0.0开始,它不起作用,但仍然存在于{strong> 2014年12月10日至12日发布的android.support.v4:21.0.3 ,这就是原因。

setRefreshing(true)

之前调用SwipeRefreshLayout.onMeasure()时,不会显示SwipeRefreshLayout指示符

解决方法:

SwipeRefreshLayout上调用setProgressViewOffset()会导致布局的圆圈视图无效,导致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问题跟踪器中的issue。请用它来表示我们需要修复它。

答案 2 :(得分:46)

我的解决方案是覆盖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;
        }
    }
}

答案 3 :(得分:20)

mRefreshLayout.getViewTreeObserver()
                .addOnGlobalLayoutListener(
                        new ViewTreeObserver.OnGlobalLayoutListener() {
                            @Override
                            public void onGlobalLayout() {
                                mRefreshLayout
                                        .getViewTreeObserver()
                                        .removeGlobalOnLayoutListener(this);
                                mRefreshLayout.setRefreshing(true);
                            }
                        });

答案 4 :(得分:14)

使用Android支持库24.2.0,问题应该已经解决了! https://developer.android.com/topic/libraries/support-library/revisions.html#24-2-0-bugfixes

答案 5 :(得分:4)

基于Volodymyr Baydalka's answer,这只是一个小小的想法,可以帮助您保持代码清洁。它应该得到一个帖子我相信:一旦修复了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);
            }
        });
    }
}

在您的代码中用mSwipeContainer.setRefreshing(isRefreshing)代替Utils.setRefreshing(mSwipeContainer, isRefreshing):现在,只要修复了错误Utils类,代码中只需要更改一个点。该方法也可以内联(并从Utils中删除)。

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

答案 6 :(得分:2)

你也可以在setRefreshing ..

之前调用这个方法
=IF(ISERROR(DATEDIF(RC[-16],R3C23,""M"")<=12),0,RC[-1])

对我而言。

答案 7 :(得分:1)

我使用了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>

答案 8 :(得分:1)

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

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

<强>解释 我实现了Volodymyr Baydalka给出的解决方案(使用片段)但是在swipeReferesh启动后它甚至在调用swipeContainer.setRefreshing(false);时也没有消失 所以必须实现上面给出的代码解决了我的问题。 更多的想法为什么会发生这种情况是最受欢迎的。

此致

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

答案 9 :(得分: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;
    }
}

答案 10 :(得分:0)

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

答案 11 :(得分:0)

我正在使用&#39; com.android.support:appcompat-v7:23.1.1&#39;

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

之前我在swipeRefreshLayout.setRefreshing(true);方法中使用了getData(),所以它不起作用。 我不知道为什么它不在内部方法。

虽然我在片段中只使用了swipeRefreshLayout.setRefreshing(true);一次。

答案 12 :(得分:0)

试试这个

mSwipeRefreshLayout.setNestedScrollingEnabled(真);

答案 13 :(得分:-1)

另一种解决方法是从SwipeRefreshLayout创建一个新控件和派生程序。如果激活刷新,则覆盖OnMeasure功能并再次切换刷新。我在xamarin项目中使用此解决方案,效果很好。这里有一些示例C#-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;
            }
        }
    }
}