web-dev-qa-db-ja.com

Androidサポートv4SwipeRefreshLayout空のビューの問題

SwipeRefreshレイアウトの唯一の子であるlistviewに空のビューを設定した後、SwipeRefreshが機能しません。この問題を解決する方法は?

16
Dinesh

解決策は次のとおりです。このビュー階層を使用するだけです。

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

それでおしまい。

22
nitesh goel

私もこの問題を抱えていて、以下のレイアウトを使用して解決しましたアクティビティに追加のコードなしで

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は期待どおりに機能します。

4
avb

私にとっての問題は、空のビューが表示されているときに、更新方法が機能したにもかかわらず、更新サークルが表示されないことでした。私にとってこのコードはうまくいきました、私はそれが役立つことを願っています。

  • 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);
    

お役に立てば幸いです。

3
gipsey

これが私がこれをした方法です(おそらくあまりエレガントな解決策ではありません)

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>
2
orium

2つのSwipeToRefreshLayoutsを使用してこの問題を修正しました。

  • ListViewをラップするための1つ
  • EmptyViewとしてのもう1つ

コードを GitHub に投稿しました。

1
Tobrun

この問題を確認できます。回避策を投稿しました。

Android-テキストビューが空のSwipeRefreshLayout

1
hufeng03

UIハックを試しましたが、機能しませんでした。機能した唯一の解決策はアダプターの設定です。空の値を渡し、値がnullにならないようにします。

NotificationListAdapter notificationListAdapter;
notificationListAdapter = new NotificationListAdapter(mContext,notificationResponse);
reCycleViewNotificationList.setAdapter(notificationListAdapter); // weather ListView or RecyclerView
0

上で書いた@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にすることを忘れないでください。

0

私はうまくいく別のアイデアを持っています。サブクラス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に設定できるように感じます。必要に応じて。

0
Matt Wolfe