Как реализовать Android Pull-to-Refresh
В приложениях Android, таких как Twitter (официальное приложение), когда вы сталкиваетесь с ListView, вы можете вытащить его (и он будет возвращаться при отпускании), чтобы обновить содержимое.
Интересно, какой лучший способ, на ваш взгляд, реализовать это?
Некоторые возможности, о которых я мог подумать:
- Элемент в верхней части ListView - однако я не думаю, что прокрутка назад к позиции позиции 1 (основанная на 0) с анимацией в ListView является легкой задачей.
- Еще один вид вне списка ListView - но мне нужно позаботиться о том, чтобы перемещать позицию ListView вниз, когда оно вытащено, и я не уверен, можем ли мы обнаружить, что перетаскивание в ListView по-прежнему действительно прокручивает элементы на ListView.
Любые рекомендации?
P.S. Интересно, когда выйдет официальный исходный код приложения Twitter. Было упомянуто, что он будет выпущен, но прошло 6 месяцев, и с тех пор мы не слышали об этом.
Ответы
Ответ 1
Наконец, Google выпустил официальную версию библиотеки для обновления!
Он называется SwipeRefreshLayout
внутри библиотеки поддержки, и документация находится здесь here:
Добавьте 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>
Добавьте слушателя в свой класс
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.
Любое предложение или улучшение оцениваются:)
Ответ 12
Я думаю, что лучшая библиотека: https://github.com/chrisbanes/Android-PullToRefresh.
Работает с:
ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager
Ответ 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 тянуть, чтобы обновить. Надеюсь, это поможет.