实施轻扫以刷新布局后,Recycler视图不能正确滚动

在实施刷卡刷新视图之前,回收者视图运行正常,但无论何时尝试向下滚动回收视图刷卡以刷新干扰并阻碍滚动移动。

这是问题的屏幕截图:

(请注意刷新布局来回收视图向下滚动)

在这里输入图像说明

这是我的布局片段:

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

下面是我的片段的代码:

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

我还在活动布局中实施了协调员布局。 这里是代码:

 <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视图应该是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()方法。

这是一个已知的问题,我想知道为什么这个问题还没有解决。 这里的问题是SwipeRefreshLayout总是假定列表不能向上滚动。

一个解决scheme是扩展SwipeRefreshLayout并覆盖canChildScrollUp() 。 当你开始滚动并返回false时,这个方法被调用,当列表不在顶端位置时,应该这样做。

接下来,使用此实用程序方法来确定您的RecyclerView是否可以向上滚动:

 /** * Returns whether or not a View can scroll vertically any further. * @param downwardScroll The direction to check for. Pass true for downwards and * false for upward. Note that downward scroll == upward swipe * */ public static boolean canScrollVerticallyAnyFurther(View view, boolean downwardScroll){ return view.canScrollVertically(downwardScroll ? +1 : -1); } 

我设法实现向下滑动刷新和无限滚动。 如果有人有兴趣退房。你可以看看这个执行

https://github.com/snijsure/TwitterSample

虽然从UX的angular度来看,我不确定是否支持SwipeDown刷新以及在滚动结束时刷新,这是一个好主意,可能会让最终用户感到困惑。

干杯!