English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Имитация下拉 обновления и загрузки больше в Android, вдохновленная новыми новостями в Silicon Valley

1. Add the load more layout

1_Initialization and hidden code

Call in the RefreshListView constructor

private void initFooterView(Context context) {
View footerView = View.inflate(context, R.layout.refresh_listview_footer, null);
//Hidden code
footerView.measure(0, 0);
int footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0);
this.addFooterView(footerView);
}

2_Layout file refresh_listview_footer.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal" >
<ProgressBar
android:layout_margin="5dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminateDrawable="@drawable/custom_progressbar" />
<TextView
android:layout_marginLeft="10dip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Загрузка больше..."
android:textColor="#ff0000"
android:textSize="25sp" />
</LinearLayout>

2. При драге до дна

/**
* Страницы новостей соответствующие меню
* Всего 12
* @author Administrator
*
*/
public class TabMenuDetailPager extends MenuDetailBasePager implements OnPageChangeListener {
/**
* Данные для тега новостей центра - новости соответствующие меню
*/
private NewCenterTag newCenterTag;
.......................
/**
* URL для загрузки дополнительных данных
*/
private String moreUrl;
/**
* Загрузка данных в процессе
*/
protected boolean isLoadingMore = false;
...................
@Override
public View initView() {
View view = View.inflate(mActivity, R.layout.tab_detail, null);
//Ввод View в рамочный аппарат XUtils
ViewUtils.inject(this, view); 
.......................... 
//Настройка слушателя для обновления下拉
mListView.setOnRefreshListener(new OnRefreshListener() {
@Override
public void onPullDownRefresh() {
isPullDownRefreshing = true;
getDataFromNet();
}
@Override
public void onLoadingMore() {
if (TextUtils.isEmpty(moreUrl)) {
Toast.makeText(mActivity, "Нет дополнительных данных", 1).show();
mListView.onRefreshFinish(false);
} else {
//Есть дополнительные данные, нужно загрузить еще данные
getMoreDataFromNet();
}
}
});
return view;
}
/**
* Загрузка дополнительного данных
*/
protected void getMoreDataFromNet() {
HttpUtils httpUtils = new HttpUtils();
httpUtils.send(HttpMethod.GET, moreUrl, new RequestCallBack<String>() {
@Override
public void onSuccess(ResponseInfo<String> responseInfo) {
System.out.println("加载更多数据成功:"+responseInfo.result);
mListView.onRefreshFinish(false);
isLoadingMore = true;
processData(responseInfo.result);
}
@Override
public void onFailure(HttpException error, String msg) {
mListView.onRefreshFinish(false);
System.out.println("加载更多数据失败:"+ msg);
}
}); 
}
/**
* 处理和解析json数据
* @param json
*/
protected void processData(String json) {
TabDetailBean bean = parserJson(json);
if(!isLoadingMore){
System.out.println(bean.data.news.get(0).title);
topnews = bean.data.topnews;
//给ViewPager设置适配器
TabDetailAdapter adapter = new TabDetailAdapter();
mViewPager.setAdapter(adapter);
// 把所有的View清除
ll_point_group.removeAllViews();
for(int i=0;i<topnews.size();i++){
View point = new View(mActivity);
LayoutParams params = new LayoutParams(5, 5) ;
point.setBackgroundResource(R.drawable.tab_detail_point_bg);
if(i!=0){
params.leftMargin = 10;
}
point.setEnabled(false);
point.setLayoutParams(params);
ll_point_group.addView(point);
}
previousPointPosition = 0;
// Настройка-default изображения описания и индикатора
mtv_title_description.setText(topnews.get(previousPointPosition).title);
ll_point_group.getChildAt(previousPointPosition).setEnabled(true);
// Настройка监听ера изменения страницы
mViewPager.setOnPageChangeListener(this);
// Настройка адаптера и соответствующих данных
newsLists = bean.data.news;
listViewAdapter = new ListViewAdapter();
mListView.setAdapter(listViewAdapter);
// mListView.addHeaderView(v); // Добавление视图 в ListView в виде заголовка 
} else {
// Получение списка новостей и добавление их в以前的 набор, обновление данных
isLoadingMore = false;
List<News> moreDataNews = bean.data.news;
newsLists.addAll(moreDataNews);
listViewAdapter.notifyDataSetChanged(); // Обновление данных
}
}
................
/**
* Использование проекта Gson для парсинга json
* @param json
*/
private TabDetailBean parserJson(String json) {
Gson gson = new Gson();
TabDetailBean bean = gson.fromJson(json, TabDetailBean.class);
moreUrl = bean.data.more;
if (TextUtils.isEmpty(moreUrl)) {
moreUrl = null;
} else {
moreUrl = ConstantUtils.server_url + moreUrl;
}
return bean;
}
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Автоматически сгенерированный метод stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Автоматически сгенерированный метод stub
}
.............
}

3. Полный код

package com.atguigu.refreshlistview;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Функция: пользовательский интерфейс для下拉刷新的ListView
*/
public class RefreshListview extends ListView {
/**
* 下拉刷新和顶部轮播图
*/
private LinearLayout headerView;
/**
* 下拉刷新控件
*/
private View ll_pull_down_refresh;
private ImageView iv_arrow;
private ProgressBar pb_status;
private TextView tv_status;
private TextView tv_time;
/**
* Высокая下拉刷新控件
*/
private int pullDownRefreshHeight;
/**
* Refresh при下拉
*/
public static final int PULL_DOWN_REFRESH = 0;
/**
* Refresh при отпускании
*/
public static final int RELEASE_REFRESH = 1;
/**
* В процессе обновления
*/
public static final int REFRESHING = 2;
/**
* Текущее состояние
*/
private int currentStatus = PULL_DOWN_REFRESH;
private Animation upAnimation;
private Animation downAnimation;
/**
* Контроллер загрузки больше
*/
private View footerView;
/**
* Высота контроллера загрузки больше
*/
private int footerViewHeight;
/**
* Было ли загружено больше
*/
private boolean isLoadMore = false;
/**
* Часть верхней ленты новостей
*/
private View topNewsView;
/**
* ListView в координатах по оси Y
*/
private int listViewOnScreenY = -1;
public RefreshListview(Context context) {
this(context, null);
}
public RefreshListview(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RefreshListview(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initHeaderView(context);
initAnimation();
initFooterView(context);
}
private void initFooterView(Context context) {
footerView = View.inflate(context, R.layout.refresh_footer, null);
footerView.measure(0, 0);
footerViewHeight = footerView.getMeasuredHeight();
footerView.setPadding(0, -footerViewHeight, 0, 0);
//Добавить footer в ListView
addFooterView(footerView);
//Слушать скольжение ListView
setOnScrollListener(new MyOnScrollListener());
}
/**
* Добавлять верхний слайдер новостей
* @param topNewsView
*/
public void addTopNewsView(View topNewsView) {
if(topNewsView != null){
this.topNewsView = topNewsView;
headerView.addView(topNewsView);
}
}
class MyOnScrollListener implements OnScrollListener{
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
//Когда静止 или инерционное скольжение
if(scrollState == OnScrollListener.SCROLL_STATE_IDLE || scrollState == OnScrollListener.SCROLL_STATE_FLING){
//и это последний видимый элемент
if(getLastVisiblePosition()>=getCount()-1){
//1. Показывать布局 загрузки более
footerView.setPadding(8,8,8,8);
//2. Изменение состояния
isLoadMore = true;
//3. Возвратный интерфейс
if(mOnRefreshListener != null){
mOnRefreshListener.onLoadMore();
}
}
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
}
}
private void initAnimation() {
upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
upAnimation.setDuration(500);
upAnimation.setFillAfter(true);
downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f);
downAnimation.setDuration(500);
downAnimation.setFillAfter(true);
}
private void initHeaderView(Context context) {
headerView = (LinearLayout) View.inflate(context, R.layout.refresh_header, null);
//下拉刷新控件
ll_pull_down_refresh = headerView.findViewById(R.id.ll_pull_down_refresh);
iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
pb_status = (ProgressBar) headerView.findViewById(R.id.pb_status);
tv_status = (TextView) headerView.findViewById(R.id.tv_status);
tv_time = (TextView) headerView.findViewById(R.id.tv_time);
//测量
ll_pull_down_refresh.measure(0, 0);
pullDownRefreshHeight = ll_pull_down_refresh.getMeasuredHeight();
//По умолчанию скрывать контроллер обновления прокрутки
// View.setPadding(0,-вtezza,0,0);//полностью скрыт
//View.setPadding(0, 0, 0, 0); // Полное отображение
ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0);
//Добавление заголовка в ListView
addHeaderView(headerView);
}
private float startY = -1;
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//1. Запись начальных координат
startY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
if (startY == -1) {
startY = ev.getY();
}
//Определение того, полностью ли отображается верхней сплошной карусели, только при полном отображении возможна обновление при下拉е
boolean isDisplayTopNews = isDisplayTopNews();
if(!isDisplayTopNews){
//Загрузка более
break;
}
//Если正在进行 обновление, то не позволяют повторно обновляться
if (currentStatus == REFRESHING) {
break;
}
//2. Прибытие на новые координаты
float endY = ev.getY();
//3. Запись расстояния скольжения
float distanceY = endY - startY;
if (distanceY > 0) { // В下拉е
//int paddingTop = -высота контроллера + distanceY;
int paddingTop = (int) (-pullDownRefreshHeight + distanceY);
if (paddingTop < 0 && currentStatus != PULL_DOWN_REFRESH) {
//Состояние обновления при下拉
currentStatus = PULL_DOWN_REFRESH;
//Обновление состояния
refreshViewState();
} else if (paddingTop > 0 && currentStatus != RELEASE_REFRESH) {
//Состояние обновления при отпускании
currentStatus = RELEASE_REFRESH;
//Обновление состояния
refreshViewState();
}
ll_pull_down_refresh.setPadding(0, paddingTop, 0, 0);
//View.setPadding(0, paddingTop, 0, 0); // Динамически отображать контроллер обновления прокрутки
}
break;
case MotionEvent.ACTION_UP:
startY = -1;
if (currentStatus == PULL_DOWN_REFRESH) {
// View.setPadding(0,-вtezza,0,0);//полностью скрыт
ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0);
} else if (currentStatus == RELEASE_REFRESH) {
//установить состояние как «в процессе обновления»
currentStatus = REFRESHING;
refreshViewState();
// View.setPadding(0,0,0,0);//полностью отображается
ll_pull_down_refresh.setPadding(0, 0, 0, 0);
//回调接口
if (mOnRefreshListener != null) {
mOnRefreshListener.onPullDownRefresh();
}
}
break;
}
return super.onTouchEvent(ev);
}
/**
* Определить, полностью ли отображается верхний рекламный баннер
* Когда координата Y ListView на экране меньше или равна координате Y верхнего рекламного баннера, верхний рекламный баннер полностью отображается
* @return
*/
private boolean isDisplayTopNews() {
if(topNewsView != null){
//1.得到ListView在屏幕上的坐标
int[] location = new int[2];
if(listViewOnScreenY == -1){
getLocationOnScreen(location);
listViewOnScreenY = location[1];
}
//2.得到顶部轮播图在屏幕上的坐标
topNewsView.getLocationOnScreen(location);
int topNewsViewOnScreenY = location[1];
// if(listViewOnScreenY <= topNewsViewOnScreenY){
// return true;
// }else{
// return false;
// }
return listViewOnScreenY <= topNewsViewOnScreenY;
} else {
return true;
}
}
private void refreshViewState() {
switch (currentStatus) {
case PULL_DOWN_REFRESH://Состояние прокрутки вниз
iv_arrow.startAnimation(downAnimation);
tv_status.setText("Прокрутка вниз...");
break;
case RELEASE_REFRESH://Состояние обновления при отпущенных руках
iv_arrow.startAnimation(upAnimation);
tv_status.setText("Руки отпущены для обновления...");
break;
case REFRESHING://Состояние обновления
tv_status.setText("Идет обновление...");
pb_status.setVisibility(VISIBLE);
iv_arrow.clearAnimation();
iv_arrow.setVisibility(GONE);
break;
}
}
/**
* При успешном и неуспешном соединении с сетью вызывается该方法
* Восстановить состояние пользователя
*
* @param sucess
*/
public void onRefreshFinish(boolean sucess) {
if(isLoadMore){
//Загрузка более
isLoadMore = false;
//Скрыть макет загрузки более
footerView.setPadding(0, -footerViewHeight, 0, 0);
} else {
//Прокрутка вниз
tv_status.setText("Прокрутка вниз...");
currentStatus = PULL_DOWN_REFRESH;
iv_arrow.clearAnimation();
pb_status.setVisibility(GONE);
iv_arrow.setVisibility(VISIBLE);
//Скрыть компонент прокрутки вниз
ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0);
if (sucess) {
//Установить последнее обновление времени
tv_time.setText("Последнее обновление времени: " + getSystemTime());
}
}
}
/**
* Получить текущее время Android системы
*
* @return
*/
private String getSystemTime() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
return format.format(new Date());
}
/**
* Наблюдать за обновлением компонента
*/
public interface OnRefreshListener {
/**
* Когда обновление прокрутки вниз вызывается этот метод
*/
public void onPullDownRefresh();
/**
Когда загружается больше, вызывается этот метод
*/
public void onLoadMore();
}
private OnRefreshListener mOnRefreshListener;
/**
* Установить监听 обновление, установлено извне
*/
public void setOnRefreshListener(OnRefreshListener l) {
this.mOnRefreshListener = l;
}
}

Указанное выше — это介绍 от редактора给大家 о фейковом下拉 обновлении / прокрутке для загрузки больше новостей для Android, надеюсь, это поможет вам. Если у вас есть какие-либо вопросы, пожалуйста, оставьте комментарий, редактор ответит вам в ближайшее время. В этом также очень благодарим всех за поддержку呐喊 учебника сайта!

Заявление: содержимое этой статьи взято из Интернета, авторские права принадлежат соответствующему автору, материал предоставлен пользователями Интернета в качестве добровольного вклада и загружен самостоятельно, сайт не имеет права собственности на него, не прошел редактирование в ручном режиме и не несет ответственности за связанные с этим юридические обязательства. Если вы обнаружите контент,涉嫌侵犯版权, пожалуйста, отправьте письмо по адресу: notice#oldtoolbag.com (во время отправки письма замените # на @) для сообщения о нарушении,并提供 соответствующие доказательства. При обнаружении факта нарушения мы немедленно удалим涉嫌侵权的内容.

Давайте посмотрим, что вам понравится