Android支持v4 SwipeRefreshLayout空视图问题

SwipeRefresh设置一个空视图的ListView这是SwipeRefresh布局的唯一的孩子之后不工作。 如何解决这个问题?

Solutions Collecting From Web of "Android支持v4 SwipeRefreshLayout空视图问题"

这里是解决scheme:您可以简单地使用这个视图层次结构:

<FrameLayout ...> <android.support.v4.widget.SwipeRefreshLayout ...> <ListView android:id="@android:id/list" ... /> </android.support.v4.widget.SwipeRefreshLayout> <TextView android:id="@android:id/empty" ... android:text="@string/empty_list"/> </FrameLayout> 

然后,在代码中,您只需调用:

 _listView.setEmptyView(findViewById(android.R.id.empty)); 

而已。

我的问题是,当空的视图是可见的,然而刷新的方法工作,虽然没有显示刷新的圈子。 对于我这个代码工作,我希望它有帮助。

  • xml布局:

     <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:clickable="true"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="wrap_content" android:fadingEdge="none" android:footerDividersEnabled="false" android:headerDividersEnabled="false"/> <ScrollView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center"> <TextView android:id="@+id/empty_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center" android:gravity="center" android:visibility="gone"/> </ScrollView> </FrameLayout> 

  • 自定义SwipeRefreshLayout:

     package misc; import android.content.Context; import android.support.v4.widget.SwipeRefreshLayout; import android.widget.ListView; public class CustomSwipeRefreshLayout extends SwipeRefreshLayout { private ListView mListView; public CustomSwipeRefreshLayout(Context context) { super(context); } public void setListView(ListView listView) { mListView = listView; } @Override public boolean canChildScrollUp() { if (mListView == null) { return true; } return mListView.canScrollVertically(-1); } } 
  • 并在我使用布局的片段中,我只设置刷新以这种方式刷新布局:

     mSwipeRefreshLayout.setListView(mListView); 
  • ListView的空视图是这样设置的:

     TextView emptyView = (TextView) view.findViewById(R.id.empty_view); emptyView.setText("No data"); mListView.setEmptyView(emptyView); 

我希望它有帮助。

我也有这个问题,并通过使用下面的布局解决了它没有任何额外的代码在活动中。

如果您使用的是ListActivityListFragment它会处理显示/隐藏空白视图,并使用此布局结构刷新空白列表。

没有hacks需要,一切都在SwipeRefreshLayout ,因为它应该是。

 <?xml version="1.0" encoding="utf-8"?> <android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/Refresher" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" android:divider="@null" /> <ScrollView android:id="@android:id/empty" android:layout_width="match_parent" android:layout_height="match_parent"> <TextView android:text="Geen formulieren gevonden" style="@style/text.EmptyView" /> </ScrollView> </LinearLayout> </android.support.v4.widget.SwipeRefreshLayout> 

希望这可以帮助你。 如果是这样,不要忘记接受答案。

注:这是我对这个问题的答案的重复,但这个问题几乎是这个问题的重复… 🙂

UPDATE
如果SwipeRefreshLayout被激活得太早,您可以通过以下方式实现ListView.OnScroll:

 _refresher.Enabled = e.FirstVisibleItem == 0; 

这将禁用刷新,直到您滚动到顶部。 这只是在使用ListView时才需要,新的RecyclerView按预期工作。

这是我如何做到这一点(可能不是很优雅的解决scheme)

 private void createEmptyView() { ViewGroup parent = (ViewGroup) listView.getParent(); emptyView = (TextView) getLayoutInflater(null) .inflate(R.layout.view_empty, parent, false); parent.addView(emptyView); listView.setEmptyView(emptyView); } public class FrameSwipeRefreshLayout extends SwipeRefreshLayout { private ViewGroup listView; public void setListView(ViewGroup list) { listView = list; } @Override public boolean canChildScrollUp() { if (listView != null) { View child = listView.getChildAt(0); return child != null && child.getTop() != 0; } return super.canChildScrollUp(); } } 

空的布局

 <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center_horizontal" android:clickable="true" /> 

列表布局

  <FrameSwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent" > <ListView android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="match_parent" /> </FrameLayout> </FrameSwipeRefreshLayout> 

你可以看看这个问题。 我发布了解决scheme。

Android – 与空textview的SwipeRefreshLayout

我使用两个SwipeToRefreshLayouts解决了这个问题。

  • 一个用于包装ListView
  • 另一个为空视图

我把我的代码发布到GitHub上 。

正如上面写的@Dinesh,我已经使用clickable="true"如下面的空RecyclerView

 mRecyclerView.setVisibility(View.VISIBLE); mRecyclerView.setClickable(true); myText.setVisibility(View.VISIBLE); 

xml布局:

 <RelativeLayout android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipeRefreshKartvizitKisilerim" android:layout_width="match_parent" android:layout_height="wrap_content"> <android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent"/> </android.support.v4.widget.SwipeRefreshLayout> <TextView android:id="@+id/myText" android:visibility="gone" android:text="@string/noListItem" android:textSize="18sp" android:layout_centerInParent="true" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </RelativeLayout> 

RecyclerView高度是match_parentSwipeRefreshwrap_content 。 当列表中有项目时,不要忘记使文本gone

我有另一个想法,运作良好。 子类ListView并重写setAdapter()setEmptyView()setEmptyView应该只存储用于空视图的视图,并且setAdapter应该注册一个DataSetObserver ,它将隐藏/显示空视图而不改变列表视图的可见性。 你可能会想要使用一个FrameLayout来保存你的SwipeToRefreshLayout和一个空的视图(作为兄弟)。 然后你可以很容易地使用重力和布局重力定位空的视图在顶部/中间/底部等。 你也可以使用RelativeLayout,但我没有尝试过。 你会想以某种方式取消注册dataSetObserver,我相信你可能想在onDetachFromWindow中做到这一点,如下所示。

 public class SwipeToRefreshCompatibleList extends ListView { private boolean mIsEmpty = false; private View mEmptyView; private Adapter mAdapter; private DataSetObserver mLocalObserver = new DataSetObserver() { @Override public void onChanged() { boolean isEmpty = mAdapter == null || mAdapter.getCount() == 0; if (mEmptyView != null) { if (isEmpty != mIsEmpty) { mEmptyView.setVisibility(isEmpty ? View.VISIBLE : View.GONE); } } mIsEmpty = isEmpty; } }; public SwipeToRefreshCompatibleList(Context context) { super(context); } public SwipeToRefreshCompatibleList(Context context, AttributeSet attrs) { super(context, attrs); } public SwipeToRefreshCompatibleList(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @TargetApi(Build.VERSION_CODES.LOLLIPOP) public SwipeToRefreshCompatibleList(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public void setAdapter(ListAdapter adapter) { mAdapter = adapter; adapter.registerDataSetObserver(mLocalObserver); super.setAdapter(adapter); } @Override public void setEmptyView(View view) { mEmptyView = view; } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); if (mAdapter != null) { mAdapter.unregisterDataSetObserver(mLocalObserver); } } } 

示例布局文件:

  <?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <android.support.v4.widget.SwipeRefreshLayout android:id="@+id/swipe_container" android:layout_width="match_parent" android:layout_height="match_parent" > <com.company.widget.SwipeToRefreshCompatibleList android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/BasicList" android:divider="@null" /> </android.support.v4.widget.SwipeRefreshLayout> <TextView android:padding="20dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:layout_gravity="center" android:textSize="18sp" android:id="@android:id/empty" /> </FrameLayout> 

虽然这需要更多的代码,而不是简单地inheritanceListView并改变setVisibility,使它不会将列表设置为GONE / HIDDEN,但我觉得这是一个黑客攻击,并且仍然允许用户将列表设置为GONE / Hidden如果他们需要。