我在RecyclerView
内处理SwipeRefreshLayout
,其中包含CardViews
基于从API调用中检索到的数据。这在一个应用中的Fragment
中实现,而在另一个应用中直接在Activity
中实现。
虽然此代码(经适当修改)在Activity
中正常工作,但片段中的变体始终显示为空白 - 即使我已验证已收到数据。即使播种假人CardView
也不会显示任何内容。
我做错了什么或错过了什么?
OnCreateView中的初始化如下:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate (R.layout.fragment_revive_housecall, container, false);
...
...
constraintLayout = view.findViewById (R.id.constraintLayout);
swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById (R.id.swipeRefreshLayout);
recyclerView = (RecyclerView) view.findViewById (R.id.recyclerView);
emptyView = (TextView) view.findViewById (R.id.empty_view);
houseCallList = new ArrayList<> ();
adapter = new HouseCallAdapter (getActivity ().getApplicationContext (), houseCallList);
if(houseCallList.isEmpty ()) {
emptyView.setText (R.string.pulltorefresh);
recyclerView.setVisibility (View.GONE);
emptyView.setVisibility (View.VISIBLE);
} else {
//emptyView.setVisibility (View.GONE);
recyclerView.setVisibility (View.VISIBLE);
adapter.notifyDataSetChanged();
}
recyclerView.setLayoutManager (new LinearLayoutManager (getActivity ().getApplicationContext ()));
recyclerView.setItemAnimator (new DefaultItemAnimator ());
recyclerView.setAdapter (adapter);
adapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() {
@Override
public void onChanged() {
super.onChanged();
checkEmpty();
}
@Override
public void onItemRangeInserted(int positionStart, int itemCount) {
super.onItemRangeInserted(positionStart, itemCount);
checkEmpty();
}
@Override
public void onItemRangeRemoved(int positionStart, int itemCount) {
super.onItemRangeRemoved(positionStart, itemCount);
checkEmpty();
}
void checkEmpty() {
emptyView.setText (R.string.no_data_available);
emptyView.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
recyclerView.setVisibility (adapter.getItemCount() == 0 ? View.GONE : View.VISIBLE);
}
});
ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT /*| ItemTouchHelper.RIGHT*/, this);
new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView);
swipeRefreshLayout.setOnRefreshListener (new SwipeRefreshLayout.OnRefreshListener () {
@Override
public void onRefresh() {
loadHouseCallRequests(null); // in this function call onItemsLoadComplete when done
}
});
return view;
}
OnSwiped覆盖如下:
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) {
if (viewHolder instanceof HouseCallAdapter.MyViewHolder) {
// get the removed item name to display it in snack bar
String housecallid = houseCallList.get(viewHolder.getAdapterPosition()).getHousecallid ();
// backup of removed item for undo purpose
final HouseCall deletedItem = houseCallList.get(viewHolder.getAdapterPosition());
final int deletedIndex = viewHolder.getAdapterPosition();
// remove the item from recycler view
adapter.removeItem(viewHolder.getAdapterPosition());
if (direction == ItemTouchHelper.LEFT) {
((HouseCallAdapter.MyViewHolder) viewHolder).viewBackground.setBackgroundColor (getResources ().getColor (R.color.bg_row_background_decline));
// showing snack bar with Undo option
Snackbar snackbar = Snackbar
.make(constraintLayout, "Request " + housecallid + " declined!", Snackbar.LENGTH_LONG);
snackbar.setAction("UNDO", new View.OnClickListener() {
@Override
public void onClick(View view) {
// undo is selected, restore the deleted item
adapter.restoreItem(deletedItem, deletedIndex);
}
});
snackbar.setActionTextColor(Color.RED);
snackbar.show();
}
}
}
void onItemsLoadComplete() {
swipeRefreshLayout.setRefreshing(false);
}
private void loadHouseCallRequests(@Nullable JsonObject params) {
// This is the code that generates the dummy cardview
/*HouseCall call = new HouseCall ("abc123", "open", "12/02/1991", "26/02/2018:22:39", "general", "6", "XY", "AB", "ACB@XZY.com", "Male", "Line1", "Line2", "Line3", "City", "State", "123456789");
houseCallList.add (call);*/
adapter.notifyDataSetChanged();
onItemsLoadComplete ();
if (params == null) {
params = new JsonObject ();
params.addProperty ("email", email);
}
GetHouseCalls calls = new GetHouseCalls ();
calls.execute (params);
}
适配器
public class HouseCallAdapter extends RecyclerView.Adapter<HouseCallAdapter.MyViewHolder> {
private Context mContext;
private List<HouseCall> houseCallList;
private static final int DATASET_EMPTY = 0;
private static final int DATA_AVAILABLE = 1;
public class MyViewHolder extends RecyclerView.ViewHolder{
public TextView txtFname, txtLname, txtDob, txtSex, txtAddress, txtMobile;
public ConstraintLayout viewBackground, viewForeground;
public MyViewHolder(View itemView) {
super (itemView);
txtName = itemView.findViewById (R.id.txtName);
... // add data to the layout of the
}
}
public HouseCallAdapter(Context mContext, List<HouseCall> houseCallList) {
this.mContext = mContext;
this.houseCallList = houseCallList;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from (parent.getContext ())
.inflate (R.layout.housecall_request, parent, false);
return new MyViewHolder (itemView);
}
@Override
public void onBindViewHolder(MyViewHolder holder, int position) {
HouseCall houseCall = houseCallList.get (position);
... // retreive data from UI elements and set data in UI
}
@Override
public int getItemCount() {
return houseCallList.size ();
}
public void removeItem(int position) {
houseCallList.remove(position);
// notify the item removed by position
// to perform recycler view delete animations
// NOTE: don't call notifyDataSetChanged()
notifyItemRemoved(position);
}
public void restoreItem(HouseCall item, int position) {
houseCallList.add(position, item);
// notify item added by position
notifyItemInserted(position);
}
}
Recycler Item Touch Helper
public class RecyclerItemTouchHelper extends ItemTouchHelper.SimpleCallback {
private RecyclerItemTouchHelperListener listener;
public RecyclerItemTouchHelper(int dragDirs, int swipeDirs, RecyclerItemTouchHelperListener listener) {
super(dragDirs, swipeDirs);
this.listener = listener;
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
return true;
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
if (viewHolder != null) {
final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;
getDefaultUIUtil().onSelected(foregroundView);
}
}
@Override
public void onChildDrawOver(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;
getDefaultUIUtil().onDrawOver(c, recyclerView, foregroundView, dX, dY,
actionState, isCurrentlyActive);
}
@Override
public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;
getDefaultUIUtil().clearView(foregroundView);
}
@Override
public void onChildDraw(Canvas c, RecyclerView recyclerView,
RecyclerView.ViewHolder viewHolder, float dX, float dY,
int actionState, boolean isCurrentlyActive) {
final View foregroundView = ((HouseCallAdapter.MyViewHolder) viewHolder).viewForeground;
getDefaultUIUtil().onDraw(c, recyclerView, foregroundView, dX, dY,
actionState, isCurrentlyActive);
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
listener.onSwiped(viewHolder, direction, viewHolder.getAdapterPosition());
}
@Override
public int convertToAbsoluteDirection(int flags, int layoutDirection) {
return super.convertToAbsoluteDirection(flags, layoutDirection);
}
public interface RecyclerItemTouchHelperListener {
void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position);
}
}
布局xml
<android.support.constraint.ConstraintLayout 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:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapp.appname.FragmentCards">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:gravity="center_vertical"
android:text="@string/no_data_available"
android:textAlignment="center"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.698"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:visibility="visible" />
</android.support.v4.widget.SwipeRefreshLayout>
答案 0 :(得分:0)
感谢@ MohammedFarhan的建议,我查看了UI的XML布局,并在那里发现了问题。
在较旧的布局中,RecyclerView被隐藏,并且在屏幕上不可见,因此手机上的空白屏幕。
<android.support.constraint.ConstraintLayout
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:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapp.appname.FragmentCards">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/empty_view"
android:layout_width="wrap_content"
android:layout_height="18dp"
android:gravity="center_vertical"
android:text="@string/no_data_available"
android:textAlignment="center"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.698"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"
android:visibility="visible" />
我需要做的就是将RecyclerView顶部的约束添加到父级,并将TextView移动到ConstraintLayout的子级。
<android.support.constraint.ConstraintLayout 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:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.testapp.appname.FragmentCards">
<TextView
android:id="@+id/empty_view"
android:layout_width="0dp"
android:layout_height="92dp"
android:gravity="center_vertical"
android:text="@string/no_data_available"
android:textAlignment="center"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.498" />
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipeRefreshLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="0dp"
android:scrollbars="vertical"
android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="8dp" />
</android.support.v4.widget.SwipeRefreshLayout>
</android.support.constraint.ConstraintLayout>