博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android开发:使用ViewDragHelper实现抽屉拉伸效果
阅读量:7087 次
发布时间:2019-06-28

本文共 5727 字,大约阅读时间需要 19 分钟。

事实上,有非常多方法能够实现一个Layout的抽屉拉伸效果,最常常的方法就是自己定义一个ViewGroup,然后控制点击事件。控制移动之类的,这样的方法的代码量多,并且实现起来复杂,后期维护添加其它效果也非常麻烦,直到今天看到了 ViewDragHelper这个类,就是专门为实现View的移动而生的。我就试着开发了一个抽屉拉伸的效果,效果图例如以下:

全部移动的控制在ViewDragHelper.Callback里面来实现。移动就用dragHelper.smoothSlideViewTo来实现,并且Callback集成了很多的方法。方便后期的维护或者添加其它功能。

首先看下最核心的DragLayout的代码

public class DragLayout extends LinearLayout {    private ViewDragHelper dragHelper;    private View mDragView, contentView;    private int dragRange;    public DragLayout(Context context) {        super(context);        init();    }    public DragLayout(Context context, AttributeSet attrs) {        super(context, attrs);        init();    }    @TargetApi(Build.VERSION_CODES.LOLLIPOP)    public DragLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        init();    }    public DragLayout(Context context, AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init();    }    private void init() {        dragHelper = ViewDragHelper.create(this, callback);    }    @Override    protected void onFinishInflate() {        super.onFinishInflate();        mDragView = findViewById(R.id.dragView);        contentView = findViewById(R.id.contentView);    }    private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {        @Override        public boolean tryCaptureView(View child, int pointerId) {            return child == mDragView;        }        @Override        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {            contentView.layout(0, top + mDragView.getHeight(), getWidth(), top + mDragView.getHeight() + dragRange);        }        @Override        public int clampViewPositionVertical(View child, int top, int dy) {            int topBound = getHeight() - dragRange - mDragView.getHeight();            int bottomBound = getHeight() - mDragView.getHeight();            final int newHeight = Math.min(Math.max(topBound, top), bottomBound);            return newHeight;        }        @Override        public int getViewVerticalDragRange(View child) {            return dragRange;        }        @Override        public void onViewReleased(View releasedChild, float xvel, float yvel) {            super.onViewReleased(releasedChild, xvel, yvel);            if (yvel > 0) {                smoothToBottom();            }else if (yvel < 0) {                smoothToTop();            }        }    };    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        dragRange = contentView.getMeasuredHeight();    }    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        mDragView.layout(0, getHeight() - mDragView.getHeight(), getWidth(), getHeight());        contentView.layout(0, getHeight(), getWidth(), getHeight() + dragRange);    }    @Override    public boolean onInterceptHoverEvent(MotionEvent event) {        final int action = MotionEventCompat.getActionMasked(event);        if (action == MotionEvent.ACTION_CANCEL || action == MotionEvent.ACTION_UP) {            dragHelper.cancel();            return false;        }        return dragHelper.shouldInterceptTouchEvent(event);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        dragHelper.processTouchEvent(event);        return true;    }    private void smoothToTop() {        if (dragHelper.smoothSlideViewTo(mDragView, getPaddingLeft(), getHeight() - dragRange - mDragView.getHeight())) {            ViewCompat.postInvalidateOnAnimation(this);        }    }    private void smoothToBottom() {        if (dragHelper.smoothSlideViewTo(mDragView, getPaddingLeft(), getHeight() - mDragView.getHeight())) {            ViewCompat.postInvalidateOnAnimation(this);        }    }    @Override    public void computeScroll() {        if (dragHelper.continueSettling(true)) {            ViewCompat.postInvalidateOnAnimation(this);        }    }}
在这里面,初始化了ViewDragHelper

dragHelper = ViewDragHelper.create(this, callback);
 
设置垂直方向的移动距离,这里设置为listview的高度:

@Override

        public int clampViewPositionVertical(View child, int top, int dy) {
            int topBound = getHeight() - dragRange - mDragView.getHeight();
            int bottomBound = getHeight() - mDragView.getHeight();
            final int newHeight = Math.min(Math.max(topBound, top), bottomBound);
            return newHeight;
        }

监听位置的移动,移动listview。让他始终挨在DrawView的以下:

@Overridepublic void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {    contentView.layout(0, top + mDragView.getHeight(), getWidth(), top + mDragView.getHeight() + dragRange);}
 
在OnLayout里面又一次布局。隐藏listView:
 
@Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        super.onLayout(changed, l, t, r, b);        mDragView.layout(0, getHeight() - mDragView.getHeight(), getWidth(), getHeight());        contentView.layout(0, getHeight(), getWidth(), getHeight() + dragRange);    }

接下来是XML的布局:

非常easy。自己定义的View里面放置两个View

最后的MainActivity:

public class MainActivity extends AppCompatActivity {    String[] listItems = {"item 1", "item 2 ", "list", "android", "item 3", "foobar", "bar", };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ListView listView = (ListView) findViewById(R.id.contentView);        listView.setAdapter(new ArrayAdapter(this,  android.R.layout.simple_list_item_1, listItems));    }}

最后,这个Demo仅仅是实现一个非常easy的功能,只是大概能够看到ViewDragHelper的强大。强烈建议去了解下,这个是两个API的地址

 

最后,附上

你可能感兴趣的文章
程序员如何优雅的记录笔记(同步云端,图床,多端发布)
查看>>
极速高清——给你带来全新的高清视野
查看>>
数据结构之链表【上】
查看>>
Go并发实战笔记整理
查看>>
奇葩问题
查看>>
使用 Laravel 5.5+ 更好的来实现 404 响应
查看>>
PHP 网络编程小白系列 —— Accept 阻塞模型
查看>>
流畅的python读书笔记-第十六章-携(协)程
查看>>
Python学到什么程度才可以去找工作?掌握这4点足够了!
查看>>
用状态机写轮播
查看>>
【379天】每日项目总结系列116(2018.02.19)
查看>>
人工智能在搜索中的应用
查看>>
Vue2从0到1(一):用webpack打包vue
查看>>
【Vue样式绑定】
查看>>
leetcode75. Sort Colors
查看>>
React 可视化开发工具 Shadow Widget 非正经入门(之一:React 三宗罪)
查看>>
Spring Boot QuickStart (3) - Web & Restful
查看>>
实现一个spring webservice服务端四:服务端、客户端以及httpclient调用spring-ws服务...
查看>>
使用 nexus 2 搭建 maven 私服及常见配置
查看>>
发布 Android Library 到 JCenter 从入门到放弃
查看>>