转载请注明出处 http://blog.csdn.net/wingichoy/article/details/47832151

几天前在慕课网上看到鸿洋老师的 自定义卫星菜单,感觉很有意思,于是看完视频以后,自己也尝试写了一遍,并且添加了可拖拽效果(光看视频是不管用的,一定要自己动手做!切记不要照着抄代码)。

有兴趣的同学可以去慕课网看看(并非广告):http://www.imooc.com/learn/300

自定义控件这个玩意呢,就得考多练,于是又写了一个抽屉效果的菜单,也是比较简单的。

老规矩,先上效果图:

那么中间的圆圈就是卫星菜单拉,而左下角的呢,是抽屉菜单。

下面进入正题:

自定义Viewgroup的一般步骤:

写构造器,重写onMeasure(),重写onLayout();

由于本篇博客是viewgroup初步,故全部从最简单的开始。 我们来讲抽屉菜单。

首先创建DrawerMenu类,使他继承于ViewGroup

  1. public class DrawerMenu extends ViewGroup

然后添加三个构造器,使用一般的方法,少参数的调用多参数的:

  1. public DrawerMenu(Context context) {
  2. this(context, null);
  3. }
  4.  
  5. public DrawerMenu(Context context, AttributeSet attrs) {
  6. this(context, attrs, 0);
  7. }
  8.  
  9. public DrawerMenu(Context context, AttributeSet attrs, int defStyleAttr) {
  10. super(context, attrs, defStyleAttr);
  11. }

一般在第三个构造器里,我们会使用TypedArray来获得他对应attr.xml里面的属性,这里为了简单,不给这个viewgroup添加任何自定义属性,所以构造器这样就可以。

接下来是重写onMeasure()方法。所谓Measure为测量view的大小

  1. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  2.  
  3. int count = getChildCount();
  4. for (int i = 0; i < count; i++) {
  5. measureChild(getChildAt(i), widthMeasureSpec, heightMeasureSpec);
  6. }
  7. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  8. }

测量模式一共分三种,这里也不多介绍了。因为我们的子view都是wrap_content的,所以我们只要简单测量一下即可。

接下来是关键的地方,onLayout(), 此方法是为子view进行布局。告诉子view他应该在什么位置,首先,我们要布局主按钮,这里我们将它固定在左下角:

  1. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  2.  
  3. layoutBottom();
  4. }
  1. private void layoutBottom() {
  2. mButton_buttom = getChildAt(0);
  3. mButton_buttom.setOnClickListener(this);
  4. mWidth_button_buttom = mButton_buttom.getMeasuredWidth();
  5. mHeight_button_buttom = mButton_buttom.getMeasuredHeight();
  6. mButtonX = 0;
  7. mButtonY = getMeasuredHeight() - mHeight_button_buttom;
  8. mButton_buttom.layout(mButtonX, mButtonY, mWidth_button_buttom, getMeasuredHeight());
  9. }

主要的button 是第一个子view 。我们用getChildAt(index=0)来获得, 然后获取得到的测量好的宽和高.

最后将主按钮layout到合适的位置,如图:

layout里面四个参数为画出圆圈地方的x,y

所以 左上角一点的位置为: 0,height - cHeight  右下角的坐标为   cWidth,height

这样我们便确定了主button的位置。

那么接下来当然是去layout 子view的位置了。相信大家也明白了,子view的位置只要找出坐标就好。所以我们这里继续确定子view的位置。

  1. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  2. Log.i("wing", mIsChanged + "");
  3. if (mIsChanged) {
  4. layoutBottom();
  5. int count = getChildCount();
  6. for (int i = 0; i < count - 1; i++) {
  7. View child = getChildAt(i + 1);
  8. int childWidth = child.getMeasuredWidth();
  9. int childHeight = child.getMeasuredHeight();
  10. child.layout(0, mButtonY - mHeight_button_buttom * (i + 1) * 2, childWidth, getMeasuredHeight());
  11.  
  12. child.setVisibility(GONE);
  13.  
  14. }
  15. }
  16. }

然后我们为主按钮添加监听: 来切换菜单的状态,如果菜单为关闭,那么按下的时候显示按钮,如果为开启,那么将按钮都GONE。

这里为按钮添加了动画效果,如果你还不了解安卓动画,那么看看这里:http://blog.csdn.net/wingichoy/article/details/47104433

为了好看呢,我们给每个动画的duration加了 i*100的延迟来有渐变的效果

  1. public void onClick(View v) {
  2. toggleMenu();
  3.  
  4. }
  1. private void toggleMenu() {
  2.  
  3. if (mIsChanged) {
  4. int count = getChildCount();
  5. for (int i = 0; i < count - 1; i++) {
  6. View child = getChildAt(i + 1);
  7. TranslateAnimation ta = new TranslateAnimation(-child.getMeasuredWidth(), 0, 0, 0);
  8. ta.setDuration(1000 + i * 100);
  9. child.startAnimation(ta);
  10. child.setVisibility(VISIBLE);
  11. mIsChanged = false;
  12. }
  13. } else {
  14.  
  15. int count = getChildCount();
  16. for (int i = 0; i < count - 1; i++) {
  17. View child = getChildAt(i + 1);
  18. TranslateAnimation ta = new TranslateAnimation(0, -child.getMeasuredWidth(), 0, 0);
  19. ta.setDuration(1000 + i * 100);
  20. child.startAnimation(ta);
  21. child.setVisibility(GONE);
  22.  
  23. mIsChanged = true;
  24. }
  25. }

这下我们的viewgroup基本大功告成了。添加到mainactivity的xml上来试试

  1. <com.wingsoft.arcmenu.DrawerMenu
  2. android:layout_width="match_parent"
  3. android:layout_height="match_parent">
  4. <ImageView
  5. android:layout_width="wrap_content"
  6. android:layout_height="wrap_content"
  7. android:src="@drawable/drawer"/>
  8.  
  9. <ImageView
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:src="@drawable/drawer"/>
  13.  
  14. <ImageView
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:src="@drawable/drawer"/>
  18.  
  19. <ImageView
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:src="@drawable/drawer"/>
  23. <ImageView
  24. android:layout_width="wrap_content"
  25. android:layout_height="wrap_content"
  26. android:src="@drawable/drawer"/>
  27. </com.wingsoft.arcmenu.DrawerMenu>

嗯。不错。  样子也实现了。 那么接下来大家动动脑筋,自己写个监听器吧~ 今天就到这里。

如果肯努力,技术很快就赶上来了~~

android自定义viewgroup初步之一----抽屉菜单的更多相关文章

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

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

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

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

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

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

  4. Android 自定义ViewGroup,实现侧方位滑动菜单

    侧方位滑动菜单 1.现在adnroid流行的应用当中很多都是用的侧方位滑动菜单如图:

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

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

  6. Android自定义顶部栏及侧滑菜单和fragment+viewpag滑动切换的实现

    嘿嘿嘿,关于android滑动的操作,是不是经常都会用到呢. 我肯定也要学习一下啦. https://blog.csdn.net/u013184970/article/details/82882107 ...

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

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

  8. Android自定义ViewGroup

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

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

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

随机推荐

  1. SpringMVC+BUI实现文件上传(附详解,源码下载)

    中午有限时间写这博文,前言就不必多说了,直奔主题吧. BUI是一个前端框架,关于BUI的介绍请看博主的文章那些年用过的一些前端框架. 下面我们开始实例的讲解! 一.效果演示: 上传成功后,会发现本地相 ...

  2. Hibernate之实体关系映射

    延迟加载与即时加载 例如Person类和Email类是一对多关系,如果设为即时加载,当加载Person时,会自动加载Email,如果设置为延迟加载,当第一次调用person.getEmails()时才 ...

  3. Android中Snackbar的介绍以及使用

    Android中Snackbar的介绍以及使用 介绍 Snackbar可以说是Toast的升级版,不仅有显示信息的功能,还可以添加一个Action,实现点击功能,可以右滑删除. 效果图 Snackba ...

  4. 为什么选择C++

    为什么选择C++,怎么不选其它语言呢? 为什么不选择C? 因为C++比C简单点~ 为什么不选择C#? 因为C++可以在所有操作系统上使用. 为什么不选择JAVA? 因为C++的性能好一点~ 还有其他的 ...

  5. Swift中不用桥接文件和.h头文件直接和C代码交互的方法

    我们知道一般情况下Swit要想调用obj-c,c或c++代码必须通过obj-c以及桥接文件才可以办到,但是对于某些简单的代码,我们可以跳过桥接文件和.h头文件,直接和C代码交互呢! 我们再Projec ...

  6. SpriteKit中的共享动作(Sharing Actions)

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 在SpriteKit中某些动作需要一些额外的延时,如果每次都重 ...

  7. [Django]bulk_create 探究

    使用django orm大批量插入的时候我们可以不使用for循环对一个一个的save而是使用 bulk_create来批量插入,可是使用了这个方法还需要在自己添加一个事务吗? 还是django本身对这 ...

  8. SQLite 运算符(http://www.w3cschool.cc/sqlite/sqlite-operators.html)

    SQLite 运算符 SQLite 运算符是什么? 运算符是一个保留字或字符,主要用于 SQLite 语句的 WHERE 子句中执行操作,如比较和算术运算. 运算符用于指定 SQLite 语句中的条件 ...

  9. JAVA面向对象-----main方法详解

    JVM看不懂的可以跳过,这里不做过多解释,(^__^) 嘻嘻-- 主函数是静态的 public static void main(String[] args){ } 主函数是什么:主函数是一个特殊的函 ...

  10. iOS中 CocoaPods Mac App的安装和使用 韩俊强的博客

    CocoaPods Mac App的安装和使用 CocoaPods桌面应用版下载地址:https://cocoapods.org/app打开应用会提示你是否安装命令行工具,选择install就也可以在 ...