高仿QQ侧滑item删除的自定义ListView
2017-04-28 14:47
281 查看
预览效果GIF图:
带注释源码:
注释中已将实现步骤写好,欢迎留言交流,运行Mode地址:https://github.com/jiarWang/AndroidView/tree/master/SlideListView_4_28
自定义SlideAdapter源码:
adapter源码比较简单,只是需要说明的是,要将SlideListView对象传递进来,在执行删除操作时需要。
public class SlideAdapter extends BaseAdapter {
private List<String> list = new ArrayList<>();
private LayoutInflater inflater;
private SlideListView listView;
SlideAdapter(Context context, List<String> data, SlideListView listView){
list.clear();
list.addAll(data);
inflater = LayoutInflater.from(context);
this.listView = listView;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.slide_item, parent, false);
holder = new Holder();
holder.tv_content = (TextView) convertView.findViewById(R.id.tv_content);
holder.tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);
convertView.setTag(holder);
}else {
holder = (Holder) convertView.getTag();
}
holder.tv_content.setText(getItem(position).toString());
holder.tv_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
list.remove(position);
listView.turnToNormal();
notifyDataSetChanged();
}
});
return convertView;
}
class Holder{
TextView tv_content;
TextView tv_delete;
}
}
实例化及适配器的使用:
带注释源码:
注释中已将实现步骤写好,欢迎留言交流,运行Mode地址:https://github.com/jiarWang/AndroidView/tree/master/SlideListView_4_28
public class SlideListView extends ListView { private final int CONTENT_POSITION = 0; private final int DELETE_POSITION = 1; private int mScreenWidth; //屏幕宽度 private int deleteWidth; private ViewGroup targetItemViewGroup; //被标记item private boolean isSelect; //是否有选中,标记 private int downX; //DOWN时的X private int downY; private LinearLayout.LayoutParams childOneParams; //padding操作的child数据 public SlideListView(Context context) { super(context, null); init(context); } public SlideListView(Context context, AttributeSet attrs) { super(context, attrs); init(context); } public SlideListView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public SlideListView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(context); } private void init(Context context) { WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); DisplayMetrics displayMetrics = new DisplayMetrics(); wm.getDefaultDisplay().getMetrics(displayMetrics); mScreenWidth = displayMetrics.widthPixels; } @Override public boolean onTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: return performActionAsDown(ev); case MotionEvent.ACTION_MOVE: performActionAsMove(ev); break; case MotionEvent.ACTION_UP: performActionAsUp(ev); break; } return super.onTouchEvent(ev); } /** * 1、获取屏幕宽度,绘制当前的子item,使其保持DOWN前的状态 * 2、判断是否有item已经被选中标记(有Delete控件); * 如果已经有被标记item,判断被标记item是否为当前点击处对应的item? * 是:则此时不做处理, * 否:则还原被标记item,拦截事件 * 如果没有,则将当前DOWN处的作为标记item * */ private boolean performActionAsDown(MotionEvent ev) { downX = (int)ev.getX(); downY 4000 = (int)ev.getY(); ViewGroup tmpItem = (ViewGroup) this.getChildAt(pointToPosition(downX, downY) - getFirstVisiblePosition()); if (isSelect){ if (tmpItem != targetItemViewGroup){ turnToNormal(); return false; } }else{ targetItemViewGroup = tmpItem; childOneParams = (LinearLayout.LayoutParams) targetItemViewGroup.getChildAt(CONTENT_POSITION).getLayoutParams(); childOneParams.width = mScreenWidth; targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams); deleteWidth = targetItemViewGroup.getChildAt(DELETE_POSITION).getLayoutParams().width; } return true; } /** * 重置选中item视图,标记判断置位false,选中item置为null * */ public void turnToNormal() { if (targetItemViewGroup != null){ childOneParams.leftMargin = 0; targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams); isSelect = false; } } /**通过performActionAsDown后,只有被标记item才有MOVE响应 * 判断是否有item已经被选中标记(有Delete控件); * 是:判断手势-->向左不处理,向右则修改Child的padding,不得超过padding界线 * 否:判断手势-->向右不处理,向左则修改Child的padding,不得超过padding界线 * */ private void performActionAsMove(MotionEvent ev) { if (targetItemViewGroup == null) return; int moveX = (int) ev.getX(); int moveY = (int)ev.getY(); int diffX = moveX - downX; int diffY = moveY - downY; if (isSelect){ if (diffX > 0 && Math.abs(diffX) > Math.abs(diffY)){ //右滑 if (diffX > deleteWidth){ diffX = deleteWidth; } childOneParams.leftMargin = diffX - deleteWidth; } }else { if (diffX < 0 && Math.abs(diffX) > Math.abs(diffY)){ if (Math.abs(diffX) > deleteWidth){ diffX = -deleteWidth; } childOneParams.leftMargin = diffX; } } targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams); } /** * 判断是否有选中标记位? * 有:标记item的Delete控件全显示,设置标志位 * 无:则标记item至为normal,设置标志位 * */ private void performActionAsUp(MotionEvent ev) { int upX = (int) ev.getX(); int upY = (int)ev.getY(); int diffX = upX - downX; int diffY = upY - downY; if (! isSelect && diffX < 0 && Math.abs(diffX) > Math.abs(diffY)){ isSelect = true; childOneParams.leftMargin = - deleteWidth; }else if (isSelect && diffX > 0 && Math.abs(diffX) > Math.abs(diffY)){ childOneParams.leftMargin = 0; isSelect = false; } targetItemViewGroup.getChildAt(CONTENT_POSITION).setLayoutParams(childOneParams); } }
自定义SlideAdapter源码:
adapter源码比较简单,只是需要说明的是,要将SlideListView对象传递进来,在执行删除操作时需要。
public class SlideAdapter extends BaseAdapter {
private List<String> list = new ArrayList<>();
private LayoutInflater inflater;
private SlideListView listView;
SlideAdapter(Context context, List<String> data, SlideListView listView){
list.clear();
list.addAll(data);
inflater = LayoutInflater.from(context);
this.listView = listView;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
Holder holder = null;
if (convertView == null) {
convertView = inflater.inflate(R.layout.slide_item, parent, false);
holder = new Holder();
holder.tv_content = (TextView) convertView.findViewById(R.id.tv_content);
holder.tv_delete = (TextView) convertView.findViewById(R.id.tv_delete);
convertView.setTag(holder);
}else {
holder = (Holder) convertView.getTag();
}
holder.tv_content.setText(getItem(position).toString());
holder.tv_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
list.remove(position);
listView.turnToNormal();
notifyDataSetChanged();
}
});
return convertView;
}
class Holder{
TextView tv_content;
TextView tv_delete;
}
}
实例化及适配器的使用:
slideListView = (SlideListView) findViewById(R.id.slideView); slideAdapter = new SlideAdapter(this, data, slideListView); slideListView.setAdapter(slideAdapter);
相关文章推荐
- Android学习自定义View(四)——继承控件(滑动时ListView的Item出现删除按钮)
- 自定义ListView,实现Item侧滑删除及侧滑出菜单效果
- android 滑动删除的listview(自定义view)
- Android ListView左滑删除、左滑自定义功能
- Android自定义Dialog,实现长按ListView删除当中item数据
- 自定义组件—ListView_加头去头,加脚去脚、添加或删除ListView中的数据、
- 仿QQ侧滑删除,自定义ListView
- 开源控件学习之-侧滑listview进行删除(一)(自定义listview)
- 滑动删除--自定义ListView
- 自定义一个带删除按钮的ListView
- 自定义View之可删除item的ListView
- Delphi中ListView中实现自定义删除功能的方法
- ListView自定义按钮实例-标记删除功能
- Android仿QQ和iOS的ListView左滑出现删除和置顶等操作,可自定义菜单
- Android 自定义ListView控件,滑动删除
- 自定义listview 实现仿qq聊天列表左滑删除效果
- Android自定义View之ListView条目滑动删除(仿QQ5.1)
- 自定义listView添加滑动删除功能
- 自定义SwipeLayout控件实现ListView条目侧滑出现删除按钮,点击实现删除ListView条目
- 自定义实现ListView左滑删除