Android Pull-to-Refresh를 구현하는 방법


432

Twitter (공식 앱)와 같은 Android 애플리케이션에서 ListView가 표시되면 컨텐츠를 새로 고치기 위해 풀다운 (해제시 바운스) 될 수 있습니다.

귀하의 의견으로는 그것을 구현하는 가장 좋은 방법이 무엇인지 궁금합니다.

내가 생각할 수있는 몇 가지 가능성 :

  1. ListView 상단의 항목-그러나 ListView에서 애니메이션을 사용하여 항목 위치 1 (0 기반)로 다시 스크롤하는 것은 쉬운 일이 아니라고 생각합니다.
  2. ListView 외부의 다른보기-ListView를 가져올 때 ListView 위치를 아래로 이동해야합니다 .ListView에 대한 드래그 터치가 여전히 ListView의 항목을 실제로 스크롤하는지 감지 할 수 있는지 확실하지 않습니다.

어떤 추천?

추신 : 나는 공식 트위터 앱 소스 코드가 언제 출시되는지 궁금합니다. 출시 될 것이라고 언급되었지만 6 개월이 지났으며 그 이후로는 그 소식을 듣지 못했습니다.


이 기능은 동적으로 생성 된 TableLayout에서 구현할 수 있습니까? 도와주세요 .....
Arun Badole

github.com/fruitranger/PulltorefreshListView 는 또 다른 구현입니다. 부드럽고 멀티 터치 지원.
Changwei Yao

6
관련 : “Pull-to-Refresh”: Android의 안티 UI 패턴 은이 UI Android에서 사용되어서는 안되며 그 적절성에 대해 많은 논의를 불러 일으킨다 고 주장하는 기사 입니다.
blahdiblah

29
최신 버전의 Android 용 Gmail은이 "안티 패턴"을 사용하므로 누군가에게 Google에 알려야합니다.
Nick

4
Pull to refresh는 iOS와 Android에서 표준으로 채택 된 패턴이며 오래 전부터 매우 자연 스럽기 때문에 이러한 반 패턴 토론은 구식입니다. 사용자는이를보고 그대로 행동해야합니다.
Martin Marconcini

답변:


310

마지막으로 Google은 새로 고침 풀 라이브러리의 공식 버전을 출시했습니다!

SwipeRefreshLayout지원 라이브러리 내에서 이라고 하며 설명서는 다음과 같습니다.

  1. SwipeRefreshLayout레이아웃을 새로 고치기 위해 풀로 취급되는 뷰의 부모로 추가하십시오 . (내가했다 ListView예를 들어, 어떤 일 수있다 View처럼 LinearLayout, ScrollView등)

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </android.support.v4.widget.SwipeRefreshLayout>
  2. 수업에 리스너 추가

    protected void onCreate(Bundle savedInstanceState) {
        final SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh);
        pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshData(); // your code
                pullToRefresh.setRefreshing(false);
            }
        });
    }

pullToRefresh.setRefreshing(true/false);요구 사항에 따라 전화 할 수도 있습니다 .

최신 정보

Android 지원 라이브러리는 더 이상 사용되지 않으며 AndroidX로 대체되었습니다. 새 라이브러리에 대한 링크는 여기 에서 찾을 수 있습니다 .

또한 프로젝트에 다음과 같은 종속성을 추가해야합니다.

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

또는

Refactor >> Migrate to AndroidX로 이동하면 Android Studio가 종속성을 처리합니다.


3
SwipeRefreshLayout에서 색상 표 대신 ProgressBar를 사용할 수 있습니까?
pablobaldez

54
144 월 1 일 -그리고 그것은 농담이 아니었다
aeracode


80

Pull to Refresh 구성 요소를 구현하려고 시도 했지만 완전 하지는 않지만 가능한 구현 방법을 보여줍니다 ( https://github.com/johannilsson/android-pulltorefresh) .

메인 로직이 PullToRefreshListView확장 되어 구현 됩니다 ListView. 내부적으로 smoothScrollBy(API 레벨 8)을 사용하여 헤더보기의 스크롤을 제어합니다 . 위젯은 이제 1.5 이상을 지원하도록 업데이트되었습니다. README 1.5 지원을 읽으십시오.

레이아웃에서 단순히 다음과 같이 추가하십시오.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />

3
요한, 샘플 코드를 다운로드했습니다. 안드로이드 2.2 장치에서는 작동하지만 2.1 장치에서는 작동하지 않습니다. 2.2 이상에서만 사용할 수있는 smoothScrollBy 메서드를 사용했기 때문에 정확 하다고 생각 합니까? 이 효과를 2.1 이전 버전으로 구현할 생각이 있습니까? 감사합니다

그렇습니다. smoothScrollBy가 API 레벨 8 (2.2)에 도입 된 답변에서 언급 한대로 맞습니다. 아직 다른 버전에서 구현하는 적절한 방법을 찾지 못했지만 smoothScrollBy 구현을 이식 할 수 있어야한다고 생각하지만 토론은 프로젝트 오버플로가 아닌 프로젝트 사이트에서 유지되어야한다고 생각합니까?
Johan Berg Nilsson

ID가 @android : id / list가 아니라 @ + id / android : list라는 것이 목적입니까, 이상하게 보입니까? 이 프로젝트는 내 편에 인플레이션 오류를 발생시킵니다. 현재이를 확인하고 있습니다.
Mathias Conradt

12
이것은 내가 찾은 pull to refresh에 가장 적합한 라이브러리입니다. github.com/chrisbanes/Android-PullToRefresh . ListViews, GridViews 및 Webviews와 함께 작동합니다. 또한 Pull up to refresh 패턴을 구현했습니다.
rOrlig

1
Intellij Idea에서 작업하는 동안 프로젝트를 라이브러리 폴더에 추가하려면 어떻게합니까? 아무도 나를 도울 수 있습니까?
Mustafa Güven

55

또한 강력한 오픈 소스, 사용하기 쉽고 사용자 정의가 가능한 Android 용 PullToRefresh 라이브러리를 구현했습니다. 프로젝트 페이지의 문서에 설명 된대로 ListView를 PullToRefreshListView로 바꿀 수 있습니다.

https://github.com/erikwt/PullToRefresh-ListView


나는 여기에 나열된 모든 구현을 시도했으며 구현을 새로 고치기 위해 단순 / 순수 / 부드러운 풀 (Johan과 같은 기이함을 탭하지 않음) 측면에서 가장 좋습니다. 감사!
Gady

1
표준 ListView를 대체하여 ListActivity, ListFragment 등을 사용할 수 있습니까?
davidcesarino

예, PullToRefreshListView에 올바른 ID를 지정하십시오. XML : android : id = "@ android : id / list"
Erik

1
이것은 절대적으로 굉장하다! 구글이 나를 여기로 데려왔고 예제를 살펴보면 구현하기 가장 쉬운 것 같습니다. 브라보 감사합니다!
Evan R.

멋지고 심플한 디자인으로 구성되어 있습니다. 이것은 분명히 받아 들여질만한 대답이어야합니다.
Adam

42

내가 생각하는 가장 쉬운 방법은 안드로이드 지원 라이브러리에서 제공하는 것입니다.

android.support.v4.widget.SwipeRefreshLayout;

일단 가져 오면 레이아웃을 다음과 같이 정의 할 수 있습니다.

  <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_height="match_parent"
        android:layout_width="match_parent">
    <android.support.v7.widget.RecyclerView
        xmlns:recycler_view="http://schemas.android.com/apk/res-auto"
        android:id="@android:id/list"
        android:theme="@style/Theme.AppCompat.Light"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/button_material_light"
        >

    </android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>

listview 대신 recycler view를 사용한다고 가정합니다. 그러나 listview는 여전히 작동하므로 recyclerview를 listview로 바꾸고 Java 코드 (Fragment)의 참조를 업데이트하면됩니다.

활동 단편에서 먼저 인터페이스를 구현하십시오 SwipeRefreshLayout.OnRefreshListener. i, e

public class MySwipeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
private SwipeRefreshLayout swipeRefreshLayout;

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_item, container, false);
        swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh);
        swipeRefreshLayout.setOnRefreshListener(this);
}


 @Override
  public void onRefresh(){
     swipeRefreshLayout.setRefreshing(true);
     refreshList();
  }
  refreshList(){
    //do processing to get new data and set your listview's adapter, maybe  reinitialise the loaders you may be using or so
   //when your data has finished loading, cset the refresh state of the view to false
   swipeRefreshLayout.setRefreshing(false);

   }
}

이것이 대중을 돕는 희망


잘 작동한다. 그래도 developer.android.com/reference/android/support/v4/widget/…에setRefreshing 설명 된대로 "스 와이프 동작으로 화면 갱신이 트리거 될 때이 기능을 호출하지 마십시오"
gabriel14

잘 했어! 감사.
technik

22

이 링크에서는 유명한 포크 찾을 수 있습니다 PullToRefresh새로운 흥미와 같은 구현이보기 PullTorRefreshWebView또는 PullToRefreshGridView또는를 추가 할 수있는 가능성이 PullToRefresh목록의 하단에 있습니다.

https://github.com/chrisbanes/Android-PullToRefresh

그리고 가장 좋은 점은 Android 4.1에서 완벽하게 작동한다는 것입니다 (정상 PullToRefresh작동하지 않습니다)


3
추가 정보 맨 위에 큰 주석이 표시됩니다.이 프로젝트는 더 이상 유지 관리되지 않습니다. 어쨌든이 라이브러리는 내가 지금까지 본 것 중 최고입니다! 훌륭한 일!
Milton

3
더 이상 유지 관리되지 않는다고해서 그것이 좋지 않다는 것을 의미하지는 않습니다. 여전히 내 모든 요구를 새로 고치기 위해 그것을 사용하십시오 :)
Muz

18

이 작업을 수행하는 매우 쉬운 방법이 있지만 이제는 그 확실한 방법을 확인하십시오. 내 코드 PullDownListView.java가 있습니다.

package com.myproject.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

/**
 * @author Pushpan
 * @date Nov 27, 2012
 **/
public class PullDownListView extends ListView implements OnScrollListener {

    private ListViewTouchEventListener mTouchListener;
    private boolean pulledDown;

    public PullDownListView(Context context) {
        super(context);
        init();
    }

    public PullDownListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PullDownListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        setOnScrollListener(this);
    }

    private float lastY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            lastY = ev.getRawY();
        } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
            float newY = ev.getRawY();
            setPulledDown((newY - lastY) > 0);
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (isPulledDown()) {
                        if (mTouchListener != null) {
                            mTouchListener.onListViewPulledDown();
                            setPulledDown(false);
                        }
                    }
                }
            }, 400);
            lastY = newY;
        } else if (ev.getAction() == MotionEvent.ACTION_UP) {
            lastY = 0;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        setPulledDown(false);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    public interface ListViewTouchEventListener {
        public void onListViewPulledDown();
    }

    public void setListViewTouchListener(
            ListViewTouchEventListener touchListener) {
        this.mTouchListener = touchListener;
    }

    public ListViewTouchEventListener getListViewTouchListener() {
        return mTouchListener;
    }

    public boolean isPulledDown() {
        return pulledDown;
    }

    public void setPulledDown(boolean pulledDown) {
        this.pulledDown = pulledDown;
    }
}

이 ListView를 사용하고 리스너를 설정하려는 활동에 ListViewTouchEventListener를 구현하면됩니다.

PullDownListViewActivity에서 구현했습니다.

package com.myproject.activities;

import android.app.Activity;
import android.os.Bundle;

/**
 * @author Pushpan
 *
 */
public class PullDownListViewActivity extends Activity implements ListViewTouchEventListener {

    private PullDownListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        listView = new PullDownListView(this);
        setContentView(listView);
        listView.setListViewTouchListener(this);

        //setItems in listview
    }

    public void onListViewPulledDown(){
        Log.("PullDownListViewActivity", "ListView pulled down");
    }
}

그것은 나를 위해 작동합니다 :)


18

안드로이드 Pull-to-Refresh를 구현하려면이 코드를 사용해보십시오.

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</android.support.v4.widget.SwipeRefreshLayout>

활동 클래스 :

ListView lv = (ListView) findViewById(R.id.lv);
SwipeRefreshLayout pullToRefresh = (SwipeRefreshLayout) findViewById(R.id.pullToRefresh);


lv.setAdapter(mAdapter);

pullToRefresh.setOnRefreshListener(new OnRefreshListener() {

        @Override
        public void onRefresh() {
            // TODO Auto-generated method stub

            refreshContent();

        }
    });



private void refreshContent(){ 

     new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                pullToRefresh.setRefreshing(false);
            }
        }, 5000);

 }

1
Thanks.it 정말 도움이되었습니다
Arpan Sharma

9

Google Now 또는 Gmail 애플리케이션과 같이 작업 표시 줄 위에 표시되는 새로운 유형의 '새로 고침'을 언급 한 사람은 없습니다.

정확히 동일하게 작동하는 ActionBar-PullToRefresh 라이브러리가 있습니다 .


7

Android 및 WP에서 구현할 때 해결해야 할 UX 문제가 있습니다.

"디자이너 / 개발자들이 iOS 앱 스타일로 풀 투 리프레쉬를 구현하지 않아야하는 이유에 대한 훌륭한 지표는 Google과 팀이 iOS에서 사용하는 동안 안드로이드에서 풀 투 리프레쉬를 사용하지 않는 방법입니다."

https://plus.google.com/109453683460749241197/posts/eqYxXR8L4eb


3
1 년이 지났지 만 Gmail 앱은 새로 고침을 사용합니다. 그러나 UI 측면에서 정확히 동일하지는 않지만 목록이 아래로 스크롤되지 않고 화면 상단에 새보기가 표시됩니다.
ashishduh '12

4

프로그램이 Android에 강제로 장착 된 iPhone 프로그램처럼 보이지 않게하려면보다 기본적인 모양과 느낌을 목표로 Gingerbread와 비슷한 작업을 수행하십시오.

대체 텍스트


2
@Rob : 아이폰처럼 목록이 튀어 오르는 대신, 너무 많이 눌렀을 때 목록 상단에 주황색 그림자가 생겼습니다. 이것은 댓글 (답변이 아님)을 의미하지만 댓글에는 이미지가있을 수 없습니다.
Lie Ryan

아 죄송합니다, 좋은 생각입니다. 나는 아직 진저 브레드를 가지고 놀지 않았으므로 그 효과를 보지 못했습니다. 여전히 구글이 넥서스로 롤백하기를 기다리고 있습니다.
Rob

9
진저 브레드가 있고 목록이 정적 일 때 주황색 광선이 잘 작동합니다. 그러나 풀다운 새로 고침은 동적 목록을 새로 고치는 훌륭한 UI 메커니즘입니다. iOS 세계에서 널리 퍼져 있지만 Android 생태계에서는 더 이상 느끼지 않는 UI 트릭입니다. 공식 Twitter 앱에서 확인하는 것이 좋습니다. :)
Thierry-Dimitri Roy

여기에서 기본 동작은 목록 끝에 도달했음을 나타냅니다. 이 작업을 수행하고 새로 고침을 수행하는 것은 플랫폼이 수행하지 않는 작업과 동일합니다. 즉, 사용자를 놀라게 할 가능성이 높습니다. 나는 목록의 끝에 도달했기 때문에 새로 고침을 기대하거나 원하지 않을 것입니다. 새로 고침하기 위해 풀다운하는 것이 훨씬 직관적이고 명확합니다. 기본 트위터 앱이 사용함에 따라 많은 사람들이 익숙한 UI 개념이라고 생각합니다.
steprobe



1

최신 Lollipop Pull-To Refresh를 받으려면 :

  1. 최신 Lollipop SDK 및 Extras / Android 지원 라이브러리 다운로드
  2. 프로젝트의 빌드 대상을 Android 5.0으로 설정하십시오 (그렇지 않으면 지원 패키지에 자원에 오류가있을 수 있음)
  3. libs / android-support-v4.jar을 21 번째 버전으로 업데이트하십시오.
  4. android.support.v4.widget.SwipeRefreshLayout플러스 사용android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

자세한 가이드는 여기에서 찾을 수 있습니다 : http://antonioleiva.com/swiperefreshlayout/

ListView의 canChildScrollUp()경우 주석에서 읽어 보는 것이 좋습니다 .)


또한 canChildScrollUp ()을 언급하기위한 것입니다. 매우 중요!
Petro

1

아주 재미있는 풀 - 투 - 새로 고침 하여 Yalantis . iOS 용 Gif이지만 확인할 수 있습니다 :)

<com.yalantis.pulltorefresh.library.PullToRefreshView
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
    android:id="@+id/list_view"
    android:divider="@null"
    android:dividerHeight="0dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />


0

먼저 Android에서 레이아웃을 새로 고치려면 Pull이 무엇인지 알아야합니다. 우리는 swipe-to-refresh로 android에서 pull to refresh를 호출 할 수 있습니다. 화면을 위에서 아래로 스 와이프하면 setOnRefreshListener에 따라 일부 작업이 수행됩니다.

다음은 새로 고침을 위해 Android 풀을 구현하는 방법을 보여주는 자습서 입니다. 이게 도움이 되길 바란다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.