我该如何解决 SwipeRefreshLayout 的这种不当行为

How can I fix this misbehavior of SwipeRefreshLayout

我正在尝试实现下拉刷新,我正在使用 SwipeRefreshLayout。但它出现故障。

当我向下拉时,SwipeRefreshLayout 会按原样向下拉,但是一旦我移开手,它就会跳回到 RecyclerView 中第一个项目的顶部。加载程序的一半隐藏在工具栏后面,另一半在 recyclerview 的第一个项目顶部可见。再往下拉就不行了

我的布局

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="android.studio@android.com"/>

</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>

样式 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>

请问这是什么问题,我该如何解决?

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


}


}

你能在 MainActivity.java 的 onCreated 方法上试试这个吗?基本上我只是将工具栏的引用放在 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);
}

还有,你的content_main.xml,你能试试用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>

这之后我就没主意了。除非你愿意尝试使用 Fragments,这是我通常使用的,到目前为止它运行良好。