之前一篇文章中介绍了微信滑动删除效果(Android 仿微信对话列表滑动删除效果),这一篇在其基础上实现QQ消息列表ListView滑动删除效果,大致原理差不多,这里就不细说了。
运行效果如下:
SwipeListView.java
package com.example.swipelistview.widget;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
import android.widget.RelativeLayout;
import com.example.swipelistview.R;
public class SwipeListView extends ListView {
private static final String TAG = SwipeListView.class.getSimpleName();
private boolean isShown;
private View mPreItemView;
private View mCurrentItemView;
private float mFirstX;
private float mFirstY;
private boolean mIsHorizontal;
public SwipeListView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public SwipeListView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public SwipeListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
float lastX = ev.getX();
float lastY = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mIsHorizontal = false;
mFirstX = lastX;
mFirstY = lastY;
int motionPosition = pointToPosition((int) mFirstX, (int) mFirstY);
Log.e(TAG, "onInterceptTouchEvent----->ACTION_DOWN position=" + motionPosition);
if (motionPosition >= 0) {
View currentItemView = getChildAt(motionPosition - getFirstVisiblePosition());
mPreItemView = mCurrentItemView;
mCurrentItemView = currentItemView;
}
break;
case MotionEvent.ACTION_MOVE:
float dx = lastX - mFirstX;
float dy = lastY - mFirstY;
if (Math.abs(dx) >= 5 && Math.abs(dy) >= 5) {
return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
Log.i(TAG, "onInterceptTouchEvent----->ACTION_UP");
if (isShown && mPreItemView != mCurrentItemView) {
Log.i(TAG, "1---> hiddenRight");
/**
* 情况一:
* <p>
* 一个Item的右边布局已经显示,
* <p>
* 这时候点击任意一个item, 那么那个右边布局显示的item隐藏其右边布局
*/
hiddenRight(mPreItemView);
}
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
float lastX = ev.getX();
float lastY = ev.getY();
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
Log.i(TAG, "---->ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
float dx = lastX - mFirstX;
float dy = lastY - mFirstY;
mIsHorizontal = isHorizontalDirectionScroll(dx, dy);
if (!mIsHorizontal) {
break;
}
Log.i(TAG, "onTouchEvent ACTION_MOVE");
if (mIsHorizontal) {
if (isShown && mPreItemView != mCurrentItemView) {
Log.i(TAG, "2---> hiddenRight");
/**
* 情况二:
* <p>
* 一个Item的右边布局已经显示,
* <p>
* 这时候左右滑动另外一个item,那个右边布局显示的item隐藏其右边布局
* <p>
* 向左滑动只触发该情况,向右滑动还会触发情况五
*/
hiddenRight(mPreItemView);
}
}else {
if (isShown) {
Log.i(TAG, "3---> hiddenRight");
/**
* 情况三:
* <p>
* 一个Item的右边布局已经显示,
* <p>
* 这时候上下滚动ListView,那么那个右边布局显示的item隐藏其右边布局
*/
hiddenRight(mPreItemView);
}
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
Log.i(TAG, "============ACTION_UP");
if (isShown) {
Log.i(TAG, "4---> hiddenRight");
/**
* 情况四:
* <p>
* 一个Item的右边布局已经显示,
* <p>
* 这时候左右滑动当前一个item,那个右边布局显示的item隐藏其右边布局
*/
hiddenRight(mPreItemView);
}
if (mIsHorizontal) {
if (mFirstX - lastX > 30) {
showRight(mCurrentItemView);
} else {
Log.i(TAG, "5---> hiddenRight");
/**
* 情况五:
* <p>
* 向右滑动一个item,且滑动的距离超过了右边View的宽度的一半,隐藏之。
*/
hiddenRight(mCurrentItemView);
}
return true;
}
break;
}
return super.onTouchEvent(ev);
}
private void showRight(View rightView) {
RelativeLayout rl_right=(RelativeLayout)rightView.findViewById(R.id.item_right);
rl_right.setVisibility(View.VISIBLE);
isShown = true;
}
private void hiddenRight(View rightView) {
RelativeLayout rl_right=(RelativeLayout)rightView.findViewById(R.id.item_right);
rl_right.setVisibility(View.GONE);
isShown = false;
}
/**
* @param dx
* @param dy
* @return judge if can judge scroll direction
*/
private boolean isHorizontalDirectionScroll(float dx, float dy) {
boolean mIsHorizontal = true;
if (Math.abs(dx) > 30 && Math.abs(dx) > 2 * Math.abs(dy)) {
mIsHorizontal = true;
System.out.println("mIsHorizontal---->" + mIsHorizontal);
} else if (Math.abs(dy) > 30 && Math.abs(dy) > 2 * Math.abs(dx)) {
mIsHorizontal = false;
System.out.println("mIsHorizontal---->" + mIsHorizontal);
}
return mIsHorizontal;
}
}
SwipeAdapter.java
package com.example.swipelistview.adapter;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import com.example.swipelistview.R;
import com.example.swipelistview.entity.WXMessage;
public class SwipeAdapter extends BaseAdapter {
/**
* 上下文对象
*/
private Context mContext = null;
private List<WXMessage> data;
/**
* @param mainActivity
*/
public SwipeAdapter(Context ctx,List<WXMessage> data) {
mContext = ctx;
this.data = data;
}
@Override
public int getCount() {
// return 100;
return data.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if (convertView == null) {
convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
holder = new ViewHolder();
holder.item_left = (RelativeLayout)convertView.findViewById(R.id.item_left);
holder.item_right = (RelativeLayout)convertView.findViewById(R.id.item_right);
holder.iv_icon = (ImageView) convertView.findViewById(R.id.iv_icon);
holder.tv_title = (TextView)convertView.findViewById(R.id.tv_title);
holder.tv_msg = (TextView)convertView.findViewById(R.id.tv_msg);
holder.tv_time = (TextView)convertView.findViewById(R.id.tv_time);
holder.item_right_txt = (TextView)convertView.findViewById(R.id.item_right_txt);
convertView.setTag(holder);
} else {// 有直接获得ViewHolder
holder = (ViewHolder)convertView.getTag();
}
Log.i("SwipeAdapter", "getView position="+position);
WXMessage msg = data.get(position);
holder.tv_title.setText(msg.getTitle());
holder.tv_msg.setText(msg.getMsg());
holder.tv_time.setText(msg.getTime());
holder.iv_icon.setImageResource(msg.getIcon_id());
holder.item_right.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (mListener != null) {
mListener.onRightItemClick(v, position);
}
}
});
return convertView;
}
static class ViewHolder {
RelativeLayout item_left;
RelativeLayout item_right;
TextView tv_title;
TextView tv_msg;
TextView tv_time;
ImageView iv_icon;
TextView item_right_txt;
}
/**
* 单击事件监听器
*/
private onRightItemClickListener mListener = null;
public void setOnRightItemClickListener(onRightItemClickListener listener){
mListener = listener;
}
public interface onRightItemClickListener {
void onRightItemClick(View v, int position);
}
}
Demo下载地址:http://download.csdn.net/detail/fx_sky/6913747