android - 实现滑动以刷新布局后,回收站 View 无法正确滚动

标签 android android-recyclerview swiperefreshlayout recyclerview-layout

在实现滑动刷新 View 之前,回收器 View 运行平稳,但每当我尝试向下滚动回收器 View 时,滑动刷新会干扰并阻碍滚动运动。

这是问题的截图:

(请注意,向下滚动回收器 View 时会出现刷新布局的滑动)

enter image description here

这是我的布局 fragment :

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.v7.widget.RecyclerView
        android:id="@+id/availableTaskRecyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />
    <RelativeLayout
        android:id="@+id/progress_wheel"
        android:visibility="gone"
        tools:visibility="visible"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_horizontal|center_vertical"
        android:background="@color/transparentLoaderBackground">

        <com.pnikosis.materialishprogress.ProgressWheel
            android:layout_width="50dp"
            android:layout_height="50dp"
            wheel:matProg_barColor="@color/white"
            wheel:matProg_barWidth="1dp"
            wheel:matProg_progressIndeterminate="true"/>
    </RelativeLayout>


    <RelativeLayout
        android:id="@+id/no_available_tasks"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:visibility="gone"
        tools:visibility = "visible"
        >

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="No tasks currently available. Pull to refresh"
            android:layout_centerInParent="true"
            android:padding="16dp"
            android:gravity="center_horizontal"
            android:textSize="18sp"/>

    </RelativeLayout>

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

下面是我的 fragment 的代码:

package com.packrboy.fragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.ParseError;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.Response;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.avast.android.dialogs.fragment.SimpleDialogFragment;
import com.packrboy.R;
import com.packrboy.activities.TaskActivity;
import com.packrboy.adapters.TaskAdapter;
import com.packrboy.classes.SharedPreferenceClass;
import com.packrboy.classes.Shipment;
import com.packrboy.network.VolleySingleton;
import com.pnikosis.materialishprogress.ProgressWheel;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import static com.packrboy.extras.Keys.Shipment.KEY_CREATED_AT;
import static com.packrboy.extras.Keys.Shipment.KEY_ID;
import static com.packrboy.extras.Keys.Shipment.KEY_IN_TRANSIT_STATUS;
import static com.packrboy.extras.Keys.Shipment.KEY_ITEM_IMAGE;
import static com.packrboy.extras.Keys.Shipment.KEY_ITEM_QUANTITY;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_CITY;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_LATITUDE;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_LONGITUDE;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_POSTAL_CODE;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_ROUTE;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_STATE;
import static com.packrboy.extras.Keys.Shipment.KEY_PICKUP_STREET_NO;
import static com.packrboy.extras.Keys.Shipment.KEY_SHIPMENT_ARRAY;
import static com.packrboy.extras.urlEndPoints.KEY_ASSIGN_DELIVERY;
import static com.packrboy.extras.urlEndPoints.KEY_ASSIGN_PICKUP;
import static com.packrboy.extras.urlEndPoints.KEY_AVAILABLE;
import static com.packrboy.extras.urlEndPoints.KEY_SHIPMENT_URL;
import static com.packrboy.extras.urlEndPoints.KEY_UAT_BASE_URL_API;
import static com.packrboy.extras.Keys.Shipment.KEY_TYPE;
import static com.packrboy.extras.Keys.Shipment.KEY_SHIPMENT;
import static com.packrboy.extras.Keys.ServiceKeys.KEY_ERROR_CODE;

/**
 * Created by arindam.paaltao on 29-Jul-15.
 */
public class AvailableTaskFragment extends Fragment implements TaskAdapter.ClickListener{
    private RecyclerView mRecyclerView;
    private TaskAdapter mTaskAdapter;
    private JSONArray shipmentListArray;
    private TaskActivity activity;
    private SharedPreferenceClass preferenceClass;
    private ArrayList<Shipment> shipmentArrayList = new ArrayList<>();
    int shipmentId;
    String userId,transitStatus,requestType,streetNo,route,city,state,postalCode,imageURL,customerName,latitude,longitude,createdTime,updatedTime,itemQuantity;
    View layout;
    RelativeLayout progressWheel,noAvailableTasks;
    private SwipeRefreshLayout mSwipeRefreshLayout;

    public AvailableTaskFragment() {

    }
    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        layout = inflater.inflate(R.layout.available_task_fragment, container, false);

        mSwipeRefreshLayout = (SwipeRefreshLayout)layout.findViewById(R.id.activity_main_swipe_refresh_layout);
        preferenceClass = new SharedPreferenceClass(getActivity());
        userId = preferenceClass.getCustomerId();
        progressWheel = (RelativeLayout)layout.findViewById(R.id.progress_wheel);
        noAvailableTasks = (RelativeLayout)layout.findViewById(R.id.no_available_tasks);
        sendJsonRequest();
        mRecyclerView = (RecyclerView) layout.findViewById(R.id.availableTaskRecyclerView);
        mTaskAdapter = new TaskAdapter(getActivity(), activity);
        mRecyclerView.setAdapter(mTaskAdapter);
        mTaskAdapter.setClickListener(this);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
        mSwipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                sendJsonRequest();
            }
        });


        return layout;
    }

    public static String getRequestUrl(){
        return KEY_UAT_BASE_URL_API + KEY_SHIPMENT_URL + KEY_AVAILABLE;
    }

    public void sendJsonRequest(){
        progressWheel.setVisibility(View.VISIBLE);
        final JSONObject testObject = new JSONObject();
        try {
            testObject.put("token", preferenceClass.getAccessToken());

        } catch (JSONException e) {
            e.printStackTrace();
        }

        RequestQueue requestQueue = VolleySingleton.getsInstance().getRequestQueue();
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, getRequestUrl(), testObject, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                if (mSwipeRefreshLayout.isRefreshing()){
                    mSwipeRefreshLayout.setRefreshing(false);
                }
                progressWheel.setVisibility(View.GONE);
                Log.i("error", jsonObject.toString());
                Log.i("login", testObject.toString());
                shipmentArrayList = parseJsonResponse(jsonObject);
                mTaskAdapter.setShipmentArrayList(shipmentArrayList);

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                if (volleyError instanceof TimeoutError || volleyError instanceof NoConnectionError) {


                } else if (volleyError instanceof AuthFailureError) {

                    //TODO
                } else if (volleyError instanceof ServerError) {

                    //TODO
                } else if (volleyError instanceof NetworkError) {

                    //TODO
                } else if (volleyError instanceof ParseError) {

                    //TODO
                }

            }
        }) {
            @Override
            protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                return super.parseNetworkResponse(response);
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headers = super.getHeaders();

                if (headers == null
                        || headers.equals(Collections.emptyMap())) {
                    headers = new HashMap<String, String>();
                }

                headers.put("Cookie", preferenceClass.getCookie());
                return headers;
            }
        };
        requestQueue.add(jsonObjectRequest);
    }

    public ArrayList<Shipment> parseJsonResponse(JSONObject response) {

        ArrayList<Shipment> shipmentArrayList = new ArrayList<>();
        if (response != null && response.length() > 0) {

            try {
                shipmentListArray  = response.getJSONArray(KEY_SHIPMENT_ARRAY);
                if (shipmentListArray.length() == 0){
                    if (noAvailableTasks.getVisibility() == View.GONE)
                        noAvailableTasks.setVisibility(View.VISIBLE);
                }else {
                    if (noAvailableTasks.getVisibility() == View.VISIBLE)
                        noAvailableTasks.setVisibility(View.GONE);

                    for (int i = 0; i < shipmentListArray.length(); i++) {
                        JSONObject shipmentObject = shipmentListArray.getJSONObject(i);
                        if (shipmentObject.has(KEY_TYPE)) {
                            requestType = shipmentObject.getString(KEY_TYPE);
                            transitStatus = shipmentObject.getString(KEY_IN_TRANSIT_STATUS);
                        }
                        JSONObject shipmentDetails = new JSONObject();
                        shipmentDetails = shipmentObject.getJSONObject(KEY_SHIPMENT);

                        streetNo = shipmentDetails.getString(KEY_PICKUP_STREET_NO);
                        route = shipmentDetails.getString(KEY_PICKUP_ROUTE);
                        city = shipmentDetails.getString(KEY_PICKUP_CITY);
                        state = shipmentDetails.getString(KEY_PICKUP_STATE);
                        postalCode = shipmentDetails.getString(KEY_PICKUP_POSTAL_CODE);
                        imageURL = shipmentDetails.getString(KEY_ITEM_IMAGE);
                        latitude = shipmentDetails.getString(KEY_PICKUP_LATITUDE);
                        longitude = shipmentDetails.getString(KEY_PICKUP_LONGITUDE);
                        createdTime = shipmentDetails.getString(KEY_CREATED_AT);
                        itemQuantity = shipmentDetails.getString(KEY_ITEM_QUANTITY);
                        shipmentId = Integer.parseInt(shipmentDetails.getString(KEY_ID));


                        Shipment current = new Shipment();
                        current.setImageURL(imageURL);
                        current.setCity(city);
                        current.setCreatedTime(createdTime);
                        current.setLatitude(Double.parseDouble(latitude));
                        current.setLongitude(Double.parseDouble(longitude));
                        current.setPostalCode(postalCode);
                        current.setState(state);
                        current.setStreetNo(streetNo);
                        current.setRoute(route);
                        current.setRequestType(requestType);
                        current.setItemQuantity(itemQuantity);
                        current.setItemId(shipmentId);
                        current.setTransitStatus(transitStatus);

                        shipmentArrayList.add(current);

                    }
                }

            } catch (JSONException e) {
                e.printStackTrace();
            }

        }
        return shipmentArrayList;
    }


    public static String getAcceptRequestRequestUrl(){
        return KEY_UAT_BASE_URL_API + KEY_SHIPMENT_URL + KEY_ASSIGN_PICKUP;
    }

    public void sendAcceptRequestJsonRequest(){
        final JSONObject shipmentObject = new JSONObject();
        final JSONObject pendingTaskObject = new JSONObject();
        try {
            shipmentObject.put("packrboy_id", userId);
            shipmentObject.put("shipment_id", shipmentId);
            pendingTaskObject.put("payload", shipmentObject);
            pendingTaskObject.put("token", preferenceClass.getAccessToken());


        } catch (JSONException e) {
            e.printStackTrace();
        }

        RequestQueue requestQueue = VolleySingleton.getsInstance().getRequestQueue();
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, getAcceptRequestRequestUrl(), pendingTaskObject, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                Log.i("error", jsonObject.toString());
                Log.i("login", pendingTaskObject.toString());
                if (jsonObject.has(KEY_ERROR_CODE)){
                    try {
                        String errorCode = jsonObject.getString(KEY_ERROR_CODE);
                        if (errorCode.contentEquals("200")){
                            SimpleDialogFragment.createBuilder(getActivity(), getFragmentManager()).setTitle("Request Accepted").setMessage(R.string.pickup_request_accepted).show();
                        }
                        else {
                            SimpleDialogFragment.createBuilder(getActivity(), getFragmentManager()).setTitle("Request cannot be accepted").setMessage(R.string.pickup_request_not_allowed).show();
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                if (volleyError instanceof TimeoutError || volleyError instanceof NoConnectionError) {


                } else if (volleyError instanceof AuthFailureError) {

                    //TODO
                } else if (volleyError instanceof ServerError) {

                    //TODO
                } else if (volleyError instanceof NetworkError) {

                    //TODO
                } else if (volleyError instanceof ParseError) {

                    //TODO
                }

            }
        }) {
            @Override
            protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                return super.parseNetworkResponse(response);
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headers = super.getHeaders();

                if (headers == null
                        || headers.equals(Collections.emptyMap())) {
                    headers = new HashMap<String, String>();
                }

                headers.put("Cookie", preferenceClass.getCookie());
                return headers;
            }
        };
        requestQueue.add(jsonObjectRequest);
    }


    public static String getAcceptDeliveryRequestRequestUrl(){
        return KEY_UAT_BASE_URL_API + KEY_SHIPMENT_URL + KEY_ASSIGN_DELIVERY;
    }

    public void sendAcceptDeliveryRequestJsonRequest(){
        final JSONObject shipmentObject = new JSONObject();
        final JSONObject pendingTaskObject = new JSONObject();
        try {
            shipmentObject.put("packrboy_id", userId);
            shipmentObject.put("shipment_id", shipmentId);
            pendingTaskObject.put("payload", shipmentObject);
            pendingTaskObject.put("token", preferenceClass.getAccessToken());


        } catch (JSONException e) {
            e.printStackTrace();
        }

        RequestQueue requestQueue = VolleySingleton.getsInstance().getRequestQueue();
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST, getAcceptDeliveryRequestRequestUrl(), pendingTaskObject, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                Log.i("error", jsonObject.toString());
                Log.i("login", pendingTaskObject.toString());
                if (jsonObject.has(KEY_ERROR_CODE)){
                    try {
                        String errorCode = jsonObject.getString(KEY_ERROR_CODE);
                        if (errorCode.contentEquals("200")){
                            SimpleDialogFragment.createBuilder(getActivity(), getFragmentManager()).setTitle("Request Accepted").setMessage("Delivery request has been accepted").show();
                        }
                        else {
                            SimpleDialogFragment.createBuilder(getActivity(), getFragmentManager()).setTitle("Request cannot be accepted").setMessage("The request cannot be accepted").show();
                        }
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                }

            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                if (volleyError instanceof TimeoutError || volleyError instanceof NoConnectionError) {


                } else if (volleyError instanceof AuthFailureError) {

                    //TODO
                } else if (volleyError instanceof ServerError) {

                    //TODO
                } else if (volleyError instanceof NetworkError) {

                    //TODO
                } else if (volleyError instanceof ParseError) {

                    //TODO
                }

            }
        }) {
            @Override
            protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
                return super.parseNetworkResponse(response);
            }

            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                Map<String, String> headers = super.getHeaders();

                if (headers == null
                        || headers.equals(Collections.emptyMap())) {
                    headers = new HashMap<String, String>();
                }

                headers.put("Cookie", preferenceClass.getCookie());
                return headers;
            }
        };
        requestQueue.add(jsonObjectRequest);
    }














    @Override
    public void itemClicked(View view, int position) {
        shipmentId = shipmentArrayList.get(position).getItemId();
        if (shipmentArrayList.get(position).getRequestType().contentEquals("pickup")){
        sendAcceptRequestJsonRequest();}

        else{
            sendAcceptDeliveryRequestJsonRequest();
        }



    }
}

我还在 Activity 布局中实现了协调器布局。这是代码:

<android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <include
            layout="@layout/toolbar"
            android:id="@+id/toolbar"/>

        <android.support.design.widget.TabLayout
            android:id="@+id/sliding_tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabMode="scrollable"
            app:tabGravity="fill" />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />
</android.support.design.widget.CoordinatorLayout>

你能帮我解决这个问题吗?会有很大的帮助。提前致谢。

最佳答案

终于自己解决了。

问题出在xml布局本身。 Recycler View 应该是 SwipeToReferesh 布局中的单个子元素。

布局文件应该如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:wheel="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


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


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

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

    <com.pnikosis.materialishprogress.ProgressWheel
        android:id="@+id/progress_wheel"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:visibility="gone"
        tools:visibility="visible"
        wheel:matProg_barColor="@color/colorAccent"
        wheel:matProg_barWidth="1dp"
        wheel:matProg_progressIndeterminate="true" />


    <TextView
        android:id="@+id/no_available_tasks"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:gravity="center_horizontal|center_vertical"
        android:padding="16dp"
        android:text="No tasks currently available. Pull to refresh"
        android:textSize="18sp"
        android:visibility="gone"
        tools:visibility="visible" />
</RelativeLayout>

无需添加一些其他实用程序类或重写 SwipeToRefesh 的 canChildScrollUp() 方法。

关于android - 实现滑动以刷新布局后,回收站 View 无法正确滚动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31739182/

相关文章:

android - 如何从 Activity 警报对话框中检索多项检查选择

c# - 在 Recyclerview 中更改所选项目的背景颜色

android - SwipeRefreshLayout 中的 RecyclerView 不是 "wrap_content"

java - 使用共享首选项将项目保存在 ListView 中

android - Play商店上Android应用中的“应用权限”页面

java - Second Spinner 从不更改基于 First Spinner 的数组

android - 取消刷新后,带有 CollapsibleToobarLayout 的 SwipeRefreshLayout 不向下滚动

android - 将外部 JAR 作为外部 SDK 添加到 Android 项目,例如 Dropbox sdk 或其他类型的第三方 sdk

android - 是否可以像 ListView 一样在 recycleview 中设置 CursorAdapter?

android - SwipeRefreshLayout 阻止水平滚动的 RecyclerView