GVKun编程网logo

Android使用Item Swipemenulistview实现仿QQ侧滑删除功能

15

这篇文章主要围绕Android使用ItemSwipemenulistview实现仿QQ侧滑删除功能展开,旨在为您提供一份详细的参考资料。我们将全面介绍Android使用ItemSwipemenulis

这篇文章主要围绕Android使用Item Swipemenulistview实现仿QQ侧滑删除功能展开,旨在为您提供一份详细的参考资料。我们将全面介绍Android使用Item Swipemenulistview实现仿QQ侧滑删除功能,同时也会为您带来android listview item点击时更改textview的颜色 代码中实现、Android ListView实现上拉加载下拉刷新和滑动删除功能、Android ListView实现仿iPhone实现左滑删除按钮的简单实例、Android ListView滑动删除操作(SwipeListView)的实用方法。

本文目录一览:

Android使用Item Swipemenulistview实现仿QQ侧滑删除功能

Android使用Item Swipemenulistview实现仿QQ侧滑删除功能

 大家都用过QQ,肯定有人好奇QQ滑动删除Item的效果是怎样实现的,其实我们使用Swipemenulistview就可以简单的实现。先看看我们项目中的效果:

   使用的时候可以把Swipemenulistview作为一个library,也可以把Swipemenulistview的源码拷贝到我们的项目中来,使用步骤大致可以分为三步:1.在布局中配置;2.在Java代码中初始化配置;3.按钮点击事件的处理

 1.在布局中配置

 xml布局文件中只需要简单使用这个自定义的ListView就行了,需要注意的是必须使用类的全名。

 <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"> 
 <com.baoyz.swipemenulistview.SwipeMenuListView 
  android:id="@+id/listView" 
  android:layout_width="match_parent" 
  android:layout_height="match_parent" /> 
 </RelativeLayout> 

2.在java代码中初始化菜单配置

 SwipeMenuCreator creator = new SwipeMenuCreator(){ 
 <span>  </span>@Override 
 public void create(SwipeMenu menu) { 
  //创建一个"打开"功能菜单 
  SwipeMenuItem openItem = new SwipeMenuItem(context); 
  // 设置菜单的背景 
  openItem.setBackground(new ColorDrawable(Color.rgb(0xC9,0xC9,0xCE))); 
  // 宽度:菜单的宽度是一定要有的,否则不会显示 
  openItem.setWidth(180); 
  // 菜单标题 
  openItem.setTitle("打开"); 
  // 标题文字大小 
  openItem.setTitleSize(16); 
  // 标题的颜色 
  openItem.setTitleColor(Color.WHITE); 
  // 添加到menu 
  menu.addMenuItem(openItem); 
  //创建一个"打开"功能菜单 
  SwipeMenuItem deleteItem = new SwipeMenuItem(context); 
  // 设置菜单的背景 
  deleteItem.setBackground(new ColorDrawable(Color.rgb(0xF9,0x3F,0x25))); 
  // 宽度:菜单的宽度是一定要有的,否则不会显示 
  deleteItem.setWidth(180); 
  // 菜单标题 
  deleteItem.setTitle("删除"); 
  // 标题文字大小 
  deleteItem.setTitleSize(16); 
  // 标题的颜色 
  deleteItem.setTitleColor(Color.WHITE); 
  // 给菜单设置一个图标 
  //deleteItem.setIcon(R.drawable.ic_delete); 
  // 添加到menu 
  menu.addMenuItem(deleteItem); 
 } 
 }; 
 // 不要忘记了 
 mListView.setMenuCreator(creator); 

 这里是添加了两个菜单按钮,一个“打开”,一个“删除”。

 3.菜单按钮点击事件的处理

 mListView.setonMenuItemClickListener(new OnMenuItemClickListener() { 
 @Override 
 public void onMenuItemClick(int position,SwipeMenu menu,int index) { 
  switch (index) { 
  case 0: 
  Toast.makeText(context,"打开第" + mArrayList.get(position) + "个条目",0).show(); 
  break; 
  case 1: 
  Toast.makeText(context,"删除第" + mArrayList.get(position) + "个条目",0).show(); 
  mArrayList.remove(position); 
  mAdapter.notifyDataSetChanged(); 
  break; 
  } 
 } 
 }); 

 最后的效果图如下:

以上所述是小编给大家介绍的Android使用Item Swipemenulistview实现仿QQ侧滑删除功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

android listview item点击时更改textview的颜色 代码中实现

android listview item点击时更改textview的颜色 代码中实现

listview点击时更改textview文字颜色很多网上的资料都已经介绍,本人也在实际中xml文件中已实现。

但是将xml文件中设置的textcolor放到代码就确不起作用了,目前仍未找到原因,希望知道原因的大神指点下。

不过经过一天的努力还是找到了解决办法,就是自定义按钮文字变色类

ColorStateList

代码:

new ColorStateList(
                new int[][]{
                        new int[]{android.R.attr.state_pressed}, //1
                        new int[]{-android.R.attr.state_focused}, //2
                        new int[]{android.R.attr.state_selected, android.R.attr.state_pressed} //3
                },
                new int[] {
                    Color.GREEN, //1
                    Color.WHITE, //2
                    Color.BLUE //3
                }
            );


然后设置 .setTextColor(myColorStateList);就可以了


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

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

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

实现步骤

一、组合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.

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

好像效果不是很理想,有很多问题,比如滑动删除的时候可以上拉下拉,上拉时没有底部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,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,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,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,a);
  mHeaderLoadingView.setVisibility(View.GONE);
  frame.addView(mHeaderLoadingView,lp);
  mRefreshableView.addHeaderView(frame,a);
  mFooterLoadingView.setVisibility(View.GONE);
  mLvFooterLoadingFrame.addView(mFooterLoadingView,lp);
  // 添加底部加载view
  mRefreshableView.addFooterView(mLvFooterLoadingFrame,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,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,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,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,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下拉刷新上拉加载效果》,欢迎大家学习研究。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

Android ListView实现仿iPhone实现左滑删除按钮的简单实例

Android ListView实现仿iPhone实现左滑删除按钮的简单实例

需要自定义ListView。这里就交FloatDelListView吧。

复写onTouchEvent方法。如下:

@Override
  public boolean onTouchEvent(MotionEvent ev) { 
    switch (ev.getAction()) { 
      case MotionEvent.ACTION_DOWN:<BR>          // 获取按下的条目视图(child view) 
        int childCount = getChildCount(); 
        int[] listViewCoords = new int[2]; 
        getLocationOnScreen(listViewCoords); 
        int x = (int) ev.getRawX() - listViewCoords[0]; 
        int y = (int) ev.getRawY() - listViewCoords[1]; 
        for (int i = 0; i < childCount; i++) { 
          downChild = getChildAt(i); // 
          Rect rect = new Rect(); 
          assert downChild != null; 
          downChild.getHitRect(rect); 
 
          int childPosition = getPositionForView(downChild); 
 
          if (rect.contains(x,y)) { 
            downX = ev.getRawX(); 
            int downPosition = childPosition; 
 
            veLocityTracker = VeLocityTracker.obtain(); 
            assert veLocityTracker != null; 
            veLocityTracker.addMovement(ev); 
            break; 
          } 
        } 
        isSwipe = false; 
        break; 
      case MotionEvent.ACTION_MOVE: 
        veLocityTracker.addMovement(ev);<BR>          // 计算水平和垂直方向移动速度 
        veLocityTracker.computeCurrentVeLocity(1000); 
        float veLocityX = Math.abs(veLocityTracker.getXVeLocity()); 
        float veLocityY = Math.abs(veLocityTracker.getYVeLocity()); 
<BR>          // 水平移动距离 
        float deltaX = ev.getRawX() - downX; 
        float deltaMode = Math.abs(deltaX); 
        if (deltaX > 150) {// right swipe(右滑) 
          isSwipetoLeft = false; 
        } else if (deltaX < -150) {// left swipe(左滑) 
          isSwipetoLeft = true; 
        }<BR>          // 如果水平滑动距离大于零,并且水平滑动速率比垂直大,说明是水平滑动 
        if (deltaMode > 0 && veLocityY < veLocityX) {<BR>            // 这里的FloatDelButtonLayout是自定义的LinearLayout。 
          ((FloatDelButtonLayout) downChild).showDelButton(ev,isSwipetoLeft); 
          isSwipe = true; 
        } 
        break; 
      case MotionEvent.ACTION_CANCEL: 
      case MotionEvent.ACTION_UP: 
        downChild.setSelected(false); 
        if (isSwipe) { 
          isSwipe = false; 
          return true; 
        } 
        break; 
    } 
    return super.onTouchEvent(ev); 
  }

FloatDelButtonLayou.java :

public class FloatDelButtonLayout extends LinearLayout { 
<BR>   // 提供删除按钮的接口 
  private OnDelListener delListener; 
<BR>   // 当前视图在列表中的索引,在delListener中使用 
  private int index; 
<BR>   // 右滑 还是 左滑?<BR>  private boolean isSwipetoLeft;<BR> 
  public void setonDelListener(OnDelListener listener,int i) { 
    delListener = listener; 
    index = i; 
  } 
 
  public FloatDelButtonLayout(Context context) { 
    super(context,null); 
  } 
 
  public FloatDelButtonLayout(Context context,AttributeSet attrs) { 
    super(context,attrs,0); 
  } 
 
  public FloatDelButtonLayout(Context context,AttributeSet attrs,int defStyle) { 
    super(context,defStyle); 
  } 
<BR>   // 用来显示或者隐藏删除按钮。 
  public void showDelButton(MotionEvent ev,boolean isSwipetoLeft) { 
    this.isSwipetoLeft = isSwipetoLeft; 
    onTouchEvent(ev); 
  } 
 
  private OnClickListener clickDel = new OnClickListener() { 
    @Override
    public void onClick(View v) { 
      delListener.onDel(index); 
    } 
  }; 
<BR>   /**<BR>    * 这里的event是我们显示的从FloatDelListView的onTouchEvent里面传进来的,<BR>   */
  @Override
  public boolean onTouchEvent(MotionEvent event) { 
    switch (MotionEventCompat.getActionMasked(event)) { 
      case MotionEvent.ACTION_MOVE:<BR>          // 获取删除按钮对象,视图layout中必须要有id为del_button的Button标签 
        Button view = (Button) findViewById(R.id.del_button); 
        view.setText(R.string.del);<BR>          // 设置Button的MarginLayoutParams,当然可以做成各种动作,比如渐隐之类的显示出来。 
        MarginLayoutParams layoutParams = (MarginLayoutParams) view.getLayoutParams(); 
        assert layoutParams != null; 
        if (isSwipetoLeft) { 
          view.setVisibility(View.VISIBLE); 
          view.setonClickListener(clickDel); 
          layoutParams.leftMargin = -200; 
        } else { 
          view.setVisibility(View.GONE); 
          layoutParams.leftMargin = 0; 
        } 
        view.setLayoutParams(layoutParams); 
        invalidate(); 
        break; 
    } 
    return super.onTouchEvent(event); 
  } 
 
  public interface OnDelListener { 
    void onDel(int i); 
  } 
}

以上这篇Android ListView实现仿iPhone实现左滑删除按钮的简单实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持编程小技巧。

Android ListView滑动删除操作(SwipeListView)

Android ListView滑动删除操作(SwipeListView)

新版本的微信和QQ上引入的滑动删除功能是现在比较流行的一个功能。其实这个滑动删除的控件,github上已经有了,是一个热门的开源框架SwipeListView。不过,这个SwipeListView是一个framelayout,即是一个两层的布局,上面的布局front覆盖了下面的布局back,滑动的时候则会滑开front,这样下面的back就显示出来了。但是看了一下微信的滑动删除好像不是这样的,感觉更像是一个超出了屏幕的单层布局,滑动的时候是右边超出屏幕的button进入屏幕,猜测应该不是使用SwipeListView控件。QQ的滑动删除则是在ListView的item右边隐藏一个button,但检测到滑动事件的时候,给button一个出现的动画,使其可见,这个方案应该是最好实现的了。

本篇主要是学习SwipeListView这个开源框架。

使用这个框架有两种方式,一种是导入SwipeListViewLibrary这个工程,将其作为一个android工程的依赖库。由于SwipeListViewLibrary库工程自身也依赖另外一个热门的开源框架NineOldAndroids,这个也很容易就能网上或者github上搜到。

导入这两个库工程,对于NineOldAndroids,做如下设置,其实主要就是勾选Is Library这个选项,这样就能是NineOldAndroids工程作为别的工程的依赖库使用: 

对于SwipeListViewLibrary,除了要勾选Is Library选项,记得在旁边的Add里面,加上上面的NineOldAndroids作为本库的依赖库:

下面就是使用这个库了,先clean一下上面两个库工程,很多时候工程的错误,clean一下就好了。然后新建自己的工程,在Add选项里面添加SwipeListViewLibrary工程就行。这样就能直接使用SwipeListView这个控件了,很简单,代码如下: 

 <com.fortysevendeg.swipelistview.SwipeListView
  android:id="@+id/swipe_lv"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  app:swipeMode="left"
  app:swipeAnimationTime="300"
  app:swipeOffsetLeft="200dp"
  app:swipeFrontView="@+id/front"
  app:swipeBackView="@+id/back"
  app:swipeActionLeft="reveal"/>

其中app:swipeFrontView属性就是指定前面说的framelayout里面上面一层的view的id,app:swipeBackView则是指定下面一层的view的id,在下面自定义BaseAdatpter要使用的item的布局里面可以看到:

 <?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent" >
  <RelativeLayout
    android:id="@+id/back"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button
      android:id="@+id/close_btn"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerVertical="true"
      android:layout_toLeftOf="@+id/delete_btn"
      android:text="Close"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:focusable="false"
      android:focusableInTouchMode="false"/>
    <Button
      android:id="@+id/delete_btn"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerVertical="true"
      android:layout_alignParentRight="true"
      android:text="Delete"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:focusable="false"
      android:focusableInTouchMode="false"/>
  </RelativeLayout>
  <RelativeLayout
    android:id="@+id/front"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">
    <TextView
      android:id="@+id/content_tv"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:gravity="center"
      android:text="hello world"
      android:textAppearance="?android:attr/textAppearanceMedium"
      android:textColor="@android:color/black"/>
  </RelativeLayout>
</FrameLayout>

在Activity里面初始化的代码:

arrays = new ArrayList<String>(Arrays.asList(Util.arrays));

    mSwipeLv = (SwipeListView)findViewById(R.id.swipe_lv);
    mAdapter = new MyAdapter(this,arrays);
    mSwipeLv.setAdapter(mAdapter);
    mSwipeLv.setSwipeListViewListener(new BaseSwipeListViewListener() {

      @Override
      public void onClosed(int position,boolean fromright) {
      }
    });

以及自定义BaseAdapter中的getView(): 

    @Override
    public View getView(final int position,View convertView,final ViewGroup parent) {
      ViewHolder holder;

      if(convertView == null) {
        holder = new ViewHolder();
        convertView = LayoutInflater.from(mContext).inflate(
            R.layout.layout_swipe_list_item,null);
        holder.mContentTv = (TextView)convertView.findViewById(R.id.content_tv);
        holder.mCloseBtn = (Button)convertView.findViewById(R.id.close_btn);
        holder.mDeleteBtn = (Button)convertView.findViewById(R.id.delete_btn);

        convertView.setTag(holder);
      } else {
        holder = (ViewHolder)convertView.getTag();
      }

      holder.mContentTv.setText(arrays.get(position));
      holder.mCloseBtn.setonClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
          ((SwipeListView)parent).closeAnimate(position);
        }
      });
      holder.mDeleteBtn.setonClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
          ((SwipeListView)parent).cloSEOpenedItems();
          mHandler.postDelayed(new Runnable() {

            @Override
            public void run() {
              mArrays.remove(position);
              mAdapter.notifyDataSetChanged();
            }
          },350);
        }
      });

      return convertView;
    }

然后就ok了,运行工程的效果如下图: 

另外一种是用SwipeListView控件的方法就是直接导入官方给出的两个jar包,上面开篇的地址里可以看到,但是直接导入这两个jar包,不代表可以立即使用了!首先先把这个包添加到新建工程的build path里面,如果你的工程没有添加android的支持包android-support-v4.jar记得也添加以下,然后记得从前面已经导入过的SwipeListViewLibrary库工程中的res\values\swipelistview__attrs.xml文件复制到新建工程的res/values/目录下,这个文件主要是申明SwipeListView控件里面的各项属性的,直接导入的jar包是没有包含申明这些属性的文件的。然后就是向上面一样在代码里面引用了,不过需要注意两点:一,jar包里面SwipeListView的包名和库工程里面的包名是不一样的,引用的时候需要注意以下;二,准备妥当,确认前面步骤无误后,有时在编译工程时回报错,说没有申明swipeFrontView和swipeBackView两个属性,这个问题好像是SwipeListView框架的一个bug,stackoverflow上有人指出过,,大意就是在布局文件里面申明swipeFrontView和swipeBackView这两个属性的值得时候,最好不要自定义id的名称,而是使用swipelistview_backview和swipelistview_frontview。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程小技巧。

关于Android使用Item Swipemenulistview实现仿QQ侧滑删除功能的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于android listview item点击时更改textview的颜色 代码中实现、Android ListView实现上拉加载下拉刷新和滑动删除功能、Android ListView实现仿iPhone实现左滑删除按钮的简单实例、Android ListView滑动删除操作(SwipeListView)等相关知识的信息别忘了在本站进行查找喔。

本文标签: