仿照QQ的删除效果

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_32673327/article/details/52020870

前几天看到手机QQ中的聊天列表的删除功能的效果比较好,于是就仿照来做了下,下面是效果图:

首先是MainActivity,下面是代码:

package com.example.slidedel;


import java.util.ArrayList;


import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.BaseAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;


import com.example.slidedel.SwipeLayout.OnSwipeStateChangeListener;


public class MainActivity extends Activity {
private ListView listview;
private ArrayList<String> list = new ArrayList<String>();
private MyAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listview);
//1.准备数据
for (int i = 0; i < 30; i++) {
list.add("name - "+i);
}
mAdapter = new MyAdapter();
listview.setAdapter(mAdapter);


listview.setOnScrollListener(new OnScrollListener() {
@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
if(scrollState==OnScrollListener.SCROLL_STATE_TOUCH_SCROLL){
//如果垂直滑动,则需要关闭已经打开的layout
SwipeLayoutManager.getInstance().closeCurrentLayout();
}
}
@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
}
});
}


@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}


class MyAdapter extends BaseAdapter implements OnSwipeStateChangeListener{
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
if(convertView==null){
convertView=View.inflate(MainActivity.this, R.layout.adapter_list, null);
}
ViewHolder holder = ViewHolder.getHolder(convertView);

holder.tv_name.setText(list.get(position));

holder.swipeLayout.setTag(position);
holder.swipeLayout.setOnSwipeStateChangeListener(this);
holder.tv_delete.setOnClickListener(new OnClickListener() {

@Override
public void onClick(View v) {
list.remove(position);
mAdapter.notifyDataSetChanged();
SwipeLayoutManager.getInstance().closeCurrentLayout();
}
});

return convertView;
}
@Override
public void onOpen(Object tag) {
Toast.makeText(MainActivity.this,"第"+(Integer)tag+"个打开", 0).show();
}
@Override
public void onClose(Object tag) {
Toast.makeText(MainActivity.this,"第"+(Integer)tag+"个关闭", 0).show();
}

}

static class ViewHolder{
TextView tv_name,tv_delete;
SwipeLayout swipeLayout;
public ViewHolder(View convertView){
tv_name = (TextView) convertView.findViewById(R.id.tv_name);
tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);
swipeLayout = (SwipeLayout) convertView.findViewById(R.id.swipeLayout);
}
public static ViewHolder getHolder(View convertView){
ViewHolder holder = (ViewHolder) convertView.getTag();
if(holder==null){
holder = new ViewHolder(convertView);
convertView.setTag(holder);
}
return holder;
}
}
}

接下来就是重点,也就是我们自定义控件来实现的效果:

package com.example.slidedel;


import android.content.Context;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.ViewDragHelper;
import android.support.v4.widget.ViewDragHelper.Callback;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.FrameLayout;


public class SwipeLayout extends FrameLayout {


private View contentView;
private View delView;
private int delHeight;
private int delWidth;
private int contentWidth;
private ViewDragHelper viewDragHelper;


public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}


public SwipeLayout(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}


public SwipeLayout(Context context) {
super(context);
init();
}


private void init() {
viewDragHelper = ViewDragHelper.create(this, callback);
}


private ViewDragHelper.Callback callback = new Callback() {


@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == contentView || child == delView;
}


public int getViewHorizontalDragRange(View child) {
return delWidth;
};


@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (child == contentView) {
if (left > 0) {
left = 0;
}
if (left < -delWidth) {
left = -delWidth;
}
}
if (child == delView) {
if (left > contentWidth) {
left = contentWidth;
}
if (left < contentWidth - delWidth) {
left = contentWidth - delWidth;
}
}
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) {
delView.layout(delView.getLeft() + dx, delView.getTop() + dy,
delView.getRight() + dx, delView.getBottom() + dy);
} else if (changedView == delView) {
contentView.layout(contentView.getLeft() + dx,
contentView.getTop() + dy, contentView.getRight() + dx,
contentView.getBottom() + dy);
}
// 判断开关的逻辑
if (contentView.getLeft() == 0 && currentState != SwipeState.Close) {
// 关闭
currentState = SwipeState.Close;
if (listener!=null) {
listener.onClose(getTag());
}
// 当前关闭
SwipeLayoutManager.getInstance().clearCurrentLayout();
} else if (contentView.getLeft() == -delWidth
&& currentState != SwipeState.Open) {
currentState = SwipeState.Open;
if (listener!=null) {
listener.onOpen(getTag());
}
// 当前打开
SwipeLayoutManager.getInstance().setSwipeLayout(
SwipeLayout.this);
}
}


@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, activePointerId);
}


@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
if (contentView.getLeft() < -delWidth / 2) {
// 打开
open();
} else {
// 关闭
close();
}
}


};


public void close() {
viewDragHelper.smoothSlideViewTo(contentView, 0, contentView.getTop());
ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
}


public void open() {
viewDragHelper.smoothSlideViewTo(contentView, -delWidth,
contentView.getTop());
ViewCompat.postInvalidateOnAnimation(SwipeLayout.this);
}


public void computeScroll() {
if (viewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}


public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean result = viewDragHelper.shouldInterceptTouchEvent(ev);
// 如果有打开的,需要拦截,交给ontouch处理
if (!SwipeLayoutManager.getInstance().isShouldSwipe(this)) {
SwipeLayoutManager.getInstance().closeCurrentLayout();


result = true;
}
return result;
};


enum SwipeState {
Open, Close;
}


private SwipeState currentState = SwipeState.Close;// 当前默认是关闭状态
private float downX, downY;


@Override
public boolean onTouchEvent(MotionEvent event) {
// 判断当前是否可以打开
if (!SwipeLayoutManager.getInstance().isShouldSwipe(this)) {
// 先关闭已经打开的
requestDisallowInterceptTouchEvent(true);
return true;
}
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = event.getX();
downY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
// 1.获取x和y方向移动的距离
float moveX = event.getX();
float moveY = event.getY();
float delatX = moveX - downX;// x方向移动的距离
float delatY = moveY - downY;// y方向移动的距离
if (Math.abs(delatX) > Math.abs(delatY)) {
// 表示移动是偏向于水平方向,那么应该SwipeLayout应该处理,请求listview不要拦截
requestDisallowInterceptTouchEvent(true);
}
// 更新downX,downY
downX = moveX;
downY = moveY;
break;
case MotionEvent.ACTION_UP:


break;


default:
break;
}
viewDragHelper.processTouchEvent(event);
return true;
}


@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
delHeight = delView.getMeasuredHeight();
delWidth = delView.getMeasuredWidth();
contentWidth = contentView.getMeasuredWidth();


}


@Override
protected void onFinishInflate() {
super.onFinishInflate();
contentView = getChildAt(0);
delView = getChildAt(1);
}


@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
// super.onLayout(changed, left, top, right, bottom);


contentView.layout(0, 0, contentWidth, delHeight);
delView.layout(contentView.getRight(), 0, contentView.getRight()
+ delWidth, delHeight);
}


private OnSwipeStateChangeListener listener;


public void setOnSwipeStateChangeListener(
OnSwipeStateChangeListener listener) {
this.listener = listener;
}


public interface OnSwipeStateChangeListener {
void onOpen(Object tag);


void onClose(Object tag);
}


}

最后这里是一个layout的管理者对象:

package com.example.slidedel;


public class SwipeLayoutManager {
private SwipeLayoutManager(){}
private static SwipeLayoutManager mInstance = new SwipeLayoutManager();

public static SwipeLayoutManager getInstance(){
return mInstance;
}

private SwipeLayout currentLayout;//用来记录当前打开的SwipeLayout
public void setSwipeLayout(SwipeLayout layout){
this.currentLayout = layout;
}

/**
* 清空当前所记录的已经打开的layout
*/
public void clearCurrentLayout(){
currentLayout = null;
}

/**
* 关闭当前已经打开的SwipeLayout
*/
public void closeCurrentLayout(){
if(currentLayout!=null){
currentLayout.close();
}
}

/**
* 判断当前是否应该能够滑动,如果没有打开的,则可以滑动。
* 如果有打开的,则判断打开的layout和当前按下的layout是否是同一个

* @return
*/
public boolean isShouldSwipe(SwipeLayout swipeLayout){
if(currentLayout==null){
//说明当前木有打开的layout
return true;
}else {
//说明有打开的layout
return currentLayout==swipeLayout;
}
}
}

附上下载链接:http://download.csdn.net/detail/qq_32673327/9585222

猜你喜欢

转载自blog.csdn.net/qq_32673327/article/details/52020870