先看下效果
首先把这个自定义view放到项目下
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.Scroller;
/**
* Created by DU on 2018/11/20.
*/
public class SwipeView extends ViewGroup{
private int downX, moveX, moved;
private Scroller scroller = new Scroller(getContext());
private boolean haveShowRight = false;
public static SwipeView swipeMenu;
public SwipeView(Context context) {
super(context);
}
public SwipeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SwipeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
if (swipeMenu != null) {
swipeMenu.closeMenus();
swipeMenu = null;
}
}
//缓慢滚动到指定位置
private void smoothScrollTo(int destX, int destY) {
int scrollX = getScrollX();
int delta = destX - scrollX;
//1000ms内滑动destX,效果就是慢慢滑动
scroller.startScroll(scrollX, 0, delta, 0, 100);
invalidate();
}
public void closeMenus() {
smoothScrollTo(0, 0);
haveShowRight = false;
}
public static void closeMenu() {
swipeMenu.closeMenus();
}
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
postInvalidate();
}
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (!scroller.isFinished()) {
return false;
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) ev.getRawX();
break;
case MotionEvent.ACTION_MOVE:
if (swipeMenu != null && swipeMenu == this && haveShowRight) {
closeMenu();
return true;
}
moveX = (int) ev.getRawX();
moved = moveX - downX;
if (haveShowRight) {
moved -= getChildAt(1).getMeasuredWidth();
}
scrollTo(-moved, 0);
if (getScrollX() <= 0) {
scrollTo(0, 0);
} else if (getScrollX() >= getChildAt(1).getMeasuredWidth()) {
scrollTo(getChildAt(1).getMeasuredWidth(), 0);
}
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (swipeMenu != null) {
closeMenu();
}
if (getScrollX() >= getChildAt(1).getMeasuredWidth() / 2) {
haveShowRight = true;
swipeMenu = this;
smoothScrollTo(getChildAt(1).getMeasuredWidth(), 0);
} else {
haveShowRight = false;
smoothScrollTo(0, 0);
}
break;
}
return true;
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs) {
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
measureChildren(widthMeasureSpec, heightMeasureSpec);
int width = MeasureSpec.getSize(widthMeasureSpec);
View child = getChildAt(0);
int margin =
((MarginLayoutParams) child.getLayoutParams()).topMargin +
((MarginLayoutParams) child.getLayoutParams()).bottomMargin;
setMeasuredDimension(width, getChildAt(0).getMeasuredHeight() + margin);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int cCount = getChildCount();
for (int i = 0; i < cCount; i++) {
View child = getChildAt(i);
if (i == 0) {
child.layout(l, t, r, b);
} else if (i == 1) {
child.layout(r, t, r + child.getMeasuredWidth(), b);
}
}
}
}
然后再在xml里面定义 (listviewitem要用的xml里面)
最外层一定要用FrameLayout
SwipeView里面分为两部分一部分是列表item要用的布局,第二部分是要隐藏在屏幕外面的删除按钮,我这里用的就是一个按钮标识删除,当然大家也可以用Linearlayout或者Relativelayout来表示更多想侧拉出来的效果
<?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="wrap_content">
<com.example.administrator.standardOA.view.SwipeView
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/cOmmtv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="8"
android:padding="@dimen/dp_5"
android:textSize="@dimen/sp_20" />
<View
android:layout_width="match_parent"
android:layout_height="@dimen/dp_1"
android:layout_marginBottom="@dimen/dp_2"
android:layout_marginLeft="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_10"
android:layout_marginTop="@dimen/dp_1"
android:background="#EFEFEF" />
</LinearLayout>
//这里就是隐藏到屏幕外边的删除按钮
<Button
android:id="@+id/tv_usb_delete"
android:layout_width="@dimen/dp_50"
android:layout_height="wrap_content"
android:background="@drawable/bg_cancel"
android:gravity="center"
android:padding="@dimen/dp_5"
android:text="删除"
android:textColor="@color/white"
android:textSize="@dimen/sp_20" />
</com.example.administrator.standardOA.view.SwipeView>
</FrameLayout>
然后adapter里面正常使用
然后要在合适的地方上关闭已经打开的viewgroup
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = View.inflate(context, R.layout.celaitem, null);
viewHolder.cOmmontv = convertView.findViewById(R.id.cOmmtv);
viewHolder.tv_usb_delete = convertView.findViewById(R.id.tv_usb_delete);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.cOmmontv.setText(list.get(position).getCommonSentence());
viewHolder.tv_usb_delete.setGravity(Gravity.CENTER);
//删除按钮的点击事件
viewHolder.tv_usb_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(final View v) {
list.remove(position);
//关闭删除按钮
SwipeView.closeMenu();
notifyDataSetChanged();
}
});
return convertView;
}
ok到这里就可以去看效果啦,activity的xml还有listview设置数据的代码没有列出来,可以根据自己需求使用哦,recyclerview也可用哦