SwipeRefreshレイアウトの唯一の子であるlistviewに空のビューを設定した後、SwipeRefreshが機能しません。この問題を解決する方法は?
解決策は次のとおりです。このビュー階層を使用するだけです。
<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));
それでおしまい。
私もこの問題を抱えていて、以下のレイアウトを使用して解決しましたアクティビティに追加のコードなしで。
ListActivity
またはListFragment
を使用している場合は、空のビューの表示/非表示を処理し、このレイアウト構造では空のリストでも更新が機能します。
ハックは必要ありません。すべてが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は期待どおりに機能します。
私にとっての問題は、空のビューが表示されているときに、更新方法が機能したにもかかわらず、更新サークルが表示されないことでした。私にとってこのコードはうまくいきました、私はそれが役立つことを願っています。
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);
お役に立てば幸いです。
これが私がこれをした方法です(おそらくあまりエレガントな解決策ではありません)
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>
この問題を確認できます。回避策を投稿しました。
UIハックを試しましたが、機能しませんでした。機能した唯一の解決策はアダプターの設定です。空の値を渡し、値がnullにならないようにします。
NotificationListAdapter notificationListAdapter;
notificationListAdapter = new NotificationListAdapter(mContext,notificationResponse);
reCycleViewNotificationList.setAdapter(notificationListAdapter); // weather ListView or RecyclerView
上で書いた@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_parent
で、SwipeRefresh
の高さはwrap_content
です。リストに項目がある場合は、テキストをgone
にすることを忘れないでください。
私はうまくいく別のアイデアを持っています。サブクラスListViewおよびオーバーライドsetAdapter()およびsetEmptyView()。 setEmptyViewは、空のビューに使用するビューを格納する必要があります。setAdapterは、変更せずに空のビューを表示/非表示にするDataSetObserverを登録する必要があります。リストビューの可視性。 SwipeToRefreshLayoutと空のビュー(兄弟として)を保持するFrameLayoutを使用することをお勧めします。次に、重力とレイアウト重力を使用して、空のビューを上/中央/下などに非常に簡単に配置できます。 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>
これは、単にListViewをサブクラス化し、リストをGONE/HIDDENに設定しないようにsetVisibilityを変更するよりも少し多くのコードを必要としますが、これはハックではなく、ユーザーがリストをGONE/Hiddenに設定できるように感じます。必要に応じて。