1.应用场景:替换item长按删除
2.实现逻辑:
a.自定义一个可以滑动的布局;
4.2 SwipeLayout.java
4.3 MainActivity.java
5. 布局文件
5.2 layout_content.xml
5.3 layout_delete.xml
5.4 list_item.xml
6.运行效果图:
2.实现逻辑:
a.自定义一个可以滑动的布局;
b.将该布局放入adapter的布局中,需要处理滑动冲突;
3.目录结构:
4.java代码:
4.1 SwipeLayoutManager.java
package com.weizh.swipedelete.manager;
import com.weizh.swipedelete.widget.SwipeLayout;
/**
* Created by weizh_000 on 2016/8/24.
*/
public class SwipeLayoutManager {
private static SwipeLayoutManager swipeLayoutManager = new SwipeLayoutManager();
private SwipeLayout currentLayout;
public static SwipeLayoutManager getInstance(){
return swipeLayoutManager;
}
//记录当前打开的是哪一个swipeLayout
public void setCurrentLayout(SwipeLayout swipeLayout){
this.currentLayout = swipeLayout;
}
//清除记录
public void clearCurrentLayout(){
currentLayout=null;
}
//关闭记录中的swipelayout
public void closeSwipeLayout(){
if (currentLayout!=null){
currentLayout.close();
}
}
//判断是否可以左右滑动swipelayout
public boolean isShouldOpen(SwipeLayout swipeLayout){
if (currentLayout==null){
//说明无记录,可以打开
return true;
}else {
//说明有记录,
//记录的是自己,可以左右滑动
//记录的是别的swipelayout,则不能滑动
return currentLayout==swipeLayout;
}
}
public void resumeSwipeLayout() {
if(currentLayout!=null){
currentLayout.resume();
}
}
}
4.2 SwipeLayout.java
package com.weizh.swipedelete.widget;
import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;
import com.weizh.swipedelete.manager.SwipeLayoutManager;
/**
* Created by weizh_000 on 2016/8/23.
*/
public class SwipeLayout extends FrameLayout {
private View contentView;//item内容区域的view
private View deleteView;//delete区域的view
private int contentWidth;//内容区域的宽度
private int deleteWidth;//delete区域的宽度
private int deleteHeight;//delete区域的高度
private ViewDragHelper dragHelper;
private float downX;
private float downY;
private SwipeState currentState;//当前状态是默认是关闭状态
public SwipeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
public SwipeLayout(Context context) {
super(context);
init();
}
public SwipeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
private void init() {
dragHelper = ViewDragHelper.create(this, callback);
currentState = SwipeState.Close;
}
enum SwipeState {
Open, Close;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
contentView = getChildAt(0);
deleteView = getChildAt(1);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
contentWidth = contentView.getMeasuredWidth();
deleteWidth = deleteView.getMeasuredWidth();
deleteHeight = deleteView.getMeasuredHeight();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
contentView.layout(0, 0, contentWidth, deleteHeight);
deleteView.layout(contentView.getRight(), 0, contentView.getRight() + deleteWidth, deleteHeight);
}
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == contentView || child == deleteView;
}
@Override
public int getViewHorizontalDragRange(View child) {
return deleteWidth;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (child == contentView) {
if (left < -deleteWidth) left = -deleteWidth;
if (left > 0) left = 0;
} else if (child == deleteView) {
if (left < contentWidth - deleteWidth) left = contentWidth - deleteWidth;
if (left > contentWidth) left = contentWidth;
}
return left;
}
@Override
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
// super.onViewPositionChanged(changedView, left, top, dx, dy);
//做伴随移动
if (changedView == contentView) {
deleteView.layout(deleteView.getLeft() + dx, 0, deleteView.getRight() + dx, deleteHeight);
} else if (changedView == deleteView) {
contentView.layout(contentView.getLeft() + dx, 0, contentView.getRight() + dx, deleteHeight);
}
//判断开关逻辑
if (contentView.getLeft() == 0) {
//说明state应更改为关闭
currentState = SwipeState.Close;
//清空已打开swipelayout记录
SwipeLayoutManager.getInstance().clearCurrentLayout();
} else if (contentView.getLeft() == -deleteWidth) {
//说明state应更改为打开
currentState = SwipeState.Open;
//记录已打开swipelayout
SwipeLayoutManager.getInstance().setCurrentLayout(SwipeLayout.this);
}
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (contentView.getLeft() < -deleteWidth / 2) {
//应该打开
open();
} else {
//应该关闭
close();
}
}
};
//打开swipelayout
private void open() {
dragHelper.smoothSlideViewTo(contentView, -deleteWidth, 0);
ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
}
//关闭swipelayout
public void close() {
dragHelper.smoothSlideViewTo(contentView, 0, 0);
ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
}
//恢复swipelayout至初始位置
public void resume() {
contentView.layout(0,0,contentWidth,deleteHeight);
deleteView.layout(contentView.getRight(),0,contentView.getRight()+deleteWidth,deleteHeight);
}
@Override
public void computeScroll() {
if (dragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
}
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
//让dragHelper决定是否拦截事件
boolean b = dragHelper.shouldInterceptTouchEvent(ev);
if (!SwipeLayoutManager.getInstance().isShouldOpen(this)) {
b = true;//将事件传递给onTouchEvent
//当前swipelayout不能滑动,先关闭swipelayout
SwipeLayoutManager.getInstance().closeSwipeLayout();
//请求父类不要拦截事件
requestDisallowInterceptTouchEvent(true);
}
return b;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//如果有已打开的swipelayout,则先关闭
if (!SwipeLayoutManager.getInstance().isShouldOpen(this)) {
//消费掉触摸事件
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
float moveX = event.getX();
float moveY = event.getY();
float delatX = moveX - downX;
float delatY = moveY - downY;
if (Math.abs(delatX) > Math.abs(delatY)) {
//禁止listview拦截事件
requestDisallowInterceptTouchEvent(true);
}
downX = moveX;
downY = moveY;
break;
case MotionEvent.ACTION_UP:
break;
}
//交给dragHelper处理触摸事件
dragHelper.processTouchEvent(event);
return true;
}
}
4.3 MainActivity.java
package com.weizh.swipedelete;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import com.weizh.swipedelete.manager.SwipeLayoutManager;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
private ListView lvListView;
private ArrayList<String> strings;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initData() {
//1.设置数据
strings = new ArrayList<>();
for (int i=0;i<30;i++) {
strings.add("name - "+i);
}
lvListView.setAdapter(new MyAdapter());
lvListView.setOnScrollListener(new AbsListView.OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView absListView, int scrollState) {
if(scrollState==SCROLL_STATE_TOUCH_SCROLL){
//垂直滑动则需要关闭已经打开的swipelayout
SwipeLayoutManager.getInstance().closeSwipeLayout();
}
}
@Override
public void onScroll(AbsListView absListView, int i, int i1, int i2) {
}
});
}
private void initView() {
lvListView=(ListView) findViewById(R.id.lv_list);
}
class MyAdapter extends BaseAdapter{
@Override
public int getCount() {
return strings.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(final int position, View convertView, ViewGroup viewGroup) {
ViewHolder holder=null;
if (convertView==null){
convertView=View.inflate(getApplicationContext(),R.layout.list_item,null);
holder=new ViewHolder();
holder.tvName= (TextView) convertView.findViewById(R.id.tv_name);
holder.tvDelete= (TextView) convertView.findViewById(R.id.tv_delete);
convertView.setTag(holder);
}else {
holder= (ViewHolder) convertView.getTag();
}
holder.tvName.setText(strings.get(position));
//给delete textview设置点击事件
holder.tvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//恢复swipelayout至初始位置
SwipeLayoutManager.getInstance().resumeSwipeLayout();
//清除swipelayout打开记录
SwipeLayoutManager.getInstance().clearCurrentLayout();
strings.remove(position);//从集合中移除对应的条目数据
notifyDataSetChanged();//通知数据更新
}
});
return convertView;
}
}
class ViewHolder{
public TextView tvName;
public TextView tvDelete;
}
}
5. 布局文件
5.1 activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.weizh.swipedelete.MainActivity">
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/lv_list"
></ListView>
</LinearLayout>
5.2 layout_content.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="80dp"
android:paddingLeft="15dp"
android:background="#33666666"
android:gravity="center_vertical"
android:orientation="horizontal" >
<ImageView android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/head_1"/>
<TextView android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="#99000000"
android:id="@+id/tv_name"
android:layout_marginLeft="10dp"
android:textSize="20sp"
android:text="名称"/>
</LinearLayout>
5.3 layout_delete.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="80dp"
android:orientation="horizontal" >
<TextView android:layout_width="100dp"
android:layout_height="match_parent"
android:textSize="18sp"
android:textColor="#ffffff"
android:gravity="center"
android:background="#aa000000"
android:text="Call"/>
<TextView android:layout_width="100dp"
android:layout_height="match_parent"
android:textSize="18sp"
android:textColor="#ffffff"
android:id="@+id/tv_delete"
android:gravity="center"
android:background="#eeff0000"
android:text="Delete"/>
</LinearLayout>
5.4 list_item.xml
<?xml version="1.0" encoding="utf-8"?>
<com.weizh.swipedelete.widget.SwipeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/sd_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<include layout="@layout/layout_content" />
<include layout="@layout/layout_delete" />
</com.weizh.swipedelete.widget.SwipeLayout>
6.运行效果图: