Android ListView实现上拉加载下拉刷新和滑动删除功能

作者:冷不冷 时间:2021-09-24 19:08:04 

最近项目需要用到可以滑动删除并且带有上拉加载下拉刷新的Listview,查阅了一些资料,大多都是在SwipeMenuListView的基础上去添加头部和底部View,来扩展上拉加载和下拉刷新的功能,不过需要手动的去绘制UI及处理一些动画效果.用起来也不是特别方便.刚好项目中用到PulltorefreshLibrary库,就尝试着扩展了一个PullToRefreshSwipeMenuListView类来实现需求.先看一下效果:

Android ListView实现上拉加载下拉刷新和滑动删除功能

实现步骤

一、组合Pulltorefresh与SwipeMenuListView

PulltorefreshLibrary库中包含很多种可以上拉加载下拉刷新的控件,经常用到的比如PullToRefreshListView,PullToRefreshGridView,PullToRefreshScrollView,它们的实现方式类似,本质上是在控件外部添加父布局,父布局中去添加控件的头部和底部View,来实现上拉加载下拉刷新的功能,所以扩展性很强.照猫画虎,copy一份PullToRefreshListView,对他做一些处理.


protected ListView createListView(Context context, AttributeSet attrs) {
final ListView lv;
if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
 lv = new InternalListViewSDK9(context, attrs);
} else {
 lv = new InternalListView(context, attrs);
}
return lv;
}

找到这部分代码,简单的做下修改:


protected SwipeMenuListView createListView(Context context, AttributeSet attrs) {
final SwipeMenuListView lv;
lv = new SwipeMenuListView(context, attrs);
return lv;
}

为什么要copy一份PullToRefreshListView而不是其他的呢?因为SwipeMenuListView是继承自ListView的(看名字就可以发现),修改起来比较方便.为什么要修改这部分代码呢?往下看.找一下引用这部分代码的地方:


@Override
protected ListView createRefreshableView(Context context, AttributeSet attrs) {
ListView lv = createListView(context, attrs);
// Set it to this so it can be used in ListActivity/ListFragment
lv.setId(android.R.id.list);
return lv;
}

是继承父类实现的方法,打开父类的该方法:


/**
* This is implemented by derived classes to return the created View. If you
* need to use a custom View (such as a custom ListView), override this
* method and return an instance of your custom class.
* <p/>
* Be sure to set the ID of the view in this method, especially if you're
* using a ListActivity or ListFragment.
*
* @param context Context to create view with
* @param attrs AttributeSet from wrapped class. Means that anything you
*  include in the XML layout declaration will be routed to the
*  created View
* @return New instance of the Refreshable View
*/
protected abstract T createRefreshableView(Context context, AttributeSet attrs);

看一 * 释,大概的意思是说,如果需要一个自定义的上拉加载下拉刷新View,可以返回该自定义View.并且返回值是T,一个泛型,说的很明白.看一下这个方法的引用mRefreshableView = createRefreshableView(context, attrs);看命名就知道,这个方法最终返回的是需要上拉加载下拉刷新功能的View.

感觉差不多可以了,来试一下,看一下效果:

Android ListView实现上拉加载下拉刷新和滑动删除功能

好像效果不是很理想,有很多问题,比如滑动删除的时候可以上拉下拉,上拉时没有底部View.接下来来解决这些问题.

二、解决滑动冲突及相关问题

先来解决为什么没有底部View的问题,看一下copy过来修改过的PullToRefreshSwipeMenuListView类和PullToRefreshListView类,对比一下到底有什么区别,使得PullToRefreshSwipeMenuListView没有底部View,在PullToRefreshSwipeMenuListView中只修改了一个部分,就是把之前返回的InternalListView替换成了SwipeMenuListView,显然问题出现在InternalListView上,查看一下InternalListView(很容易找,是个内部类),可以看到这部分代码:


@Override
public void setAdapter(ListAdapter adapter) {
 // Add the Footer View at the last possible moment
 if (null != mLvFooterLoadingFrame && !mAddedLvFooter) {
 addFooterView(mLvFooterLoadingFrame, null, false);
 mAddedLvFooter = true;
 }

super.setAdapter(adapter);
}

底部View是在InternalListView调用setAdapter方法时添加上的,那头部View呢?查找一下,找到如下代码:


@Override
protected void handleStyledAttributes(TypedArray a) {
super.handleStyledAttributes(a);

mListViewExtrasEnabled = a.getBoolean(com.handmark.pulltorefresh.library.R.styleable.PullToRefresh_ptrListViewExtrasEnabled, true);

if (mListViewExtrasEnabled) {
 final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
  FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);

// Create Loading Views ready for use later
 FrameLayout frame = new FrameLayout(getContext());
 mHeaderLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_START, a);
 mHeaderLoadingView.setVisibility(View.GONE);
 // FrameLayout添加头View
 frame.addView(mHeaderLoadingView, lp);
 // 添加头部View
 mRefreshableView.addHeaderView(frame, null, false);

mLvFooterLoadingFrame = new FrameLayout(getContext());
 mFooterLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_END, a);
 mFooterLoadingView.setVisibility(View.GONE);
 // FrameLayout添加底部View
 mLvFooterLoadingFrame.addView(mFooterLoadingView, lp);
 // 添加底部View
 ...
 /**
 * If the value for Scrolling While Refreshing hasn't been
 * explicitly set via XML, enable Scrolling While Refreshing.
 */
 if (!a.hasValue(com.handmark.pulltorefresh.library.R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) {
 setScrollingWhileRefreshingEnabled(true);
 }
}
}

发现头部是在初始化的时候被添加上,而底部并没有添加(代码中…的部分),InternalListView在setAdapter方法中,添加上了底部,SwipeMenuListView中并没有相关的处理,所以在…处添加代码
mRefreshableView.addFooterView(mLvFooterLoadingFrame, null, false);把底部加上,之前发现的没有底部的问题就解决了(当然也可以仿照InternalListView去修改一下SwipeMenuListView,不过比较麻烦,这里就不去做了)

接下来处理一下滑动删除时,可以进行上拉下拉操作的问题,很明显是滑动冲突的问题,想一下,当滑动删除时,不希望进行上拉下拉操作,而PullToRefreshSwipeMenuListView本身是一个ViewGroup,所以当滑动删除时,屏蔽掉父布局的滑动事件就可以了,打开SwipeMenuListView,在滑动事件中做一下处理即可:


case MotionEvent.ACTION_MOVE:
 float dy = Math.abs((ev.getY() - mDownY));
 float dx = Math.abs((ev.getX() - mDownX));
 if (mTouchState == TOUCH_STATE_X) {
  if (mTouchView != null) {
  mTouchView.onSwipe(ev);
  }
  getSelector().setState(new int[]{0});
  ev.setAction(MotionEvent.ACTION_CANCEL);
  super.onTouchEvent(ev);
  // 处理滑动冲突,当处于滑动删除状态时,请求父布局不处理滑动事件
  requestDisallowInterceptTouchEvent(true);
  return true;
 } else if (mTouchState == TOUCH_STATE_NONE) {
  if (Math.abs(dy) > MAX_Y) {
  mTouchState = TOUCH_STATE_Y;
  } else if (dx > MAX_X) {
  mTouchState = TOUCH_STATE_X;
  if (mOnSwipeListener != null) {
   mOnSwipeListener.onSwipeStart(mTouchPosition);
  }
  }
 }
 break;

很简单,就不多做说明了,不太清楚点击事件分发的童鞋,可以去查阅一下材料,这样一个带有上拉加载下拉刷新可滑动删除的ListView就基本完工了.

三、完整代码

PullToRefreshSwipeMenuListView:


package swipemenulistview;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ListAdapter;
import android.widget.ListView;

import com.handmark.pulltorefresh.library.LoadingLayoutProxy;
import com.handmark.pulltorefresh.library.PullToRefreshAdapterViewBase;
import com.handmark.pulltorefresh.library.internal.LoadingLayout;

/**
* Created by junweiliu on 16/10/12.
*/
public class PullToRefreshSwipeMenuListView extends PullToRefreshAdapterViewBase<ListView> {

private LoadingLayout mHeaderLoadingView;
private LoadingLayout mFooterLoadingView;

private FrameLayout mLvFooterLoadingFrame;

private boolean mListViewExtrasEnabled;

public PullToRefreshSwipeMenuListView(Context context) {
super(context);
}

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

public PullToRefreshSwipeMenuListView(Context context, Mode mode) {
super(context, mode);
}

public PullToRefreshSwipeMenuListView(Context context, Mode mode, AnimationStyle style) {
super(context, mode, style);
}

@Override
public final Orientation getPullToRefreshScrollDirection() {
return Orientation.VERTICAL;
}

@Override
protected void onRefreshing(final boolean doScroll) {
/**
 * If we're not showing the Refreshing view, or the list is empty, the
 * the header/footer views won't show so we use the normal method.
 */
ListAdapter adapter = mRefreshableView.getAdapter();
if (!mListViewExtrasEnabled || !getShowViewWhileRefreshing() || null == adapter || adapter.isEmpty()) {
 super.onRefreshing(doScroll);
 return;
}

super.onRefreshing(false);

final LoadingLayout origLoadingView, listViewLoadingView, oppositeListViewLoadingView;
final int selection, scrollToY;

switch (getCurrentMode()) {
 case MANUAL_REFRESH_ONLY:
 case PULL_FROM_END:
 origLoadingView = getFooterLayout();
 listViewLoadingView = mFooterLoadingView;
 oppositeListViewLoadingView = mHeaderLoadingView;
 selection = mRefreshableView.getCount() - 1;
 scrollToY = getScrollY() - getFooterSize();
 break;
 case PULL_FROM_START:
 default:
 origLoadingView = getHeaderLayout();
 listViewLoadingView = mHeaderLoadingView;
 oppositeListViewLoadingView = mFooterLoadingView;
 selection = 0;
 scrollToY = getScrollY() + getHeaderSize();
 break;
}

// Hide our original Loading View
origLoadingView.reset();
origLoadingView.hideAllViews();

// Make sure the opposite end is hidden too
oppositeListViewLoadingView.setVisibility(View.GONE);

// Show the ListView Loading View and set it to refresh.
listViewLoadingView.setVisibility(View.VISIBLE);
listViewLoadingView.refreshing();

if (doScroll) {
 // We need to disable the automatic visibility changes for now
 disableLoadingLayoutVisibilityChanges();

// We scroll slightly so that the ListView's header/footer is at the
 // same Y position as our normal header/footer
 setHeaderScroll(scrollToY);

// Make sure the ListView is scrolled to show the loading
 // header/footer
 mRefreshableView.setSelection(selection);

// Smooth scroll as normal
 smoothScrollTo(0);
}
}

@Override
protected void onReset() {
/**
 * If the extras are not enabled, just call up to super and return.
 */
if (!mListViewExtrasEnabled) {
 super.onReset();
 return;
}

final LoadingLayout originalLoadingLayout, listViewLoadingLayout;
final int scrollToHeight, selection;
final boolean scrollLvToEdge;

switch (getCurrentMode()) {
 case MANUAL_REFRESH_ONLY:
 case PULL_FROM_END:
 originalLoadingLayout = getFooterLayout();
 listViewLoadingLayout = mFooterLoadingView;
 selection = mRefreshableView.getCount() - 1;
 scrollToHeight = getFooterSize();
 scrollLvToEdge = Math.abs(mRefreshableView.getLastVisiblePosition() - selection) <= 1;
 break;
 case PULL_FROM_START:
 default:
 originalLoadingLayout = getHeaderLayout();
 listViewLoadingLayout = mHeaderLoadingView;
 scrollToHeight = -getHeaderSize();
 selection = 0;
 scrollLvToEdge = Math.abs(mRefreshableView.getFirstVisiblePosition() - selection) <= 1;
 break;
}

// If the ListView header loading layout is showing, then we need to
// flip so that the original one is showing instead
if (listViewLoadingLayout.getVisibility() == View.VISIBLE) {

// Set our Original View to Visible
 originalLoadingLayout.showInvisibleViews();

// Hide the ListView Header/Footer
 listViewLoadingLayout.setVisibility(View.GONE);

/**
 * Scroll so the View is at the same Y as the ListView
 * header/footer, but only scroll if: we've pulled to refresh, it's
 * positioned correctly
 */
 if (scrollLvToEdge && getState() != State.MANUAL_REFRESHING) {
 mRefreshableView.setSelection(selection);
 setHeaderScroll(scrollToHeight);
 }
}

// Finally, call up to super
super.onReset();
}

@Override
protected LoadingLayoutProxy createLoadingLayoutProxy(final boolean includeStart, final boolean includeEnd) {
LoadingLayoutProxy proxy = super.createLoadingLayoutProxy(includeStart, includeEnd);

if (mListViewExtrasEnabled) {
 final Mode mode = getMode();

if (includeStart && mode.showHeaderLoadingLayout()) {
 proxy.addLayout(mHeaderLoadingView);
 }
 if (includeEnd && mode.showFooterLoadingLayout()) {
 proxy.addLayout(mFooterLoadingView);
 }
}

return proxy;
}

protected SwipeMenuListView createListView(Context context, AttributeSet attrs) {
final SwipeMenuListView lv;
// if (VERSION.SDK_INT >= VERSION_CODES.GINGERBREAD) {
//  lv = new InternalListViewSDK9(context, attrs);
// } else {
//  lv = new InternalListView(context, attrs);
// }
lv = new SwipeMenuListView(context, attrs);
return lv;
}

@Override
protected ListView createRefreshableView(Context context, AttributeSet attrs) {
ListView lv = createListView(context, attrs);

// Set it to this so it can be used in ListActivity/ListFragment
lv.setId(android.R.id.list);
return lv;
}

@Override
protected void handleStyledAttributes(TypedArray a) {
super.handleStyledAttributes(a);

mListViewExtrasEnabled = a.getBoolean(com.handmark.pulltorefresh.library.R.styleable.PullToRefresh_ptrListViewExtrasEnabled, true);

if (mListViewExtrasEnabled) {
 final FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
  FrameLayout.LayoutParams.WRAP_CONTENT, Gravity.CENTER_HORIZONTAL);

// Create Loading Views ready for use later
 FrameLayout frame = new FrameLayout(getContext());
 mHeaderLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_START, a);
 mHeaderLoadingView.setVisibility(View.GONE);
 frame.addView(mHeaderLoadingView, lp);
 mRefreshableView.addHeaderView(frame, null, false);

mLvFooterLoadingFrame = new FrameLayout(getContext());
 mFooterLoadingView = createLoadingLayout(getContext(), Mode.PULL_FROM_END, a);
 mFooterLoadingView.setVisibility(View.GONE);
 mLvFooterLoadingFrame.addView(mFooterLoadingView, lp);
 // 添加底部加载view
 mRefreshableView.addFooterView(mLvFooterLoadingFrame, null, false);

/**
 * If the value for Scrolling While Refreshing hasn't been
 * explicitly set via XML, enable Scrolling While Refreshing.
 */
 if (!a.hasValue(com.handmark.pulltorefresh.library.R.styleable.PullToRefresh_ptrScrollingWhileRefreshingEnabled)) {
 setScrollingWhileRefreshingEnabled(true);
 }
}
}

}

SwipeMenuListView:


package swipemenulistview;

import android.content.Context;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.ListAdapter;
import android.widget.ListView;

/**
* @author baoyz
* @date 2014-8-18
*/
public class SwipeMenuListView extends ListView {

private static final int TOUCH_STATE_NONE = 0;
private static final int TOUCH_STATE_X = 1;
private static final int TOUCH_STATE_Y = 2;

public static final int DIRECTION_LEFT = 1;
public static final int DIRECTION_RIGHT = -1;
private int mDirection = 1;//swipe from right to left by default

private int MAX_Y = 5;
private int MAX_X = 3;
private float mDownX;
private float mDownY;
private int mTouchState;
private int mTouchPosition;
private SwipeMenuLayout mTouchView;
private OnSwipeListener mOnSwipeListener;

private SwipeMenuCreator mMenuCreator;
private OnMenuItemClickListener mOnMenuItemClickListener;
private Interpolator mCloseInterpolator;
private Interpolator mOpenInterpolator;

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

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

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

private void init() {
MAX_X = dp2px(MAX_X);
MAX_Y = dp2px(MAX_Y);
mTouchState = TOUCH_STATE_NONE;
}

@Override
public void setAdapter(ListAdapter adapter) {
super.setAdapter(new SwipeMenuAdapter(getContext(), adapter) {
 @Override
 public void createMenu(SwipeMenu menu) {
 if (mMenuCreator != null) {
  mMenuCreator.create(menu);
 }
 }

@Override
 public void onItemClick(SwipeMenuView view, SwipeMenu menu,
    int index) {
 boolean flag = false;
 if (mOnMenuItemClickListener != null) {
  flag = mOnMenuItemClickListener.onMenuItemClick(
   view.getPosition(), menu, index);
 }
 if (mTouchView != null && !flag) {
  mTouchView.smoothCloseMenu();
 }
 }
});
}

public void setCloseInterpolator(Interpolator interpolator) {
mCloseInterpolator = interpolator;
}

public void setOpenInterpolator(Interpolator interpolator) {
mOpenInterpolator = interpolator;
}

public Interpolator getOpenInterpolator() {
return mOpenInterpolator;
}

public Interpolator getCloseInterpolator() {
return mCloseInterpolator;
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
 return super.onTouchEvent(ev);
int action = MotionEventCompat.getActionMasked(ev);
action = ev.getAction();
switch (action) {
 case MotionEvent.ACTION_DOWN:
 int oldPos = mTouchPosition;
 mDownX = ev.getX();
 mDownY = ev.getY();
 mTouchState = TOUCH_STATE_NONE;

mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());

if (mTouchPosition == oldPos && mTouchView != null
  && mTouchView.isOpen()) {
  mTouchState = TOUCH_STATE_X;
  mTouchView.onSwipe(ev);
  return true;
 }

View view = getChildAt(mTouchPosition - getFirstVisiblePosition());

if (mTouchView != null && mTouchView.isOpen()) {
  mTouchView.smoothCloseMenu();
  mTouchView = null;
  // return super.onTouchEvent(ev);
  // try to cancel the touch event
  MotionEvent cancelEvent = MotionEvent.obtain(ev);
  cancelEvent.setAction(MotionEvent.ACTION_CANCEL);
  onTouchEvent(cancelEvent);
  return true;
 }
 if (view instanceof SwipeMenuLayout) {
  mTouchView = (SwipeMenuLayout) view;
  mTouchView.setSwipeDirection(mDirection);
 }
 if (mTouchView != null) {
  mTouchView.onSwipe(ev);
 }
 break;
 case MotionEvent.ACTION_MOVE:
 float dy = Math.abs((ev.getY() - mDownY));
 float dx = Math.abs((ev.getX() - mDownX));
 if (mTouchState == TOUCH_STATE_X) {
  if (mTouchView != null) {
  mTouchView.onSwipe(ev);
  }
  getSelector().setState(new int[]{0});
  ev.setAction(MotionEvent.ACTION_CANCEL);
  super.onTouchEvent(ev);
  // 处理滑动冲突,当处于滑动删除状态时,请求父布局不处理滑动事件
  requestDisallowInterceptTouchEvent(true);
  return true;
 } else if (mTouchState == TOUCH_STATE_NONE) {
  if (Math.abs(dy) > MAX_Y) {
  mTouchState = TOUCH_STATE_Y;
  } else if (dx > MAX_X) {
  mTouchState = TOUCH_STATE_X;
  if (mOnSwipeListener != null) {
   mOnSwipeListener.onSwipeStart(mTouchPosition);
  }
  }
 }
 break;
 case MotionEvent.ACTION_UP:
 requestDisallowInterceptTouchEvent(false);
 if (mTouchState == TOUCH_STATE_X) {
  if (mTouchView != null) {
  mTouchView.onSwipe(ev);
  if (!mTouchView.isOpen()) {
   mTouchPosition = -1;
   mTouchView = null;
  }
  }
  if (mOnSwipeListener != null) {
  mOnSwipeListener.onSwipeEnd(mTouchPosition);
  }
  ev.setAction(MotionEvent.ACTION_CANCEL);
  super.onTouchEvent(ev);
  return true;
 }
 break;
}
return super.onTouchEvent(ev);
}

public void smoothOpenMenu(int position) {
if (position >= getFirstVisiblePosition()
 && position <= getLastVisiblePosition()) {
 View view = getChildAt(position - getFirstVisiblePosition());
 if (view instanceof SwipeMenuLayout) {
 mTouchPosition = position;
 if (mTouchView != null && mTouchView.isOpen()) {
  mTouchView.smoothCloseMenu();
 }
 mTouchView = (SwipeMenuLayout) view;
 mTouchView.setSwipeDirection(mDirection);
 mTouchView.smoothOpenMenu();
 }
}
}

private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
 getContext().getResources().getDisplayMetrics());
}

public void setMenuCreator(SwipeMenuCreator menuCreator) {
this.mMenuCreator = menuCreator;
}

public void setOnMenuItemClickListener(
 OnMenuItemClickListener onMenuItemClickListener) {
this.mOnMenuItemClickListener = onMenuItemClickListener;
}

public void setOnSwipeListener(OnSwipeListener onSwipeListener) {
this.mOnSwipeListener = onSwipeListener;
}

public static interface OnMenuItemClickListener {
boolean onMenuItemClick(int position, SwipeMenu menu, int index);
}

public static interface OnSwipeListener {
void onSwipeStart(int position);

void onSwipeEnd(int position);
}

public void setSwipeDirection(int direction) {
mDirection = direction;
}
}

MainActivity:


package com.example.junweiliu.pulltorefreshswipemenulistviewdemo;

import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.util.TypedValue;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.Toast;

import com.handmark.pulltorefresh.library.PullToRefreshBase;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import swipemenulistview.PullToRefreshSwipeMenuListView;
import swipemenulistview.SwipeMenu;
import swipemenulistview.SwipeMenuCreator;
import swipemenulistview.SwipeMenuItem;
import swipemenulistview.SwipeMenuListView;

public class MainActivity extends AppCompatActivity {
/**
* 控件
*/
private PullToRefreshSwipeMenuListView mPullToRefreshSwipeMenuListView;
/**
* 适配器
*/
private SimpleAdapter mAdapter;
/**
* 数据源
*/
List<Map<String, Object>> datas = new ArrayList<Map<String, Object>>();
/**
* 信息
*/
private String[] message = {"数据0", "数据1", "数据2", "数据3", "数据4", "数据5", "数据6", "数据7", "数据8", "数据9", "数据10"};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
initView();

}

/**
* 初始化控件
*/
private void initView() {
mPullToRefreshSwipeMenuListView = (PullToRefreshSwipeMenuListView) findViewById(R.id.psl_demo);
mAdapter = new SimpleAdapter(this, datas, R.layout.item_adapter, new String[]{"message"}, new int[]{R.id.tv_message});
mPullToRefreshSwipeMenuListView.setMode(PullToRefreshBase.Mode.BOTH);
mPullToRefreshSwipeMenuListView.setAdapter(mAdapter);
// 创建删除滑块
SwipeMenuCreator creator = new SwipeMenuCreator() {
 @Override
 public void create(SwipeMenu menu) {
 SwipeMenuItem deleteItem = new SwipeMenuItem(
  getApplicationContext());
 deleteItem.setBackground(new ColorDrawable(Color.rgb(0xFF,
  0x20, 0x20)));
 deleteItem.setWidth(dp2px(63));
//  deleteItem.setIcon(R.drawable.ic_delete);
 deleteItem.setTitle("删除");
 deleteItem.setTitleSize(14);
 deleteItem.setTitleColor(Color.WHITE);
 menu.addMenuItem(deleteItem);
 }
};
// 设置滑块
((SwipeMenuListView) mPullToRefreshSwipeMenuListView.getRefreshableView()).setMenuCreator(creator);
// 滑块点击事件
((SwipeMenuListView) mPullToRefreshSwipeMenuListView.getRefreshableView()).setOnMenuItemClickListener(new SwipeMenuListView.OnMenuItemClickListener() {
 @Override
 public boolean onMenuItemClick(int position, SwipeMenu menu, int index) {
 switch (index) {
  case 0:
  Toast.makeText(MainActivity.this, "删除我了" + position, Toast.LENGTH_SHORT).show();
  break;
 }
 return false;
 }
});
// 滑动监听
((SwipeMenuListView) mPullToRefreshSwipeMenuListView.getRefreshableView()).setOnSwipeListener(new SwipeMenuListView.OnSwipeListener() {

@Override
 public void onSwipeStart(int position) {
 }

@Override
 public void onSwipeEnd(int position) {
 }
});
// 刷新加载事件
mPullToRefreshSwipeMenuListView.setOnRefreshListener(new PullToRefreshBase.OnRefreshListener2<ListView>() {
 @Override
 public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) {
 new Handler(new Handler.Callback() {
  @Override
  public boolean handleMessage(Message message) {
  Toast.makeText(MainActivity.this, "刷新成功", Toast.LENGTH_SHORT).show();
  mPullToRefreshSwipeMenuListView.onRefreshComplete();
  return false;
  }
 }).sendEmptyMessageDelayed(1, 1000);
 }

@Override
 public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) {
 new Handler(new Handler.Callback() {
  @Override
  public boolean handleMessage(Message message) {
  Toast.makeText(MainActivity.this, "加载成功", Toast.LENGTH_SHORT).show();
  mPullToRefreshSwipeMenuListView.onRefreshComplete();
  return false;
  }
 }).sendEmptyMessageDelayed(2, 1000);
 }
});
// 点击事件
mPullToRefreshSwipeMenuListView.getRefreshableView().setOnItemClickListener(new AdapterView.OnItemClickListener() {
 @Override
 public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {

}
});

}

/**
* 初始化数据
*/
private void initData() {
for (int i = 0; i < message.length; i++) {
 Map<String, Object> data = new HashMap<String, Object>();
 data.put("message", message[i]);
 datas.add(data);
}
}

/**
* dp转px
*
* @param dp
* @return
*/
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
 getResources().getDisplayMetrics());
}

}

activity_main:


<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.junweiliu.pulltorefreshswipemenulistviewdemo.MainActivity">
<!--上拉加载下拉刷新滑动删除控件-->
<swipemenulistview.PullToRefreshSwipeMenuListView
 android:id="@+id/psl_demo"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
>
</swipemenulistview.PullToRefreshSwipeMenuListView>
</RelativeLayout>

item_adapter:


<?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="match_parent"
 android:gravity="center"
 android:orientation="vertical">
<TextView
 android:id="@+id/tv_message"
 android:layout_width="wrap_content"
 android:layout_height="match_parent"
 android:paddingBottom="30dp"
 android:paddingTop="30dp"
 android:text="数据"
 android:textColor="@android:color/black"
 android:textSize="16sp"/>
</LinearLayout>

本文已经被整理到《Android下拉刷新上拉加载效果》,欢迎大家学习研究。

标签:ListView,上拉加载,下拉刷新,滑动删除
0
投稿

猜你喜欢

  • Java实现一个简易聊天室流程

    2023-10-02 19:55:53
  • java控制台输出百分比进度条示例

    2023-08-21 22:58:20
  • Android游戏开发学习①弹跳小球实现方法

    2022-04-27 02:48:14
  • C#泛型的逆变协变之个人理解

    2021-05-28 16:33:03
  • macOS上使用gperftools定位Java内存泄漏问题及解决方案

    2023-03-02 11:42:38
  • C#委托与冒泡排序实例

    2022-05-03 13:26:21
  • C#实现微信跳一跳小游戏的自动跳跃助手开发实战

    2022-12-11 02:49:08
  • Java 中的字符串常量池详解

    2023-08-15 04:43:45
  • Android通过自定义View实现随机验证码

    2022-10-24 07:16:19
  • Java文件上传与文件下载实现方法详解

    2023-11-20 12:28:45
  • 详解Spring boot/Spring 统一错误处理方案的使用

    2023-11-24 12:56:07
  • resty upload无需依赖的文件上传与下载

    2023-01-17 14:54:31
  • C# 三种序列化方法分享

    2022-09-21 03:43:05
  • C#日期格式强制转换方法(推荐)

    2022-09-19 10:24:57
  • 论Java Web应用中调优线程池的重要性

    2023-06-13 04:56:27
  • Java算法之最长公共子序列问题(LCS)实例分析

    2022-12-06 08:31:42
  • Java 多线程并发ReentrantLock

    2022-02-23 11:53:23
  • c# RSA非对称加解密及XML&PEM格式互换方案

    2022-07-10 12:19:31
  • Java实现堆排序(大根堆)的示例代码

    2023-09-13 15:24:01
  • IDEA修改idea64.exe.vmoptions文件以及解决coding卡顿问题

    2022-11-02 00:36:04
  • asp之家 软件编程 m.aspxhome.com