这篇文章主要围绕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 listview item点击时更改textview的颜色 代码中实现
- Android ListView实现上拉加载下拉刷新和滑动删除功能
- Android ListView实现仿iPhone实现左滑删除按钮的简单实例
- Android ListView滑动删除操作(SwipeListView)
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的颜色 代码中实现
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实现上拉加载下拉刷新和滑动删除功能
最近项目需要用到可以滑动删除并且带有上拉加载下拉刷新的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实现左滑删除按钮的简单实例
需要自定义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)
新版本的微信和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)等相关知识的信息别忘了在本站进行查找喔。
本文标签: