7.自定义ViewGroup-下滑抽屉
1.效果
2.思路
分析效果:
1.布局分为两部分,后面部分,前面部分,默认状态后面被挡住;
2.后面不可以滑动,前面可以滑动;
3.如果前面的布局本身是可以滑动的,那么当前面布局滑动到第一个时,后面的布局才显示出来
基于以上的效果,我们自定义ViewGroup 继承自FrameLayout,使用
ViewDragHelper
处理滑动事件;当前面的view 本身是可以滑动的,那么当其手指向下move的过程中需要判断前面的view是否在最顶部,从而决定是否拦截事件;
ViewDragHelper 的用法
//重点
private ViewDragHelper mDragHelper;
//初始化
mDragHelper = ViewDragHelper.create(this, mDragCallback);
ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
//只有mDragView 可以滑动
return mDragView == child;
}
@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
//控制垂直方向滑动的距离
if (top < 0) {
top = 0;
}
if (top > mMenuHeight) {
top = mMenuHeight;
}
return top;
}
//当手指松开的时候回调
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
int dy = mDragView.getTop();
if (dy > mMenuHeight / 2) {
//打开
mDragHelper.settleCapturedViewAt(0, mMenuHeight);
} else {
//关闭
mDragHelper.settleCapturedViewAt(0, 0);
}
invalidate();
}
};
@Override
public boolean onTouchEvent(MotionEvent event) {
//处理event事件
mDragHelper.processTouchEvent(event);
return true;
}
全部代码
class VerticalDragListView extends FrameLayout {
private static final String TAG = "VerticalDragListView";
private ViewDragHelper mDragHelper;
private View mMenuView;
private View mDragView;
private int mMenuHeight;
private boolean isOpen = false;
public VerticalDragListView(@NonNull Context context) {
this(context, null);
}
public VerticalDragListView(@NonNull Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public VerticalDragListView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mDragHelper = ViewDragHelper.create(this, mDragCallback);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView = getChildAt(0);
mDragView = getChildAt(1);
}
ViewDragHelper.Callback mDragCallback = new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(@NonNull View child, int pointerId) {
//只有mDragView 可以滑动
return mDragView == child;
}
@Override
public int clampViewPositionVertical(@NonNull View child, int top, int dy) {
//通过top 控制范围
if (top < 0) {
top = 0;
}
if (top > mMenuHeight) {
top = mMenuHeight;
}
return top;
}
@Override
public void onViewReleased(@NonNull View releasedChild, float xvel, float yvel) {
int dy = mDragView.getTop();
//当手指松开的时候
if (dy > mMenuHeight / 2) {
//打开
mDragHelper.settleCapturedViewAt(0, mMenuHeight);
isOpen = true;
} else {
//关闭
mDragHelper.settleCapturedViewAt(0, 0);
isOpen = false;
}
invalidate();
}
};
@Override
public void computeScroll() {
if (mDragHelper.continueSettling(true)) {
invalidate();
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
mMenuHeight = mMenuView.getMeasuredHeight();
}
float downY = 0;
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (isOpen) {
return true;
}
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mDragHelper.processTouchEvent(ev);
downY = ev.getY();
break;
case MotionEvent.ACTION_MOVE:
//子view滑动到顶部&&已经到顶了
if (ev.getY() - downY > 0 && !canChildScrollUp(mDragView)) {
return true;
}
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
mDragHelper.processTouchEvent(event);
return true;
}
/**
* 判断是否可以继续向上滑
*
* @param mTarget
* @return
*/
public boolean canChildScrollUp(View mTarget) {
if (android.os.Build.VERSION.SDK_INT < 14) {
if (mTarget instanceof AbsListView) {
final AbsListView absListView = (AbsListView) mTarget;
return absListView.getChildCount() > 0
&& (absListView.getFirstVisiblePosition() > 0 || absListView.getChildAt(0)
.getTop() < absListView.getPaddingTop());
} else {
return mTarget.canScrollVertically(-1) || mTarget.getScrollY() > 0;
}
} else {
return mTarget.canScrollVertically(-1);
}
}
}
3.目前存在的问题
当滑动的最顶端的时候,只有松开手,再按下滑,才可以滑的动
7.自定义ViewGroup-下滑抽屉的更多相关文章
- android自定义viewgroup初步之一----抽屉菜单
转载请注明出处 http://blog.csdn.net/wingichoy/article/details/47832151 几天前在慕课网上看到鸿洋老师的 自定义卫星菜单,感觉很有意思,于是看完视 ...
- Android 自定义ViewGroup
前面几节,我们重点讨论了自定义View的三板斧,这节我们来讨论自定义ViewGroup,为什么要自定义ViewGroup,其实就是为了更好的管理View. 自定义ViewGroup无非那么几步: Ⅰ. ...
- 简单的例子了解自定义ViewGroup(一)
在Android中,控件可以分为ViewGroup控件与View控件.自定义View控件,我之前的文章已经说过.这次我们主要说一下自定义ViewGroup控件.ViewGroup是作为父控件可以包含多 ...
- Android动画效果之自定义ViewGroup添加布局动画
前言: 前面几篇文章介绍了补间动画.逐帧动画.属性动画,大部分都是针对View来实现的动画,那么该如何为了一个ViewGroup添加动画呢?今天结合自定义ViewGroup来学习一下布局动画.本文将通 ...
- Android自定义控件之自定义ViewGroup实现标签云
前言: 前面几篇讲了自定义控件绘制原理Android自定义控件之基本原理(一),自定义属性Android自定义控件之自定义属性(二),自定义组合控件Android自定义控件之自定义组合控件(三),常言 ...
- Android自定义ViewGroup
视图分类就两类,View和ViewGroup.ViewGroup是View的子类,ViewGroup可以包含所有的View(包括ViewGroup),View只能自我描绘,不能包含其他View. 然而 ...
- [Android Pro] Android开发实践:自定义ViewGroup的onLayout()分析
reference to : http://www.linuxidc.com/Linux/2014-12/110165.htm 前一篇文章主要讲了自定义View为什么要重载onMeasure()方法( ...
- android 手把手教您自定义ViewGroup(一)
1.概述 在写代码之前,我必须得问几个问题: 1.ViewGroup的职责是啥? ViewGroup相当于一个放置View的容器,并且我们在写布局xml的时候,会告诉容器(凡是以layout为开头的属 ...
- 自定义ViewGroup须知
自定义ViewGroup须知: 1.必须复写onMeasure和onLayout方法,根据容器的特性进行布局设计 2.复写onMeasure方法必须处理父布局设置宽或高为wrap_content情况下 ...
随机推荐
- mfc 位图本地存储 本地位图读取显示
一.读取CImage //在绘图函数中直接使用参数pDC,无需定义 CDC* pDC = GetDC(): //读去位图路径,根据实际情况修改 CString loatImagePath = TEXT ...
- houdini 鱼眼相机
http://mattebb.com/weblog/houdini-fisheye-camera/ 这个网站是有提供一个相机shader的,,如图是方形的,国内的用户,比较多是做球幕的小伙伴,圆形就行 ...
- synchronized的底层原理?
最近更新的XX必备系列适合直接背答案,不深究,不喜勿喷. 你能说简单说一下synchronize吗? 可别真简单一句话就说完了呀~ 参考回答: synchronize是java中的关键字,可以用来修饰 ...
- android studio报butterknife错误
Error:Execution failed for task ':shipper:javaPreCompileDebug'.> Annotation processors must be ex ...
- Codeforces Educational Round 94 (Rated for Div. 2)
昨晚算是不幸中的万幸了 A题问的是给2n-1个01串,让你构造出来一个n串使得从1开始每个长度为n的串都至少存在有一个相似的地方 这道题我一开始没什么想法,但是手动观察发现每次可以留出来的空挡间隔为1 ...
- 第8.7节 Python类__new__方法和构造方法关系深入剖析:__new__方法执行结果对__init__的影响案例详解
一. 引言 前面章节介绍了类中的构造方法和__new__方法,并分析了二者执行的先后顺序关系.__new__方法在__init__方法前执行,__new__方法执行后才返回实例对象,也就是说__new ...
- PyQt(Python+Qt)学习随笔:QScrollArea滚动区域layout布局的作用及设置方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 滚动区域可以设置布局,布局的作用其实与其他布局一样,就是在滚动区域大小调整时,滚动区域内的子部件跟随 ...
- PyQt学习随笔:ListView控件获取当前选择项的方法
通过currentIndex()可以获取listView控件的当前选择元素,如果选择了多个,则可以通过selectedIndexes()来获取选择的元素,不过这两个函数返回的是元素数据,而不是索引编号 ...
- PyQt(Python+Qt)学习随笔:Qt Designer中怎么给toolBar添加按钮
在Designer中创建了一个MainWindow窗体,当想在其中的toolBar中添加toolButton时发现怎么也放不上去,最终才发现toolBar中的按钮只能通过直接拖拽Action编辑器中的 ...
- "迎圣诞,拿大奖"赛题——SQLI
0x01 本题所需知识清单: 1.php sprintf()函数漏洞:https://blog.csdn.net/WQ_BCJ/article/details/85057447 2.布尔盲注基本pla ...