Search code examples
androidandroid-appcompatandroid-recyclerviewswiperefreshlayout

SwipeRefreshLayout is hidden on empty RecyclerView


I have a Fragment with a SwipeRefreshLayout and then RecyclerView as child. When the Fragment is committed, it starts talking to a server in order to retrieve some data and populate a CustomAdapter which will serve the RecyclerView.

The user can refresh the content by swiping down or pressing a button on the ActionBar. In the latter case, I manually call swipeRefreshLayout.setRefreshing(true). So no troubles until now.

The problem arises when I manually call the refresh state during the first loading of the RecyclerView (onStart()). The progress indicator is not showed up and I assume because the RecyclerView is still empty since it requires some seconds to retrieve all the data...

I leave you some code.

Fragment code:

public class MyFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

        View mView = inflater.inflate(R.layout.fragment_stop, container, false);
        mRecyclerView = (RecyclerView) mView.findViewById(R.id.recyclerView1);
        mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),
             DividerItemDecoration.VERTICAL_LIST));
        mRecyclerView.setHasFixedSize(true);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());

       //SwipeRefreshLayout retrieved and  configured
       swipeLayout = (SwipeRefreshLayout) mView.findViewById(R.id.swipe_container);
       swipeLayout.setOnRefreshListener(this);
       swipeLayout.setColorSchemeResources(
            R.color.primaryColor,
            R.color.cyan_500,
            R.color.light_green_500,
            R.color.amber_500);

        return mView;


     }

    ...
    @Override
        public void onStart() {
            super.onStart();
            executeSchedule(); //First execution and data loading.
        }
        ...

    @Override
    public void onRefresh() {
        executeSchedule();
    }
    ...
    public void executeSchedule() {
        new Schedule().execute();
    }



    private class Schedule extends AsyncTask<Void, Void, Void> {

        ...
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            if(!swipeLayout.isRefreshing()) {
                swipeLayout.setRefreshing(true); //set refresh state
            }
        }

        @Override
        protected Void doInBackground(Void... params) {
        ...
        }

        @Override
        protected void onPostExecute(Void result) {
            adap = new CustomAdapter(getActivity(), ...);
            mRecyclerView.setAdapter(adap);
            swipeLayout.setRefreshing(false);
        }

}

XML code:

<FrameLayout 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">

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <TextView
            android:id="@+id/section_label"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>

        <android.support.v4.widget.SwipeRefreshLayout
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/swipe_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/recyclerView1"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingLeft="4dp"
                android:paddingRight="4dp"
                android:paddingBottom="2dp"
                android:layout_marginTop="5dp"
                android:divider="#e0e0e0"
                tools:context=".MyFragment" />

        </android.support.v4.widget.SwipeRefreshLayout>
    </RelativeLayout>
</FrameLayout>

What would be the best practice to address this situation? Adding a second dummy SwipeRefreshLayout? Immediately force an empty adapter?


Solution

  • You need to call measure method before call setRefreshing(true).
    Take a look at: SwipeRefreshLayout no animation on fragment creation. Maybe it can be helpful.