17

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

4

9 に答える 9

5

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

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>

これがお役に立てば幸いです。もしそうなら、答えを受け入れることを忘れないでください。

注:これはこの質問に対する私の回答の複製ですが、その質問はこの質問のほとんど複製です... :)

更新
SwipeRefreshLayout のアクティブ化が早すぎる場合は、次のように ListView.OnScroll を実装できます。

_refresher.Enabled = e.FirstVisibleItem == 0;

これにより、一番上までスクロールするまでリフレッシャーが無効になります。これは、ListView を使用する場合にのみ必要です。新しい RecyclerView は期待どおりに機能します。

于 2015-07-16T08:32:16.057 に答える
3

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

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

お役に立てば幸いです。

于 2015-09-02T16:04:34.710 に答える
2

これが私がこれを行った方法です(おそらくあまりエレガントなソリューションではありません)

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>
于 2014-12-02T10:25:59.830 に答える
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 に設定できるように感じます。彼らが必要な場合。

于 2015-09-10T17:40:19.680 に答える
0

上記の @Dinesh のように、clickable="true"以下のように emptyを使用しました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

于 2015-08-06T12:50:53.983 に答える