GitHub地址:

https://github.com/OOOOOldZhu/DrawerItemView

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;

public class SwipeLayout extends FrameLayout {

    private View content;
    private View delete;

    ViewDragHelper dragHelper;

    public SwipeLayout(Context context) {
        this(context, null);
    }

    public SwipeLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SwipeLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //初始化ViewDragHelper
        dragHelper = ViewDragHelper.create(this, callback);
    }
    //只有完成系统对xml文件完成最后标签的解析,才能获得子控件
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        content = getChildAt(0);
        delete = getChildAt(1);
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        content.layout(0, 0, content.getMeasuredWidth(),
            content.getMeasuredHeight());
        int L = content.getRight();
        //content(右下角)的right(距原点的x距离)即为 delete控件的左上角的x坐标
        delete.layout(L, 0, L + delete.getMeasuredWidth(),
            delete.getMeasuredHeight());
    }
    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
//让helper处理拦截事件 boolean result = dragHelper.shouldInterceptTouchEvent(ev); return result; } float downX,downY; @Override public boolean onTouchEvent(MotionEvent event) { 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 dx = moveX - downX; float dy = moveY - downY; //判断到底偏向于哪个方向 if(Math.abs(dx)>Math.abs(dy)){ //说明是偏向水平方向,那么就认为用户想滑动条目,此时应该让listview不要拦截 requestDisallowInterceptTouchEvent(true); } break; case MotionEvent.ACTION_UP: break; } dragHelper.processTouchEvent(event); return true; } // 回调方法 ViewDragHelper.Callback callback = new ViewDragHelper.Callback() { @Override public boolean tryCaptureView(View child, int pointerId) { return true; } @Override public int getViewHorizontalDragRange(View child) { return 1; } //修正子控件的位置坐标的方法 @Override public int clampViewPositionHorizontal(View child, int left, int dx) { //限制content if(child==content){ if(left>0){ left = 0; }else if(left<-delete.getMeasuredWidth()){ left = -delete.getMeasuredWidth(); } }else if(child==delete){ //限制delete if(left>content.getMeasuredWidth()){ left = content.getMeasuredWidth(); }else if(left<(content.getMeasuredWidth()- delete.getMeasuredWidth())) { left = (content.getMeasuredWidth()- delete.getMeasuredWidth()); } } return left; } @Override public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) { super.onViewPositionChanged(changedView, left, top, dx, dy); //如果移动的是content,那么让delete伴随移动 if(changedView==content){ // int newLeft = delete.getLeft()+dx; // delete.layout(newLeft,0,newLeft+delete.getMeasuredWidth(),delete.getMeasuredHeight()); ViewCompat.offsetLeftAndRight(delete,dx); }else if(changedView==delete){ //让content进行伴随移动 ViewCompat.offsetLeftAndRight(content,dx); } //回调接口的方法 if(listener!=null){ if(content.getLeft()==0){ listener.onClose(SwipeLayout.this); }else if(content.getLeft()==-delete.getMeasuredWidth()){ listener.onOpen(SwipeLayout.this); } } } @Override public void onViewReleased(View releasedChild, float xvel, float yvel) { super.onViewReleased(releasedChild, xvel, yvel); if(content.getLeft()>-delete.getMeasuredWidth()/2){ //关闭抽屉 closeLayout(); }else { //打开抽屉 openLayout(); } } }; /** * 打开 */ public void openLayout() { dragHelper.smoothSlideViewTo(content,-delete. getMeasuredWidth(),0); ViewCompat.postInvalidateOnAnimation(this); } /** * 关闭 */ public void closeLayout() { dragHelper.smoothSlideViewTo(content,0,0); ViewCompat.postInvalidateOnAnimation(this); } @Override public void computeScroll() { super.computeScroll(); if(dragHelper.continueSettling(true)){ ViewCompat.postInvalidateOnAnimation(this); } } private OnSwipeListener listener; public void setOnSwipeListener(OnSwipeListener listener){ this.listener = listener; } public interface OnSwipeListener{ void onOpen(SwipeLayout currentLayout); void onClose(SwipeLayout currentLayout); } }

MainActivity中:

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
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 butterknife.Bind;
import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity {

    private ListView listview;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        listview = (ListView) findViewById(R.id.listview);

        listview.setAdapter(new MyAdapter());

        //监听listview的滚动
        listview.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if(openedLayout!=null){
                    openedLayout.closeLayout();
                }
            }
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            }
        });

    }
    SwipeLayout openedLayout;//用来记录打开的SwipeLayout
    class MyAdapter extends BaseAdapter implements
        SwipeLayout.OnSwipeListener{
        @Override
        public int getCount() {
            return Constant.NAMES.length;
        }

        @Override
        public Object getItem(int position) {
            return null;
        }

        @Override
        public long getItemId(int position) {
            return 0;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            MyHolder myHolder = null;
            if(convertView==null){
                convertView = View.inflate(parent.getContext(), R.layout.adapter_list,
                    null);
                myHolder = new MyHolder(convertView);
                convertView.setTag(myHolder);
            }else {
                myHolder = (MyHolder) convertView.getTag();
            }

            //绑定数据
            myHolder.tvName.setText(Constant.NAMES[position]);

            //设置监听器
            myHolder.swipeLayout.setOnSwipeListener(this);

            return convertView;
        }
        @Override
        public void onOpen(SwipeLayout currentLayout) {
            //应该关闭当前已经打开的
            if(openedLayout!=null && openedLayout!=currentLayout){
                openedLayout.closeLayout();
            }

            openedLayout = currentLayout;
        }
        @Override
        public void onClose(SwipeLayout currentLayout) {
            if(openedLayout==currentLayout){
                openedLayout = null;
            }
        }
    }
    static class MyHolder {
        @Bind(R.id.tv_name)
        TextView tvName;
        @Bind(R.id.tv_delete)
        TextView tvDelete;
        @Bind(R.id.swipeLayout)
        SwipeLayout swipeLayout;

        MyHolder(View view) {
            ButterKnife.bind(this, view);

        }
    }
}

仿qq的条目抽屉动画效果_ViewDragHelper的更多相关文章

  1. 【Android UI设计与开发】第03期:引导界面(三)仿微信引导界面以及动画效果

    基于前两篇比较简单的实例做铺垫之后,这一篇我们来实现一个稍微复杂一点的引导界面的效果,当然也只是稍微复杂了一点,对于会的人来说当然还是so easy!正所谓会者不难,难者不会,大概说的就是这个意思了吧 ...

  2. android开发学习 ------- 仿QQ侧滑效果的实现

    需要做一个仿QQ侧滑删除的一个效果: 一开始是毫无头绪,百度找思路,找到  https://blog.csdn.net/xiaxiazaizai01/article/details/53036994  ...

  3. Android高仿qq及微信底部菜单的几种实现方式

    最近项目没那么忙,想着开发app的话,有很多都是重复,既然是重复的,那就没有必要每次都去写,所以就想着写一个app通用的基本框架,这里说的框架不是什么MVC,MVP,MVVM这种,而是app开发的通用 ...

  4. wing带你玩转自定义view系列(2) 简单模仿qq未读消息去除效果

    上一篇介绍了贝塞尔曲线的简单应用 仿360内存清理效果 这一篇带来一个  两条贝塞尔曲线的应用 : 仿qq未读消息去除效果. 转载请注明出处:http://blog.csdn.net/wingicho ...

  5. Fragment,仿QQ空间

    转载请注明出处:http://blog.csdn.net/yangyu20121224/article/details/9023451          在今天的这篇文章当中,我依然会以实战加理论结合 ...

  6. Android仿QQ窗口的抖动的动画效果

    就是仿照QQ窗口的抖动效果,在项目的res下创建anim文件夹,再创建两个xml文件:cycle.xml  . myanim.xml   cycle.xml  :   <?xml version ...

  7. Android -- 自定义ViewGroup+贝塞尔+属性动画实现仿QQ点赞效果

    1,昨天我们写了篇简单的贝塞尔曲线的应用,今天和大家一起写一个QQ名片上常用的给别人点赞的效果,实现效果图如下: 红心的图片比较丑,见谅见谅(哈哈哈哈哈哈).... 2,实现的思路和原理 从上面的效果 ...

  8. android 自定义scrollview 仿QQ空间效果 下拉伸缩顶部图片,上拉回弹 上拉滚动顶部title 颜色渐变

    首先要知道  自定义scrollview 仿QQ效果 下拉伸缩放大顶部图片 的原理是监听ontouch事件,在MotionEvent.ACTION_MOVE事件时候,使用不同倍数的系数,重置布局位置[ ...

  9. 安卓仿QQ红包领取详情界面动画

    为了能清楚的看到这个效果,本人不惜几次花费重金给众群叼发放红包,来查看红包领取详情界面的动画效果,QQ效果如图: 图中我们可以看到,动画处的头像和文字是一起的,即同时并且是整体,注意,是整体进行缩放的 ...

随机推荐

  1. XDCTF 2013 code2 跳出死循环

    题目:编写一个程序(比如kernel module),使附件2.c中的程序跳出死循环.2.c中的代码如下:#include int main(int argc, char *argv[]){int n ...

  2. java正则表达式去除html标签

    当我们用ckeditor或其他一些在线文本编辑器的时候 内容里会有很多的标签 如下片段: <p><img alt="" src="/img/upload ...

  3. ShardedJedis实现学习

    ShardedJedis实现学习-我们到底能走多远系列(33) 我们到底能走多远系列(31) 扯淡: 工作是容易的赚钱是困难的 恋爱是容易的成家是困难的 相爱是容易的相处是困难的 决定是容易的可是等待 ...

  4. Javascript:再论Javascript的单线程机制 之 DOM渲染时机

    Javascript:再论Javascript的单线程机制 之 DOM渲染时机 背景 Javascript是单线程事件驱动的,所有能看到的Javascript代码都是在一个线程执行,定时器回调和AJA ...

  5. 支持虚拟化也开来虚拟化就是装不上HyperV的解决方法

    使用NTBOOTautofix修复BCD 今日换了台性能更强劲的电脑,本是想好好爽一下,结果却是满满的悲剧.先是硬盘里的游戏一个都打不开,8.1你要不要这么烂.好吧,不娱乐,那工作吧,结果hyper又 ...

  6. php的数组与字符串的转换函数整理

    1.将一个字符串转化为数组 str_split()用于将一个字符串转化为数组 语法: str_split(string,length) //string是必须的,是要分割的字符串: //length是 ...

  7. java基础知识拾遗(二)

    1.finally public static int func (){ try{ return 1; }catch (Exception e){ return 2; }finally { retur ...

  8. IDEA异常解决: org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)

    有时候解决问题不仅仅是解决问题.-----jstarseven 最近因为开发需要,需要搭建一个ssm开发框架,采用了开发工具IDEA. 整合完了SSM开发框架之后,发布的时候出现org.apache. ...

  9. XAF-Domain Components 技术 使用接口来定义ORM业务对象

    一.简介 Domain Component组件技术,以下简称DC,是扩展自XPO的, 官方不建议新手使用DC. 如果你用过EF,XPO及类似的ORM,这是很容易理解的,DC是基于XPO的,只是原业定义 ...

  10. JS设计模式之观察者模式

    观察者模式,即发布与订阅模式,实现一对多的一种关系模式,当一种对象接受信号时其他所有依赖均有行为.我们在写code的时候总是会去自定义一些事件,这就是观察者常常使用的地方: JS中的观察者模式应用: ...