Как реализовать Android Pull-to-Refresh

В приложениях Android, таких как Twitter (официальное приложение), когда вы сталкиваетесь с ListView, вы можете вытащить его (и он будет возвращаться при отпускании), чтобы обновить содержимое.

Интересно, какой лучший способ, на ваш взгляд, реализовать это?

Некоторые возможности, о которых я мог подумать:

  • Элемент в верхней части ListView - однако я не думаю, что прокрутка назад к позиции позиции 1 (основанная на 0) с анимацией в ListView является легкой задачей.
  • Еще один вид вне списка ListView - но мне нужно позаботиться о том, чтобы перемещать позицию ListView вниз, когда оно вытащено, и я не уверен, можем ли мы обнаружить, что перетаскивание в ListView по-прежнему действительно прокручивает элементы на ListView.

Любые рекомендации?

P.S. Интересно, когда выйдет официальный исходный код приложения Twitter. Было упомянуто, что он будет выпущен, но прошло 6 месяцев, и с тех пор мы не слышали об этом.

Ответ 1

Наконец, Google выпустил официальную версию библиотеки для обновления!

Он называется SwipeRefreshLayout внутри библиотеки поддержки, и документация находится здесь here:

  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); согласно вашему требованию.

Ответ 2

Я попытался реализовать компонент pull для обновления, это далеко не полный, но демонстрирует возможную реализацию, https://github.com/johannilsson/android-pulltorefresh.

Основная логика реализована в PullToRefreshListView, которая расширяет ListView. Внутри он управляет прокруткой заголовка с помощью smoothScrollBy (API уровня 8). Теперь виджет обновляется с поддержкой 1,5 и более поздних версий, пожалуйста, прочитайте поддержку README for 1.5.

В ваших макетах вы просто добавляете его так.

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

Ответ 3

Я также внедрил надежную, открытую исходную, удобную и настраиваемую библиотеку PullToRefresh для Android. Вы можете заменить ListView на PullToRefreshListView, как описано в документации на странице проекта.

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

Ответ 4

Самый простой способ, на мой взгляд, предоставляется библиотекой поддержки Android:

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>

Я предполагаю, что вы используете представление recycler вместо listview. Однако listview все еще работает, поэтому вам просто нужно заменить recyclerview на listview и обновить ссылки в java-коде (фрагмент).

В вашем фрагменте действия вы сначала реализуете интерфейс, 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 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);

   }
}

Надеюсь, что это поможет массам

Ответ 5

В этой ссылке вы можете найти вилку знаменитого представления PullToRefresh, в котором есть новые интересные реализации, такие как PullTorRefreshWebView или PullToRefreshGridView, или возможность добавить PullToRefresh в нижний край списка.

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

И самое лучшее, что работа идеально подходит для Android 4.1 (нормальный PullToRefresh не работает)

Ответ 6

У меня есть очень простой способ сделать это, но теперь уверен, что это надежный способ Есть мой код 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;
    }
}

Вам просто нужно реализовать ListViewTouchEventListener в своей деятельности, где вы хотите использовать этот ListView и установить прослушиватель

Я реализовал его в 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");
    }
}

Это работает для меня:)

Ответ 7

Чтобы реализовать андроид 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);

 }

Ответ 8

Никто не упоминает новый тип "Pull to refresh", который отображается поверх панели действий, например, в приложении Google Now или Gmail.

Существует библиотека ActionBar-PullToRefresh, которая работает точно так же.

Ответ 9

Заметьте, есть проблемы UX, с которыми можно бороться при внедрении на Android и WP.

"Отличным показателем того, почему разработчики/разработчики не должны реализовывать pull-to-refresh в стилях iOS-приложений, является то, как Google и их команды никогда не используют push-to-refresh на Android, пока они используют его в iOS".

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

Ответ 10

Если вы не хотите, чтобы ваша программа выглядела как программа для iPhone, которая была привязана к Android, ориентируйтесь на более естественный внешний вид и делайте что-то похожее на Gingerbread:

alt text

Ответ 11

Я написал ссылку для обновления компонента здесь: https://github.com/guillep/PullToRefresh Это событие работает, если в списке нет элементов, и я тестировал его на телефонах >= 1.6 android.

Любое предложение или улучшение оцениваются:)

Ответ 13

Чтобы получить последнюю версию Lollipop Pull-Ref Refresh:

  • Загрузите последнюю библиотеку поддержки Lollipop SDK и Extras/Android.
  • Установить сборку проекта для Android 5.0 (в противном случае пакет поддержки может иметь ошибки с ресурсами)
  • Обновите свою версию libs/android-support-v4.jar до 21-й версии
  • Используйте android.support.v4.widget.SwipeRefreshLayout plus android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

Подробное руководство можно найти здесь: http://antonioleiva.com/swiperefreshlayout/

Плюс для ListView Я рекомендую прочитать о canChildScrollUp() в комментариях;)

Ответ 14

Очень интересно Pull-to-Refresh Yalantis, Gif для iOS, но вы можете проверить его:)

<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" />

Ответ 15

Сначала мы должны знать, что такое Pull для обновления макета в Android. мы можем вызвать тянуть, чтобы обновить в Android, как пролистывание, чтобы обновить. когда вы проводите пальцем по экрану сверху вниз, он выполняет некоторые действия в зависимости от setOnRefreshListener.

Здесь учебник, который демонстрирует, как реализовать Android тянуть, чтобы обновить. Надеюсь, это поможет.