转载请注明出处: http://blog.csdn.net/forwardyzk/article/details/42643865
在玩QQ的时候,我们会看到这样的效果,可以滑动删除消息,下面就模拟一下这样的效果。
1.创建一个类ListViewCompat,继承ListView。
重写其OnTouchEvent事件。
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
int x = (int) event.getX();
int y = (int) event.getY();
int position = pointToPosition(x, y);
if (position != INVALID_POSITION) {
// 获取Item内容,获取Item显示的View对象,就是SlideView
MessageItem data = (MessageItem) getItemAtPosition(position);
mFocusedItemView = data.getSlideView();
}
}
default:
break;
}
if (mFocusedItemView != null) {
mFocusedItemView.onRequireTouchEvent(event);
}
return super.onTouchEvent(event);
}
pointToPosition获取点击的item的位置position,然后通过getItemAtPosition(position)获取适配器的中制定item的信息.查看getItemAtPosition的源码
/**
* Gets the data associated with the specified position in the list.
*
* @param position Which data to get
* @return The data associated with the specified position in the list
*/
public Object getItemAtPosition(int position) {
T adapter = getAdapter();
return (adapter == null || position < 0) ? null : adapter.getItem(position);
}
调用的是getItem().所以在定义适配器的时候,要记得重写getItem(int position)方法
mFocusedItemView.onRequireTouchEvent(event)操作Item的OnTouchEvent()事件
2.MessageItem是要展示Item的信息对象。
/**
*
* item显示信息的类,包含删除按钮,要显示的信息
*
*/
public class MessageItem {
private String tv_content;
private SlideView slideView;
public String getTv_content() {
return tv_content;
}
public void setTv_content(String tv_content) {
this.tv_content = tv_content;
}
public SlideView getSlideView() {
return slideView;
}
public void setSlideView(SlideView slideView) {
this.slideView = slideView;
}
}
tv_content:是item显示信息的内容
SlideView slideView:是适配器中Item的View,getView()的返回值,ListView的Item显示的是slideView。
3.我们看一下定义的适配器
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
SlideView slideView = (SlideView) convertView;
if (slideView == null) {
View itemView = View.inflate(mContext,
R.layout.item_listview_delete, null);
// 将item显示的内容设置到Item对象中
slideView = new SlideView(mContext);
slideView.setContentView(itemView);
holder = new ViewHolder(slideView);
slideView.setOnSlideListener(SlideAdapter.this);
slideView.setTag(holder);
} else {
holder = (ViewHolder) slideView.getTag();
}
MessageItem item = mMessageItems.get(position);
item.setSlideView(slideView);
item.getSlideView().shrink();
holder.tv_content.setText(item.getTv_content());
holder.deleteHolder.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (deleteItemListener != null) {
deleteItemListener.deleteItem(v, position);
}
}
});
return slideView;
}
item.setSlideView(slideView);会把当前的item对象,设置给item信息对象的属性,为了在ListView的OnTouchEvent方便的调用其Item的onTouchEvent()事件。
设置滑动监听:slideView.setOnSlideListener(SlideAdapter.this);
会把convertView转换为SlideView。会把直接展示的Item的内容,添加到SlideView对象的内容View中
View itemView = View.inflate(mContext,R.layout.item_listview_delete, null);
slideView.setContentView(itemView);
item_listview_delete.xml
<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="58dp"
android:background="@drawable/delete_list_item_bg"
android:descendantFocusability="blocksDescendants"
android:gravity="center_vertical"
android:paddingBottom="5dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:paddingTop="5dp" >
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:textColor="@android:color/black"
android:textSize="25sp" />
</RelativeLayout>
SlideView加载的布局文件
activity_listview_delete_slide_view_merge.xml
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="@+id/view_content"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
</LinearLayout>
<RelativeLayout
android:id="@+id/holder"
android:layout_width="120dp"
android:layout_height="match_parent"
android:clickable="true"
android:background="@drawable/delete_holder_bg">
<TextView
android:id="@+id/delete"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="@drawable/delete_icon_normal"
android:layout_centerInParent="true"
android:gravity="center"
android:textColor="@android:color/white"
android:text="删除" />
</RelativeLayout>
</merge>
其实就是把展示Item的内容添加到了SlideView中加载的布局中,id为view_content先行布局中。
View.inflate(mContext,
R.layout.activity_listview_delete_slide_view_merge, this);
mViewContent = (LinearLayout) findViewById(R.id.view_content);
public void setContentView(View view) {
mViewContent.addView(view);
}
这样就把整个item需要的内容(包含删除按钮)完全的显示到了item中。
4.我们要监听Item的滑动事件
public void onRequireTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int scrollX = getScrollX();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
if (mOnSlideListener != null) {
mOnSlideListener.onSlide(this,
OnSlideListener.SLIDE_STATUS_START_SCROLL);
}
break;
}
case MotionEvent.ACTION_MOVE: {
int deltaX = x - mLastX;
int deltaY = y - mLastY;
if (Math.abs(deltaX) < Math.abs(deltaY) * TAN) {
break;
}
int newScrollX = scrollX - deltaX;
if (deltaX != 0) {
if (newScrollX < 0) {
newScrollX = 0;
} else if (newScrollX > mHolderWidth) {
newScrollX = mHolderWidth;
}
this.scrollTo(newScrollX, 0);
}
break;
}
case MotionEvent.ACTION_UP: {
int newScrollX = 0;
if (scrollX - mHolderWidth * 0.75 > 0) {
newScrollX = mHolderWidth;
}
this.smoothScrollTo(newScrollX, 0);
if (mOnSlideListener != null) {
mOnSlideListener.onSlide(this,
newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF
: OnSlideListener.SLIDE_STATUS_ON);
}
break;
}
default:
break;
}
mLastX = x;
mLastY = y;
}
在MotionEvent.ACTION_DOWN中处理,此时点击下去后,会调用滑动监听事件OnSlideListener,执行onSlide,
mOnSlideListener.onSlide(this,OnSlideListener.SLIDE_STATUS_START_SCROLL)
然而是适配器中会处理此监听
public void onSlide(View view, int status) {
if (mLastSlideViewWithStatusOn != null
&& mLastSlideViewWithStatusOn != view) {
mLastSlideViewWithStatusOn.shrink();
}
if (status == SLIDE_STATUS_ON) {
mLastSlideViewWithStatusOn = (SlideView) view;
}
}
是把前一个没有回到原点的,使其滑动到原点,保持点击ListView时,其Item全部回到原点.
MotionEvent.ACTION_MOVE时:滑动的距离来移动item,this.scrollTo(newScrollX, 0);只是水平方向移动,
if (newScrollX < 0) {
newScrollX = 0;
} else if (newScrollX > mHolderWidth) {
newScrollX = mHolderWidth;
}
限制了滑动的范围。
MotionEvent.ACTION_UP:当收值离开的时候,会把根据滑动的位置,来调节是否要显示出删除按钮。当滑动的距离大于删除按钮宽度的3/4,那么就显示出删除按钮,否则item就回到原点。this.smoothScrollTo(newScrollX, 0);
同时要把mOnSlideListener.onSlide(this,newScrollX == 0 ? OnSlideListener.SLIDE_STATUS_OFF
: OnSlideListener.SLIDE_STATUS_ON)
当前的Item对象,在适配器中记录下来,这样当点击下一个Item的时候,把当前的Item移动到原点。
/**
* 使Item回到圆点位置
*/
public void shrink() {
if (getScrollX() != 0) {
this.smoothScrollTo(0, 0);
}
}
5.在适配器中设置了删除的监听事件
private DeleteItemListener deleteItemListener;
/**
* @param deleteItemListener
* 设置删除Item监听事件
*/
public void setDeleteItemListener(DeleteItemListener deleteItemListener) {
this.deleteItemListener = deleteItemListener;
}
holder.deleteHolder.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (deleteItemListener != null) {
deleteItemListener.deleteItem(v, position);
}
}
});
6.使用步骤
布局文件
<com.example.view.ListViewCompat
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#fff4f7f9"
android:cacheColorHint="#00000000"
android:divider="#dddbdb"
android:dividerHeight="1.0px"
android:drawSelectorOnTop="false"
android:listSelector="@android:color/transparent"
android:scrollbars="none" />
public void initView() {
mListView = (ListViewCompat) findViewById(R.id.list);
for (int i = 0; i < 20; i++) {
MessageItem item = new MessageItem();
item.setTv_content("我是第 " + i + " 个Item");
mMessageItems.add(item);
}
// 创建适配器对象
adapter = new SlideAdapter(DeleteListViewMainActivity.this,
mMessageItems);
// 删除监听
adapter.setDeleteItemListener(new DeleteItemListener() {
@Override
public void deleteItem(View view, int position) {
mMessageItems.remove(position);
adapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(),
"删除了第 " + position + " item", 0).show();
}
});
// 设置适配器
mListView.setAdapter(adapter);
// 点击item事件
mListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
Toast.makeText(getApplicationContext(), "点击了=" + position, 0)
.show();
}
});
}
源码下载: http://download.csdn.net/detail/forwardyzk/8353961
效果图: