版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Daxue_haha/article/details/48052575
前段时间用到了侧滑删除效果,在网上找了一些资料,结合一些代码做了个小测试,先看效果图
效果图
思路:ListView里的每个item做成一个可以滑动的自定义控件SlideView,然后时间均又外层的ListView拦截同时把事件传递给SlideView做滑动。
下面我画的一个布局分布图,更方便直观的看代码
下面开始写代码:
SlideView.java 继承LinearLayout的一个可以滑动的自定义控件
package widget.silddelete;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import com.example.android.activity.R;
public class SlideView extends LinearLayout {
private static final String TAG = "SlideView";
private Context mContext;
private LinearLayout mViewContent;
private RelativeLayout mHolder;
// Android里Scroller类是为了实现View平滑滚动的一个Helper类。
// 通常在自定义的View时使用,在View中定义一个私有成员mScroller = new Scroller(context)。
// 设置mScroller滚动的位置时,并不会导致View的滚动,
// 通常是用mScroller记录/计算View滚动的位置,再重写View的computeScroll(),完成实际的滚动。
private Scroller mScroller;
private OnSlideListener mOnSlideListener;
private int mHolderWidth = 120;
private int mLastX = 0;
private int mLastY = 0;
private static final int TAN = 2;
public interface OnSlideListener {
public static final int SLIDE_STATUS_OFF = 0;
public static final int SLIDE_STATUS_START_SCROLL = 1;
public static final int SLIDE_STATUS_ON = 2;
/**
* @param view current SlideView
* @param status SLIDE_STATUS_ON or SLIDE_STATUS_OFF
*/
public void onSlide(View view, int status);
}
public SlideView(Context context) {
super(context);
initView();
}
//自定义控件attrs.xml的文件,并在此文件中增加对控件的属性的定义
public SlideView(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
private void initView() {
mContext = getContext();
mScroller = new Scroller(mContext);
//设置为横向滑动
setOrientation(LinearLayout.HORIZONTAL);
View.inflate(mContext, R.layout.item_listview_delete, this);
mViewContent = (LinearLayout) findViewById(R.id.view_content);
mHolderWidth = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, mHolderWidth, getResources()
.getDisplayMetrics()));
}
//将view加到ViewContent中去
public void setContentView(View view) {
mViewContent.addView(view);
}
//设置滑动回调
public void setOnSlideListener(OnSlideListener onSlideListener) {
mOnSlideListener = onSlideListener;
}
public void shrink() {
if (getScrollX() != 0) {
this.smoothScrollTo(0, 0);
}
}
// 根据MotionEvent来进行滑动,这个方法的作用相当于onTouchEvent
// 如果你不需要处理滑动冲突,可以直接重命名,照样能正常工作
public void onRequireTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
int scrollX = getScrollX();
Log.d(TAG, "x=" + x + " y=" + y);
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;
}
private void smoothScrollTo(int destX, int destY) {
// 缓慢滚动到指定位置
int scrollX = getScrollX();
int delta = destX - scrollX;
mScroller.startScroll(scrollX, 0, delta, 0, Math.abs(delta) * 3);
invalidate();
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
}
}
}
ListViewCompat继承Listview
package widget.silddelete;
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 com.explms.deletelistview.CarListItemModel;
public class ListViewCompat extends ListView {
private static final String TAG = "ListViewCompat";
private SlideView mFocusedItemView;
public ListViewCompat(Context context) {
super(context);
}
public ListViewCompat(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListViewCompat(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@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);
Log.e(TAG, "postion=" + position);
if (position != INVALID_POSITION) {
CarListItemModel data = (CarListItemModel) getItemAtPosition(position);
mFocusedItemView = data.slideView;
Log.e(TAG, "FocusedItemView=" + mFocusedItemView);
}
}
default:
break;
}
if (mFocusedItemView != null) {
mFocusedItemView.onRequireTouchEvent(event);
}
return super.onTouchEvent(event);
}
}
MainActivity.java
package com.explms.deletelistview;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import com.example.android.activity.R;
import widget.silddelete.ListViewCompat;
import widget.silddelete.SlideView;
import java.util.ArrayList;
public class MainActivity extends Activity implements SlideView.OnSlideListener {
/**
* Called when the activity is first created.
*/
ListViewCompat popCarListview;
ArrayList<CarListItemModel> poplist;
private SlideView mLastSlideViewWithStatusOn;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
initview();
}
public void initview() {
popCarListview= (ListViewCompat)findViewById(R.id.car_pop_list);
popCarListview.setAdapter(new PopCarListAdapter(this,getlist()));
}
//<span style="color: rgb(0, 130, 0); font-family: Consolas, 'Courier New', Courier, mono, serif; line-height: 18px;">向当前点击的view发送滑动事件请求,其实就是向SlideView发请求</span>
@Override
public void onSlide(View view, int status) {
if (mLastSlideViewWithStatusOn != null && mLastSlideViewWithStatusOn != view) {
mLastSlideViewWithStatusOn.shrink();
}
if (status == SLIDE_STATUS_ON) {
mLastSlideViewWithStatusOn = (SlideView) view;
}
}
public ArrayList<CarListItemModel> getlist(){
poplist=new ArrayList<CarListItemModel>();
for (int i = 0; i < 10; i++) {
CarListItemModel item = new CarListItemModel();
if (i % 2 == 0) {
item.circleImage = R.drawable.img2;
item.productName = "粉红衬衫";
item.productSize= "S";
item.producrPrice= "25.00";
item.productNumber=""+i;
} else {
item.circleImage = R.drawable.img3;
item.productName = "格子衫";
item.productSize= "M";
item.producrPrice= "65.00";
item.productNumber=""+i;
}
poplist.add(item);
}
return poplist;
}
}
PopCarListAdapter.java listview适配器
package com.explms.deletelistview;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import com.example.android.activity.R;
import widget.silddelete.SlideView;
import java.util.ArrayList;
/**
* Created by Administrator on 7/30/15.
*/
public class PopCarListAdapter extends BaseAdapter{
LayoutInflater inflater;
ArrayList<CarListItemModel> list;
Context context;
public PopCarListAdapter(Context context,ArrayList<CarListItemModel> list){
this.context=context;
this.list=list;
inflater=LayoutInflater.from(context);
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return list.get(i);
}
@Override
public long getItemId(int i) {
return i;
}
@Override
public View getView(final int i, View view, ViewGroup viewGroup) {
ViewHolder holder;
SlideView slideView = (SlideView) view;
if (slideView == null) {
View itemView = inflater.inflate(R.layout.item_listview_silde, null);
slideView = new SlideView(context);
slideView.setContentView(itemView);
holder = new ViewHolder(slideView);
slideView.setOnSlideListener((SlideView.OnSlideListener) context);
slideView.setTag(holder);
} else {
holder = (ViewHolder) slideView.getTag();
}
CarListItemModel item = list.get(i);
item.slideView = slideView;
item.slideView.shrink();
holder.circleImage.setImageResource(item.circleImage);
holder.productName.setText(item.productName);
holder.productSize.setText(item.productSize);
holder.producrPrice.setText(item.producrPrice);
holder.productNumber.setText(item.productNumber);
holder.deleteHolder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
list.remove(i);
PopCarListAdapter.this.notifyDataSetChanged();
}
});
return slideView;
}
}
class ViewHolder {
public ImageView circleImage;
public TextView productName;
public TextView productSize;
public TextView producrPrice;
public TextView productNumber;
public ViewGroup deleteHolder;
ViewHolder(View view) {
circleImage = (ImageView) view.findViewById(R.id.product_image_circle);
productName= (TextView) view.findViewById(R.id.productname);
productSize = (TextView) view.findViewById(R.id.productsize);
productNumber = (TextView) view.findViewById(R.id.productnumber);
producrPrice= (TextView) view.findViewById(R.id.productprice);
deleteHolder = (ViewGroup)view.findViewById(R.id.holder);
}
}
数据模型CarListItemModel.java
package com.explms.deletelistview;
import widget.silddelete.SlideView;
public class CarListItemModel {
public int circleImage;
public String productName;
public String productSize;
public String producrPrice;
public String productNumber;
public SlideView slideView;
}
另外此博文部分代码借鉴http://blog.csdn.net/singwhatiwanna/article/details/17515543,写的比较清楚,大家可以去看看