10.侧拉删除
* 应用场景: 聊天列表界面,邮件管理界面等条目管理(设为已读, 删除等)
* 功能实现: 参考 侧滑面板 offsetLeftAndRight , offsetTopAndBottom
activity_main
-
<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=".MainActivity" > <ListView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/lv" ></ListView> </RelativeLayout>
item_list:设置文本区域最小高度,如果不设置和设置分别是这样的
这个其实就是adapter条目
-
<com.itheima.swipelayout.ui.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/sl" android:layout_width="match_parent" android:layout_height="60dp" android:minHeight="60dp" android:background="#44000000" > <LinearLayout android:layout_width="wrap_content" android:layout_height="match_parent" android:orientation="horizontal" > <TextView android:id="@+id/tv_call" android:layout_width="60dp" android:layout_height="match_parent" android:background="#666666" android:gravity="center" android:text="Call" android:textColor="#ffffff" /> <TextView android:id="@+id/tv_del" android:layout_width="60dp" android:layout_height="match_parent" android:background="#ff0000" android:gravity="center" android:text="Delete" android:textColor="#ffffff" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:background="#44ffffff" android:gravity="center_vertical" android:orientation="horizontal" > <ImageView android:id="@+id/iv_image" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginLeft="15dp" android:src="@drawable/head_1" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:text="Name" /> </LinearLayout> </com.itheima.swipelayout.ui.SwipeLayout>
SwipeLayout
-
/** * 侧拉删除控件 * @author poplar * */ public class SwipeLayout extends FrameLayout { private Status status = Status.Close; private OnSwipeLayoutListener swipeLayoutListener; public Status getStatus() { return status; } public void setStatus(Status status) { this.status = status; } public OnSwipeLayoutListener getSwipeLayoutListener() { return swipeLayoutListener; } public void setSwipeLayoutListener(OnSwipeLayoutListener swipeLayoutListener) { this.swipeLayoutListener = swipeLayoutListener; } public static enum Status{ Close, Open, Draging } public static interface OnSwipeLayoutListener { void onClose(SwipeLayout mSwipeLayout); void onOpen(SwipeLayout mSwipeLayout); void onDraging(SwipeLayout mSwipeLayout); // 要去关闭 void onStartClose(SwipeLayout mSwipeLayout); // 要去开启,这时候需要其他开启的关闭 void onStartOpen(SwipeLayout mSwipeLayout); } public SwipeLayout(Context context) { this(context, null); } public SwipeLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SwipeLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); mDragHelper = ViewDragHelper.create(this, 1.0f, mCallback); } ViewDragHelper.Callback mCallback = new ViewDragHelper.Callback() { // c. 重写监听 @Override public boolean tryCaptureView(View view, int id) { return true; } // 限定移动范围 public int clampViewPositionHorizontal(View child, int left, int dx) { // left if(child == mFrontView){ if(left > 0){ return 0; }else if(left < -mRange){ return -mRange; } }else if (child == mBackView) { if(left > mWidth){ return mWidth; }else if (left < mWidth - mRange) { return mWidth - mRange; } } return left; }; public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { // 传递事件 if(changedView == mFrontView){ mBackView.offsetLeftAndRight(dx); }else if (changedView == mBackView) { mFrontView.offsetLeftAndRight(dx); } dispatchSwipeEvent(); // 兼容老版本 invalidate(); }; public void onViewReleased(View releasedChild, float xvel, float yvel) { if (xvel == 0 && mFrontView.getLeft() < -mRange / 2.0f) { open(); }else if (xvel < 0) { open(); }else { close(); } }; }; private ViewDragHelper mDragHelper; private View mBackView; private View mFrontView; private int mHeight; private int mWidth; private int mRange; // b. 传递触摸事件 @Override public boolean onInterceptTouchEvent(android.view.MotionEvent ev) { return mDragHelper.shouldInterceptTouchEvent(ev); }; protected void dispatchSwipeEvent() { if(swipeLayoutListener != null){ swipeLayoutListener.onDraging(this); } // 记录上一次的状态 Status preStatus = status; // 更新当前状态 status = updateStatus(); if (preStatus != status && swipeLayoutListener != null) { if (status == Status.Close) { swipeLayoutListener.onClose(this); } else if (status == Status.Open) { swipeLayoutListener.onOpen(this); } else if (status == Status.Draging) { if(preStatus == Status.Close){ swipeLayoutListener.onStartOpen(this); }else if (preStatus == Status.Open) { swipeLayoutListener.onStartClose(this); } } } } private Status updateStatus() { int left = mFrontView.getLeft(); if(left == 0){ return Status.Close; }else if (left == -mRange) { return Status.Open; } return Status.Draging; } public void close() { Utils.showToast(getContext(), "Close"); close(true); } public void close(boolean isSmooth){ int finalLeft = 0; if(isSmooth){ //开始动画 if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){ ViewCompat.postInvalidateOnAnimation(this); } }else { layoutContent(false); } } public void open() { Utils.showToast(getContext(), "Open"); open(true); } public void open(boolean isSmooth){ int finalLeft = -mRange; if(isSmooth){ //开始动画 if(mDragHelper.smoothSlideViewTo(mFrontView, finalLeft, 0)){ ViewCompat.postInvalidateOnAnimation(this); } }else { layoutContent(true); } } @Override public void computeScroll() { super.computeScroll(); if(mDragHelper.continueSettling(true)){ ViewCompat.postInvalidateOnAnimation(this); } } @Override public boolean onTouchEvent(MotionEvent event) { try { mDragHelper.processTouchEvent(event); } catch (Exception e) { e.printStackTrace(); } return true; } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); // 摆放位置 layoutContent(false); } private void layoutContent(boolean isOpen) { // 摆放前View Rect frontRect = computeFrontViewRect(isOpen); mFrontView.layout(frontRect.left, frontRect.top, frontRect.right, frontRect.bottom); // 摆放后View Rect backRect = computeBackViewViaFront(frontRect); mBackView.layout(backRect.left, backRect.top, backRect.right, backRect.bottom); // 调整顺序, 把mFrontView前置 bringChildToFront(mFrontView); } private Rect computeBackViewViaFront(Rect frontRect) { int left = frontRect.right; return new Rect(left, 0, left + mRange, 0 + mHeight); } private Rect computeFrontViewRect(boolean isOpen) { int left = 0; if(isOpen){ left = -mRange; } return new Rect(left, 0, left + mWidth, 0 + mHeight); } @Override protected void onFinishInflate() { super.onFinishInflate(); // 当xml被填充完毕时调用 mBackView = getChildAt(0); mFrontView = getChildAt(1); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mHeight = mFrontView.getMeasuredHeight(); mWidth = mFrontView.getMeasuredWidth(); mRange = mBackView.getMeasuredWidth(); } }
MyAdapter:静态导入
-
import static com.itheima.swipelayout.bean.Cheeses.NAMES; public class MyAdapter extends BaseAdapter { protected static final String TAG = "TAG"; public MyAdapter(Context context) { super(); this.context = context; opendItems = new ArrayList<SwipeLayout>(); } private Context context; private ArrayList<SwipeLayout> opendItems; @Override public int getCount() { return NAMES.length; } @Override public Object getItem(int position) { return NAMES[position]; } @Override public long getItemId(int position) { // TODO Auto-generated method stub return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { View view = convertView; if(convertView == null){ view = View.inflate(context, R.layout.item_list, null); } ViewHolder mHolder = ViewHolder.getHolder(view); SwipeLayout sl = (SwipeLayout)view; sl.setSwipeLayoutListener(new OnSwipeLayoutListener() { @Override public void onStartOpen(SwipeLayout mSwipeLayout) { Log.d(TAG, "onStartOpen"); // 要去开启时,先遍历所有已打开条目, 逐个关闭 for (SwipeLayout layout : opendItems) { layout.close(); } opendItems.clear(); } @Override public void onStartClose(SwipeLayout mSwipeLayout) { Log.d(TAG, "onStartClose"); } @Override public void onOpen(SwipeLayout mSwipeLayout) { Log.d(TAG, "onOpen"); // 添加进集合 opendItems.add(mSwipeLayout); } @Override public void onDraging(SwipeLayout mSwipeLayout) { } @Override public void onClose(SwipeLayout mSwipeLayout) { Log.d(TAG, "onClose"); // 移除集合 opendItems.remove(mSwipeLayout); } }); return view; } static class ViewHolder { TextView tv_call; TextView tv_del; public static ViewHolder getHolder(View view) { Object tag = view.getTag(); if(tag == null){ ViewHolder viewHolder = new ViewHolder(); viewHolder.tv_call = (TextView)view.findViewById(R.id.tv_call); viewHolder.tv_del = (TextView)view.findViewById(R.id.tv_del); tag = viewHolder; view.setTag(tag); } return (ViewHolder)tag; } } }
MainActivity
-
public class MainActivity extends Activity { private static final String TAG = "TAG"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); ListView mList = (ListView) findViewById(R.id.lv); mList.setAdapter(new MyAdapter(MainActivity.this)); } }