X09
X09

Reputation: 3956

How can I fix this misbehavior of SwipeRefreshLayout

I'm trying to implement pull down to refresh and I am using SwipeRefreshLayout. But it's malfunctioning.

When I pull down, the SwipeRefreshLayout pulls down as it should but as soon as I remove my hand, it jumps back to the top of the first item in the RecyclerView. Halve of the loader hides behind the toolbar and the other half is visible on top the first item in recyclerview. If I pull down again, it doesn't work.

enter image description here

My Layouts

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

    <include
        layout="@layout/app_bar_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer"/>

</android.support.v4.widget.DrawerLayout>

app_bar_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:context="com.example.myapp.MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay"/>

    </android.support.design.widget.AppBarLayout>

    <include layout="@layout/content_main"
        />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        android:src="@android:drawable/ic_dialog_email"/>

</android.support.design.widget.CoordinatorLayout>

nav_header_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="@dimen/nav_header_height"
              android:background="@drawable/side_nav_bar"
              android:gravity="bottom"
              android:orientation="vertical"
              android:paddingBottom="@dimen/activity_vertical_margin"
              android:paddingLeft="@dimen/activity_horizontal_margin"
              android:paddingRight="@dimen/activity_horizontal_margin"
              android:paddingTop="@dimen/activity_vertical_margin"
              android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:src="@android:drawable/sym_def_app_icon"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="Android Studio"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="[email protected]"/>

</LinearLayout>

content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/swipe_refrsh"
    xmlns:android="http://schemas.android.com/apk/res/android">

        <android.support.v7.widget.RecyclerView
        android:id="@+id/pews_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:scrollbarFadeDuration="5000"/>

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

MainActivity

public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    private final String TAG = "MainActivity";
    private AlertDialog internetDialog;

   private static final String GET_URLL = "https:/johnie.com/page/json";


    //Creating a list of pewss
    private List<NewsItems> mNewsItemsList;

    //Creating Views
    private RecyclerView recyclerView;
    private RecyclerView.Adapter adapter;
    private ProgressDialog mProgressDialog;
    SwipeRefreshLayout mSwipeRefreshLayout;



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "onCreate called");

        //Initializing Views
        recyclerView = (RecyclerView) findViewById(R.id.pews_recycler);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(layoutManager);
        mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refrsh);
        mSwipeRefreshLayout.setColorSchemeColors(android.R.color.holo_green_light,
                android.R.color.holo_green_dark,
                android.R.color.holo_purple,
                android.R.color.holo_red_dark,
                android.R.color.holo_orange_dark);


        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {

                refreshData();
            }
        });

        adapter = new NewsAdapter(mNewsItemsList, this);

        recyclerView.setAdapter(adapter);

Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
        fab.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                        .setAction("Action", null).show();
            }
        });

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();

        NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
        navigationView.setNavigationItemSelectedListener(this);



    }

    private void showDialog() {
        internetDialog = new AlertDialog.Builder(MainActivity.this)
                ...
    }



    private void refreshData(){


        Log.d(TAG, "RefreshData called");

        //Creating a json request
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(GET_URL,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, "onResponse called");

                        //calling method to parse json array
                        parseData(response);

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {


                    }
                });

        //Creating request queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);

        //Adding request to the queue
        requestQueue.add(jsonArrayRequest);

    }

    //This method will get data from the web api

    private void getData(){


        Log.d(TAG, "getData called");
        //Showing progress dialog
        mProgressDialog = new ProgressDialog(MainActivity.this);
        mProgressDialog.setCancelable(false);
        mProgressDialog.setMessage(this.getResources().getString(R.string.load_pews));
        mProgressDialog.show();


        //Creating a json request
        JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(GET_URL,
                new Response.Listener<JSONArray>() {
                    @Override
                    public void onResponse(JSONArray response) {
                        Log.d(TAG, "onResponse called");
                        //Dismissing the progress dialog
                        if (mProgressDialog != null) {
                            mProgressDialog.hide();
                        }
                        /*progressDialog.dismiss();*/


                        //calling method to parse json array
                        parseData(response);

                    }
                },
                new Response.ErrorListener() {
                    @Override
                    public void onErrorResponse(VolleyError error) {
                        if (mProgressDialog != null) {
                            mProgressDialog.hide();

                            final  AlertDialog.Builder sthWrongAlert = new AlertDialog.Builder(MainActivity.this);
                            sthWrongAlert.setCancelable(false);
                            sthWrongAlert.setMessage(R.string.sth_wrongme);
                            sthWrongAlert.setPositiveButton(R.string.alert_retry, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    if (!NetworkCheck.isAvailableAndConnected(MainActivity.this)) {
                                        internetDialog.show();
                                    } else {
                                        getData();
                                    }

                                }
                            });
                            sthWrongAlert.setNegativeButton(R.string.alert_cancel, new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    finish();
                                }
                            });
                            sthWrongAlert.show();
                        }

                    }
                });

        //Creating request queue
        RequestQueue requestQueue = Volley.newRequestQueue(this);

        //Adding request to the queue
        requestQueue.add(jsonArrayRequest);

    }

    //This method will parse json data
    private void parseData(JSONArray array){
        Log.d(TAG, "Parsing array");


        ...
            mNewsItemsList.add(pewsItem);


        }

        adapter.notifyItemRangeChanged(0, adapter.getItemCount());


    }


}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest package="com.example.myapp"
          xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <activity
            android:name=".PostDetails"
            android:parentActivityName=".MainActivity">

        </activity>

    </application>

</manifest>

Styles.xml

<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
    </style>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
    </style>

    <style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar"/>

    <style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Light"/>

</resources>

Styles-21

<resources>>

    <style name="AppTheme.NoActionBar">
        <item name="windowActionBar">false</item>
        <item name="windowNoTitle">true</item>
        <item name="android:windowDrawsSystemBarBackgrounds">true</item>
        <item name="android:statusBarColor">@android:color/transparent</item>
    </style>
</resources>

Please, what's the problem and how do I correct it?

Upvotes: 1

Views: 1954

Answers (2)

ads
ads

Reputation: 1723

Can you try this on the onCreated method of your MainActivity.java. Basically I just placed the referencing of the Toolbar after setContentView.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.d(TAG, "onCreate called");

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);

    //Initializing Views
    recyclerView = (RecyclerView) findViewById(R.id.pews_recycler);
    LinearLayoutManager layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);
    mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refrsh);
    mSwipeRefreshLayout.setColorSchemeColors(android.R.color.holo_green_light,
            android.R.color.holo_green_dark,
            android.R.color.holo_purple,
            android.R.color.holo_red_dark,
            android.R.color.holo_orange_dark);

    mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh() {
            refreshData();
        }
    });

    adapter = new NewsAdapter(mNewsItemsList, this);
    recyclerView.setAdapter(adapter);

    FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
    fab.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show();
        }
    });

    DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
    ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
            this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
    drawer.setDrawerListener(toggle);
    toggle.syncState();

    NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
    navigationView.setNavigationItemSelectedListener(this);
}

Also, your content_main.xml, can you try enclosing it with a FrameLayout.

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/app_bar_main">

  <android.support.v4.widget.SwipeRefreshLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/swipe_refrsh">

        <android.support.v7.widget.RecyclerView
        android:id="@+id/pews_recycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical"
        android:scrollbarFadeDuration="5000"/>

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

</FrameLayout>

I'm out of ideas after this. Unless you are willing to try and use Fragments which is what I usually use and it works fine so far.

Upvotes: 1

Nguyễn Trung Hiếu
Nguyễn Trung Hiếu

Reputation: 2032

public class MainActivity extends AppCompatActivity
    implements NavigationView.OnNavigationItemSelectedListener, SwipeRefreshLayout.OnRefreshListener {

private final String TAG = "MainActivity";
private AlertDialog internetDialog;

private static final String GET_URLL = "https:/johnie.com/page/json";


//Creating a list of pewss
private List<NewsItems> mNewsItemsList;

//Creating Views
private RecyclerView recyclerView;
private RecyclerView.Adapter adapter;
private ProgressDialog mProgressDialog;
SwipeRefreshLayout mSwipeRefreshLayout;
LinearLayoutManager layoutManager



@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    Log.d(TAG, "onCreate called");

    //Initializing Views
    recyclerView = (RecyclerView) findViewById(R.id.pews_recycler);
    layoutManager = new LinearLayoutManager(this);
    recyclerView.setLayoutManager(layoutManager);
    mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refrsh);
    adapter = new NewsAdapter(mNewsItemsList, this);
    recyclerView.setAdapter(adapter);
    addEventSwipeRefreshLayout();
}

  private void addEventSwipeRefreshLayout() {
  mSwipeRefreshLayout.setColorSchemeColors(android.R.color.holo_green_light,
            android.R.color.holo_green_dark,
            android.R.color.holo_purple,
            android.R.color.holo_red_dark,
            android.R.color.holo_orange_dark);
    mSwipeRefreshLayout.setEnabled(false);
    mSwipeRefreshLayout.setOnRefreshListener(this);

  recyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrollStateChanged(int newState) {
        }

        @Override
        public void onScrolled(int dx, int dy) {
            mSwipeRefreshLayout.setEnabled(layoutManager.findFirstCompletelyVisibleItemPosition() == 0);
        }
    });

}

 @Override
public void onRefresh() {

    mSwipeLayout.post(new Runnable() {
                          @Override
                          public void run() {
                              mSwipeLayout.setRefreshing(true);
                              (new Handler()).postDelayed(new Runnable() {
                                  @Override
                                  public void run() {
                                      refreshData()
                                  }
                              }, 500);


                          }
                      }
    );
}


private void showDialog() {
    internetDialog = new AlertDialog.Builder(MainActivity.this)
            ...
}



private void refreshData(){


    Log.d(TAG, "RefreshData called");

    //Creating a json request
    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(GET_URL,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.d(TAG, "onResponse called");

                    //calling method to parse json array
                    parseData(response);

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {


                }
            });

    //Creating request queue
    RequestQueue requestQueue = Volley.newRequestQueue(this);

    //Adding request to the queue
    requestQueue.add(jsonArrayRequest);

}

//This method will get data from the web api

private void getData(){


    Log.d(TAG, "getData called");
    //Showing progress dialog
    mProgressDialog = new ProgressDialog(MainActivity.this);
    mProgressDialog.setCancelable(false);
    mProgressDialog.setMessage(this.getResources().getString(R.string.load_pews));
    mProgressDialog.show();


    //Creating a json request
    JsonArrayRequest jsonArrayRequest = new JsonArrayRequest(GET_URL,
            new Response.Listener<JSONArray>() {
                @Override
                public void onResponse(JSONArray response) {
                    Log.d(TAG, "onResponse called");
                    //Dismissing the progress dialog
                    if (mProgressDialog != null) {
                        mProgressDialog.hide();
                    }
                    /*progressDialog.dismiss();*/


                    //calling method to parse json array
                    parseData(response);

                }
            },
            new Response.ErrorListener() {
                @Override
                public void onErrorResponse(VolleyError error) {
                    if (mProgressDialog != null) {
                        mProgressDialog.hide();

                        final  AlertDialog.Builder sthWrongAlert = new AlertDialog.Builder(MainActivity.this);
                        sthWrongAlert.setCancelable(false);
                        sthWrongAlert.setMessage(R.string.sth_wrongme);
                        sthWrongAlert.setPositiveButton(R.string.alert_retry, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (!NetworkCheck.isAvailableAndConnected(MainActivity.this)) {
                                    internetDialog.show();
                                } else {
                                    getData();
                                }

                            }
                        });
                        sthWrongAlert.setNegativeButton(R.string.alert_cancel, new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                finish();
                            }
                        });
                        sthWrongAlert.show();
                    }

                }
            });

    //Creating request queue
    RequestQueue requestQueue = Volley.newRequestQueue(this);

    //Adding request to the queue
    requestQueue.add(jsonArrayRequest);

}

//This method will parse json data
private void parseData(JSONArray array){
    Log.d(TAG, "Parsing array");


    ...
        mNewsItemsList.add(pewsItem);


    }

    adapter.notifyItemRangeChanged(0, adapter.getItemCount());


}


}

Upvotes: 0

Related Questions