开心一刻:
A:嘿 //是什么意思啊?
B:嘿.
A:呃我问你//是什么意思?
B:问吧.
A:我刚才不是问了么?
B:啊?
A:你再看看记录…
B:看完了.
A:……所以//是啥?
B:所以什么?
扫描二维码关注公众号,回复:
8489148 查看本文章
A:你存心耍我呢吧?
B:没有啊你想问什么?
……
不断循环之后,A一气之下和B绝交,自己苦学程序。
N年之后,A终于修成正果,回想起B
,又把聊天记录翻出来看,这时,他突然发现B没有耍他……
而他自己也不知道当年他问B的究竟是什么问题……
简言:
实现一个侧拉删除的效果,仿照qq侧拉删除,进行功能的简单实现。侧拉删除的效果,还是非常常见的,有一个第三方可以直接引用,之前在项目中实现过一次,今天分享给大家,我提供的是一个demo,比较简单的实现,该demo简单,易扩展。
效果展示:
代码展示:(代码里面有注解 详细讲解了功能的实现)
/**
* Created by Administrator on 2019/2/19 0019.
* 策划菜单
*/
public class SlideLayout extends FrameLayout {
private View contentView;
private View deleteView;
private int contentWidth;
private int deleteWidth;
private int viewHeight;//他们的高相等
//滚动器
private Scroller scroller;
private float endX;
private float endY;
public SlideLayout(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
scroller = new Scroller(context);
}
/**
* 当布局文件加载完成的时候回调方法
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
contentView = getChildAt(0);
deleteView = getChildAt(1);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
contentWidth = contentView.getMeasuredWidth();
deleteWidth = deleteView.getMeasuredWidth();
viewHeight = getMeasuredHeight();
}
@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
super.onLayout(changed, left, top, right, bottom);
//指定菜单的位置 将删除按钮放置最右边 进行隐藏
deleteView.layout(contentWidth, 0, contentWidth + deleteWidth, viewHeight);
}
private float startX;
private float startY;
private float downX;//值赋值一次
private float downY;
@Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下记录坐标
downX = startX = event.getX();
downY = startY = event.getY();
break;
case MotionEvent.ACTION_MOVE:
//记录我们的结束值
endX = event.getX();
endY = event.getY();
//计算偏移量
float distancexX = endX - startX;
int toScrollx = (int) (getScrollX() - distancexX);
//屏蔽非法值
if (toScrollx < 0) {
toScrollx = 0;
} else if (toScrollx > deleteWidth) {
toScrollx = deleteWidth;
}
scrollTo(toScrollx, getScrollY());
startX = event.getX();
startY = event.getY();
//在x轴和Y轴滑动的距离
float dx = Math.abs(endX - downX);
float dy = Math.abs(endY - downY);
if (dx > dy && dx >8) {
//水平滑动 响应水平拦截 反拦截 事件给slidlayout
getParent().requestDisallowInterceptTouchEvent(true);
}
break;
case MotionEvent.ACTION_UP:
int totalScrollX = getScrollX();//偏移量
if (totalScrollX < deleteWidth / 2) {
//关闭菜单
closeMenu();
} else {
//打开菜单
openMenu();
}
break;
}
return true;
}
/**
* 关闭删除菜单
*/
public void closeMenu() {
int distanceX = 0 - getScrollX();
scroller.startScroll(getScrollX(), getScrollY(), distanceX, getScrollY());
invalidate();//强制刷新
if(onStateChangeListener != null){
onStateChangeListener.onClose(this);
}
}
public void openMenu() {
int distanceX = deleteWidth - getScrollX();
scroller.startScroll(getScrollX(), getScrollY(), distanceX, getScrollY());
invalidate();//强制刷新
if(onStateChangeListener != null){
onStateChangeListener.onOpen(this);
}
}
@Override
public void computeScroll() {
super.computeScroll();
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
invalidate();
}
}
/**
* TRUE 拦截孩子的时间 但会执行当前控件的onTouchEvent方法
* false 不拦截孩子事件 事件继续传递
* */
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean intercept = false;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//按下记录坐标
downX = startX = ev.getX();
if(onStateChangeListener != null){
onStateChangeListener.onDown(this);
}
break;
case MotionEvent.ACTION_MOVE:
//记录我们的结束值
endX = ev.getX();
endX = ev.getX();
//计算偏移量
float distancexX = endX - startX;
//在x轴和Y轴滑动的距离
float dx = Math.abs(endX - downX);
if (dx > 8) {
intercept = true;
}
break;
case MotionEvent.ACTION_UP:
break;
}
return intercept;
}
/**
* 监听SlienLayout状态的改变
*
* */
public interface onStateChangeListener{
void onClose(SlideLayout slideLayout);
void onDown(SlideLayout slideLayout);
void onOpen(SlideLayout slideLayout);
}
private onStateChangeListener onStateChangeListener;
public void setOnStateChangeListener(SlideLayout.onStateChangeListener onStateChangeListener) {
this.onStateChangeListener = onStateChangeListener;
}
}
public class MainActivity extends AppCompatActivity {
private ListView lv_main;
private ArrayList<MyBean> list;
private SlideLayout slideLayouts;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
list = new ArrayList<>();
initData();
//添加数据
initView();
}
private void initData() {
for (int i = 0 ;i<100;i++){
list.add(new MyBean("CONTENT"+i));
}
}
private void initView() {
lv_main = findViewById(R.id.lv_main);
lv_main.setAdapter( new MyAdapter());
}
class MyAdapter extends BaseAdapter{
@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) {
ViewHolder viewHolder;
if(convertView == null){
convertView = View.inflate(MainActivity.this,R.layout.item_main,null);
viewHolder= new ViewHolder();
viewHolder.itemContent = convertView.findViewById(R.id.item_content);
viewHolder.itemMenu = convertView.findViewById(R.id.item_menu);
convertView.setTag(viewHolder);
}else{
viewHolder= (ViewHolder) convertView.getTag();
}
final MyBean myBean = list.get(position);
viewHolder.itemContent.setText(myBean.getName());
viewHolder.itemContent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
MyBean myBean1 = list.get(position);
Toast.makeText(MainActivity.this,myBean1.getName(),Toast.LENGTH_SHORT).show();
}
});
viewHolder.itemMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
SlideLayout slideLayout = (SlideLayout) v.getParent();
slideLayout.closeMenu();
list.remove(myBean);
notifyDataSetChanged();
}
});
SlideLayout slideLayout = (SlideLayout) convertView;
slideLayout.setOnStateChangeListener(new SlideLayout.onStateChangeListener() {
@Override
public void onClose(SlideLayout slideLayout) {
if(slideLayouts == slideLayout){
slideLayouts = null;
}
}
@Override
public void onDown(SlideLayout slideLayout) {
if(slideLayouts !=null &&slideLayouts != slideLayout){
slideLayouts.closeMenu();
}
}
@Override
public void onOpen(SlideLayout slideLayout) {
slideLayouts = slideLayout;
}
});
return convertView;
}
}
static class ViewHolder{
TextView itemContent;
TextView itemMenu;
}
}
这是实现的两个主要类(可在博客中进行观看)
自定义的view的使用
<?xml version="1.0" encoding="utf-8"?>
<com.zzsy.listviewdelete.SlideLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dp">
<include
android:id="@+id/item_content"
layout="@layout/item_content"/>
<include
android:id="@+id/item_menu"
layout="@layout/item_menu"/>
</com.zzsy.listviewdelete.SlideLayout>
项目地址: