1、前言
最近开发遇到一个问题,想实现一个日历的控件,可以实现上下拖动展开关闭,可以点击展开关闭,
我找了一些控件也使用了系统的slidingview,但是感觉效果都不怎么好,我在使用slidingview
时候会发生被拖动的view会把下面的页面遮住,是没拖出来的时候已经遮住了,后来在github上
找到一个自己撸的slidingview和slidingview的功能相似。
2、使用
根据业务逻辑要求,或者说我考虑的更全,我有两点修改
2.1、修改打开关闭的回调的位置
我在把判断打开关闭放在了ViewDragHelper.Callback的回调里面了,这样判断的话能够更好
的完成的页面(我的应用场景是:当我打开页面的时候,底部的tab栏会隐藏,如果按之前的逻辑
的话tab栏隐藏会造成页面的卡在上边下边会形成空白,我改到完全走完这个动作,然后就不会有
空白)
2.2 添加回弹回调
既然有打开和关闭的回调,为啥不能有回弹的回调呢,在回弹里可以加一些逻辑(我有这个业务需
求)。
3、学习
既然使用了,那么就要搞懂它的用法,不能只用了,就没事儿了。我感觉这个的主要点有两块,一块
儿是怎么计算这些宽高,另一块儿是ViewDragHelper.Callback的用法,主要也是在这里。现在对
这一块进行学习记录。
首先一点就是ViewDragHelper是一个用作自定义view时候很重要的类,因为在使用自定
义的时候会设计到很多的收拾问题,还有很多手势是否拦截的问题,这些问题算起来肯定麻烦,所以系统提供了ViewDragHelper。按google的API中提到的说法:用于允许用户拖放位置的有用操作和状态跟踪视图组中的视图。
public static abstract class Callback {
/**
* Called when the drag state changes. See the <code>STATE_*</code> constants
* for more information.
*
* @param state The new drag state
*
* @see #STATE_IDLE
* @see #STATE_DRAGGING
* @see #STATE_SETTLING
*/
public void onViewDragStateChanged(int state) {}
/**
* Called when the captured view's position changes as the result of a drag or settle.
*
* @param changedView View whose position changed
* @param left New X coordinate of the left edge of the view
* @param top New Y coordinate of the top edge of the view
* @param dx Change in X position from the last call
* @param dy Change in Y position from the last call
*/
public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {}
/**
* Called when a child view is captured for dragging or settling. The ID of the pointer
* currently dragging the captured view is supplied. If activePointerId is
* identified as {@link #INVALID_POINTER} the capture is programmatic instead of
* pointer-initiated.
*
* @param capturedChild Child view that was captured
* @param activePointerId Pointer id tracking the child capture
*/
public void onViewCaptured(View capturedChild, int activePointerId) {}
/**
* Called when the child view is no longer being actively dragged.
* The fling velocity is also supplied, if relevant. The velocity values may
* be clamped to system minimums or maximums.
*
* <p>Calling code may decide to fling or otherwise release the view to let it
* settle into place. It should do so using {@link #settleCapturedViewAt(int, int)}
* or {@link #flingCapturedView(int, int, int, int)}. If the Callback invokes
* one of these methods, the ViewDragHelper will enter {@link #STATE_SETTLING}
* and the view capture will not fully end until it comes to a complete stop.
* If neither of these methods is invoked before <code>onViewReleased</code> returns,
* the view will stop in place and the ViewDragHelper will return to
* {@link #STATE_IDLE}.</p>
*
* @param releasedChild The captured child view now being released
* @param xvel X velocity of the pointer as it left the screen in pixels per second.
* @param yvel Y velocity of the pointer as it left the screen in pixels per second.
*/
public void onViewReleased(View releasedChild, float xvel, float yvel) {}
/**
* Called when one of the subscribed edges in the parent view has been touched
* by the user while no child view is currently captured.
*
* @param edgeFlags A combination of edge flags describing the edge(s) currently touched
* @param pointerId ID of the pointer touching the described edge(s)
* @see #EDGE_LEFT
* @see #EDGE_TOP
* @see #EDGE_RIGHT
* @see #EDGE_BOTTOM
*/
public void onEdgeTouched(int edgeFlags, int pointerId) {}
/**
* Called when the given edge may become locked. This can happen if an edge drag
* was preliminarily rejected before beginning, but after {@link #onEdgeTouched(int, int)}
* was called. This method should return true to lock this edge or false to leave it
* unlocked. The default behavior is to leave edges unlocked.
*
* @param edgeFlags A combination of edge flags describing the edge(s) locked
* @return true to lock the edge, false to leave it unlocked
*/
public boolean onEdgeLock(int edgeFlags) {
return false;
}
/**
* Called when the user has started a deliberate drag away from one
* of the subscribed edges in the parent view while no child view is currently captured.
*
* @param edgeFlags A combination of edge flags describing the edge(s) dragged
* @param pointerId ID of the pointer touching the described edge(s)
* @see #EDGE_LEFT
* @see #EDGE_TOP
* @see #EDGE_RIGHT
* @see #EDGE_BOTTOM
*/
public void onEdgeDragStarted(int edgeFlags, int pointerId) {}
/**
* Called to determine the Z-order of child views.
*
* @param index the ordered position to query for
* @return index of the view that should be ordered at position <code>index</code>
*/
public int getOrderedChildIndex(int index) {
return index;
}
/**
* Return the magnitude of a draggable child view's horizontal range of motion in pixels.
* This method should return 0 for views that cannot move horizontally.
*
* @param child Child view to check
* @return range of horizontal motion in pixels
*/
public int getViewHorizontalDragRange(View child) {
return 0;
}
/**
* Return the magnitude of a draggable child view's vertical range of motion in pixels.
* This method should return 0 for views that cannot move vertically.
*
* @param child Child view to check
* @return range of vertical motion in pixels
*/
public int getViewVerticalDragRange(View child) {
return 0;
}
/**
* Called when the user's input indicates that they want to capture the given child view
* with the pointer indicated by pointerId. The callback should return true if the user
* is permitted to drag the given view with the indicated pointer.
*
* <p>ViewDragHelper may call this method multiple times for the same view even if
* the view is already captured; this indicates that a new pointer is trying to take
* control of the view.</p>
*
* <p>If this method returns true, a call to {@link #onViewCaptured(android.view.View, int)}
* will follow if the capture is successful.</p>
*
* @param child Child the user is attempting to capture
* @param pointerId ID of the pointer attempting the capture
* @return true if capture should be allowed, false otherwise
*/
public abstract boolean tryCaptureView(View child, int pointerId);
/**
* Restrict the motion of the dragged child view along the horizontal axis.
* The default implementation does not allow horizontal motion; the extending
* class must override this method and provide the desired clamping.
*
*
* @param child Child view being dragged
* @param left Attempted motion along the X axis
* @param dx Proposed change in position for left
* @return The new clamped position for left
*/
public int clampViewPositionHorizontal(View child, int left, int dx) {
return 0;
}
/**
* Restrict the motion of the dragged child view along the vertical axis.
* The default implementation does not allow vertical motion; the extending
* class must override this method and provide the desired clamping.
*
*
* @param child Child view being dragged
* @param top Attempted motion along the Y axis
* @param dy Proposed change in position for top
* @return The new clamped position for top
*/
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
}
onViewDragStateChanged(int state) 这个方法是用来返回拖动状态的,共有三种状态 STATE_IDLE、STATE_DRAGGING、STATE_SETTLING(拖动停止0、手指拖动中1、自动滚动2)。
onViewPositionChanged(View changedView, int left, int top, int dx, int dy)这个方法是对于changdeView
的位置发生变化的回调。
onViewCaptured(View capturedChild, int activePointerId)文档中写view被捕捉到拖拽或定居时被调用。
onViewReleased(View releasedChild, float xvel, float yvel) 当手指释放,不在拖动时的回调,xvel和yvel是拖动的速度。
onEdgeTouched(int edgeFlags, int pointerId)触摸到边界时的回调,edgeFlags有左、上、右、下四个方向。
boolean onEdgeLock(int edgeFlags) 当给定的边界被锁定的时候,true为被锁定,false被解锁。
onEdgeDragStarted(int edgeFlags, int pointerId)当边界被拖动时候的回调。
int getOrderedChildIndex(int index)z方向上子view的调用顺序。index为z方向的位置,返回值为该位置的view。
int getViewHorizontalDragRange(View child) 返回值为0则横向不可拖动点击。
int getViewVerticalDragRange(View child) 返回值为0则竖直方向不可拖动点击。
boolean tryCaptureView(View child, int pointerId)child为可拖动view,如果返回true则可拖动,返回false不可拖动。
int clampViewPositionHorizontal(View child, int left, int dx) 水平位置的拖动范围限制,返回值为限制的值。
int clampViewPositionVertical(View child, int top, int dy) 竖直位置的拖动范围限制,返回值为限制的值。
基本方法理解了,下一步就是进行demo了。