前面几节,我们重点讨论了自定义View的三板斧,这节我们来讨论自定义ViewGroup,为什么要自定义ViewGroup,其实就是为了更好的管理View。

  自定义ViewGroup无非那么几步:

  Ⅰ、重写OnMeasure()方法,测试子控件的大小。

  Ⅱ、重写onLayout()方法,计算子控件的布局。

  Ⅲ、在onDraw()方法中,绘制子控件,可有可无。

  Ⅳ、监听onTouch事件,响应屏幕触摸事件。

  相应思维导图如下所示:

  连篇累牍的说了这么多,我们通过一个小案例来理解这个自定义ViewGroup把,看看如何实现ViewGroup。

    简单的黏性ScrollView

  简单概述

  这是一个原生scrollView效果非常类似的效果,他可以像scrollView一样上下滑动的效果,不过我们增加了一个黏性效果。何为黏性效果了?即当一个子View向上滑动大于一定距离的时候,它将自动向上滑动,显示下一个子View。同理,如果一个子View滑动距离小于某一个距离,它将滚回到原始的位置。

  实现思路

  投篮要找角度,控件要找思路。我们来分析要实现此自定义ViewGroup的基本思路了:

  Ⅰ、在OnMeasure()方法中,对每个子控件的大小进行测量了。

  Ⅱ、在OnLayout()方法中,对每个要显示控件的位置进行计算。

  Ⅲ、紧接着,就是在OnTouchEvent()方法,监听着手势触摸事件,判断它是上滑还是下滑,判断它的滑动距离是否大于我们设定的值,如果大于这个值,就将它移动到下一个子View,否则,滚回到原来的位置。

  有了这样的思路之后,我们只需要所做的是按部就班实现代码编写

  具体实现

  第一步、进行一些变量的初始化,代码如下:

    private void init(Context context) {
WindowManager manager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics displayMetrics = new DisplayMetrics();
manager.getDefaultDisplay().getMetrics(displayMetrics);
mScreenHeight = displayMetrics.heightPixels;
mScroller = new Scroller(context);
}

  获取屏幕高度作为每个控件的高度,将scroller控件进行初始化。

   第二步 、实现控件的测量,代码如下:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int count = getChildCount();
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
measureChild(child, widthMeasureSpec, heightMeasureSpec);
}
}

  我们看到每个子控件的大小与父控件的大小保持一致,这样才能形成滚动的效果。

  第三步、将子控件从上到下依次排列开来,代码如下所示:

@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
MarginLayoutParams layoutParams = (MarginLayoutParams) getLayoutParams();
layoutParams.height = mScreenHeight * count;
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
if (child.getVisibility() == View.VISIBLE) {
child.layout(l, i * mScreenHeight, r, (i + 1) * mScreenHeight);
} }
}

  我们可以清晰的看到,如果将其子控件进行从上到下依次排列,这个子控件占一频,这样,才能形成可以上下滚动的必要条件。

  第四步、监听手势事件,源代码如下:

@Override
public boolean onTouchEvent(MotionEvent event) {
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mLastY = y;
mStart = getScrollY();
break;
case MotionEvent.ACTION_MOVE:
if (!mScroller.isFinished()) {
mScroller.abortAnimation();
}
int dy = y - mLastY;
if (getScrollY()< 0) {
dy = 0;
} else if (getScrollY()> getHeight() - mScreenHeight) {
dy = 0;
}
scrollBy(0, dy);
mLastY = y;
break;
case MotionEvent.ACTION_UP:
mEnd = getScrollY();
int delta = mEnd - mStart;
if (delta > 0) {
if (delta < mScreenHeight / 3) {
mScroller.startScroll(0, getScrollY(), 0, -delta);
} else {
mScroller.startScroll(0, getScrollY(), 0, mScreenHeight
- delta);
}
} else {
if (Math.abs(delta) < mScreenHeight / 3) {
mScroller.startScroll(0, getScrollY(), 0, -delta);
} else {
mScroller.startScroll(0, getScrollY(), 0, -mScreenHeight
- delta);
}
}
break;
default:
break;
} return true;
}

  事后总结

  其实,在这个事件监听中就做了三件事件

  ①、根据手势按下、抬起的距离进行判断,判断手势到底是上滑还是下滑。

  ②、如果手势滑动的距离,小于小于相应的阈值(这里为屏幕高度的三分之一)以后,就滚回到原来的位置,否则自动滑入下一个子View。

  ③、在手指移动事件,使这个控件能够随着手势的滑动而自由的移动。但是,我们要做好相应临界值判断,判断其是否小于0或者大于屏幕高度,就不进行滑动。

  最终效果 

  这个控件最终运行的效果为:

  这就是,我对自定义viewGroup控件的一定总结。本人才疏学浅,恳请大家指教。

Android 自定义ViewGroup的更多相关文章

  1. android自定义viewgroup之我也玩瀑布流

    先看效果图吧, 继上一篇<android自定义viewgroup实现等分格子布局>中实现的布局效果,这里稍微有些区别,每个格子的高度不规则,就是传说的瀑布流布局,一般实现这种效果,要么用第 ...

  2. Android自定义ViewGroup

    视图分类就两类,View和ViewGroup.ViewGroup是View的子类,ViewGroup可以包含所有的View(包括ViewGroup),View只能自我描绘,不能包含其他View. 然而 ...

  3. Android自定义ViewGroup,实现自动换行

    学习<Android开发艺术探索>中自定义ViewGroup章节 自定义ViewGroup总结的知识点 一.自定义ViewGroup中,onMeasure理解 onMeasure(int ...

  4. android自定义viewgroup实现等分格子布局

    先上效果图: 实现这样的效果: 一般的思路就是,直接写布局文件,用LinearLayout 嵌套多层子LinearLayout,然后根据权重layout_weight可以达到上面的效果 还有就是利用g ...

  5. android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu

    示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这里我简单说明一下用自定义ViewGroup来实现. 实现方法:我们自定义一个ViewGroup实现左右滑动, ...

  6. android 自定义ViewGroup和对view进行切图动画实现滑动菜单SlidingMenu[转]

    http://blog.csdn.net/jj120522/article/details/8095852 示意图就不展示了,和上一节的一样,滑动菜单SlidingMenu效果如何大家都比较熟悉,在这 ...

  7. Android自定义ViewGroup(四、打造自己的布局容器)

    转载请标明出处: http://blog.csdn.net/xmxkf/article/details/51500304 本文出自:[openXu的博客] 目录: 简单实现水平排列效果 自定义Layo ...

  8. android自定义viewgroup初步之一----抽屉菜单

    转载请注明出处 http://blog.csdn.net/wingichoy/article/details/47832151 几天前在慕课网上看到鸿洋老师的 自定义卫星菜单,感觉很有意思,于是看完视 ...

  9. Android 自定义ViewGroup手把手教你实现ArcMenu

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/37567907 逛eoe发现这样的UI效果,感觉很不错,后来知道github上有这 ...

  10. Android -- 自定义ViewGroup实现FlowLayout效果

    1,在开发的时候,常在我们的需求中会有这种效果,添加一个商品的一些热门标签,效果图如下: 2,从上面效果可以看得出来,这是一个自定义的ViewGroup,然后实现换行效果,让我们一起来实现一下 自定义 ...

随机推荐

  1. 【随笔】Linux服务器备份相关

    服务器数据的安全性一直都是服务器日常管理的重中之重.Linux服务器虚拟化虽然以其高度可靠的作业系统而闻名,不过系统失效仍然可能发生.可能因为硬体故障,电源中断,或其他不可预料的问题.更常见的这 些问 ...

  2. WIN2003使用IP安全策略只允许指定IP远程桌面连接

    一,新建IP安全策略 WIN+R打开运行对话框,输入gpedit.msc进入组策略编辑器. 依次打开“本地计算机”策略--计算机配置--Windows设置--安全设置--IP安全策略,在 本地计算机上 ...

  3. spring+struts2的jar

  4. 【Mail】JavaMail介绍及发送邮件(一)

    JavaMail介绍 JavaMail是SUN提供给开发人员在应用程序中实现邮件发送和接收功能而提供的一套标准开发类库,支持常用的邮件协议,如SMTP.POP3.IMAP,开发人员使用JavaMail ...

  5. URAL1132_Square Root

    求解方程,x^2=n (mod P). 解二次同余方程的步骤: 1.首先判断勒让德符号(n,p)是否的等于1,即n^((p-1/2)=1 (mod p)是否成立.不成立显然无解.(略) 2.任取0-( ...

  6. javascript总结

    javascript:它是一种script脚本语言           脚本语言:就是可以和HTML混合在一起使用的语言,可以用来在IE的客                    户端进行程序编制,从 ...

  7. Guidelines for accessing OneDrive from an app

    Guidelines for accessing OneDrive from an app https://msdn.microsoft.com/en-us/library/windows/apps/ ...

  8. Angular常用功能

    1.默认选择让第0个元素的class为active ng-class="{active:$index == 0}" 2.指令的例子 <!DOCTYPE html> &l ...

  9. Windows下nginx+php配置

    1. 首先,将 nginx.conf 中的 PHP 配置注释去掉. # pass the PHP scripts to FastCGI server listening on # #location ...

  10. 堆排序Heap sort

    堆排序有点小复杂,分成三块 第一块,什么是堆,什么是最大堆 第二块,怎么将堆调整为最大堆,这部分是重点 第三块,堆排序介绍 第一块,什么是堆,什么是最大堆 什么是堆 这里的堆(二叉堆),指得不是堆栈的 ...