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情况下 ...
随机推荐
- 蓝桥杯——快速排序(2018JavaB组第5题9分)
快速排序(18JavaB5,9') 以下代码可以从数组a[]中找出第k小的元素. 它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的. 请仔细阅读分析源码,填写划线部分缺失的内容. impo ...
- [自学] MIT的EECS本科+研究生课程【持续更新中-2020.06.02】
前言 我的本科是读的电子信息工程,研究生跟着老师做项目,参与到深度学习中来,毕业后做了算法工程师,工作之后愈发发现,不论从事什么岗位,基础都很重要,但现在也没有时间再读一遍本科了,自学的话也不知道从何 ...
- 训练yolo之前,anchor聚类问题
前期做数据可视化,发现标签数据存在一些孤立点(噪声点),影响kmeans聚类. 处理方法如下: 使用kmeans迭代10次得到聚类中心 计算所有数据到其聚类中心的欧式距离均值和方差 通过拟合正态分布, ...
- python之汉诺塔
# -*- coding: utf-8 -*- def move(n, a, b, c): if n==1: print(a,'==>',c)#只有一块的时候直接从A到C即可 else: mov ...
- 给你一个亿的keys,Redis如何统计?
前言 不知你大规模的用过Redis吗?还是仅仅作为缓存的工具了?在Redis中使用最多的就是集合了,举个例子,如下场景: 签到系统中,一天对应一系列的用户签到记录. 电商系统中,一个商品对应一系列的评 ...
- 2017 Mid Central Regional F.Orderly Class(大水题)
这两天刷了两道过去的原题,看看思维还是8太行. 这道题问给出两个字符串,要求只翻转一次,问有几种不同的方法使得a串变成b串 我一开始没看到只翻转一次,还以为是个计数 + 字符串dp大难题,心想当年的学 ...
- 将Shiny APP搭建为独立的桌面可执行程序 - Deploying R shiny app as a standalone application
目录 起源! 目的? 怎么做? 0 准备工作 1 下载安装R-portable 2 配置 Rstudio 3 搭建Shiny App 3.1 添加模块 3.2 写AppUI和AppServer 3.3 ...
- 国产开源数据库:腾讯云TBase在分布式HTAP领域的探索与实践
导语 | TBase 是腾讯TEG数据平台团队在开源 PostgreSQL 的基础上研发的企业级分布式 HTAP 数据库系统,可在同一数据库集群中同时为客户提供强一致高并发的分布式在线事务能力以及高 ...
- moviepy音视频剪辑:mask clip遮罩剪辑、遮片、蒙版的作用以及其包含的构成内容
☞ ░ 前往老猿Python博文目录 ░ 在阅读moviepy的类ImageClip的构造方法代码时,对于其中涉及遮罩的处理没有理解,到处查找遮罩的资料没有查到,最后到moviepy的官网上尝试了一下 ...
- PyQt(Python+Qt)学习随笔:QTreeWidget中获取可见项视口位置矩形的visualItemRect方法
老猿Python博文目录 专栏:使用PyQt开发图形界面Python应用 老猿Python博客地址 树型部件的visualItemRect方法可以返回参数指定项在视口的位置矩形. QRect visu ...