尊重原创http://blog.csdn.net/yuanzeyao/article/details/40264433

好久都没有写文章了,如今利用周末的时间对一些知识进行总结。便于加深理解,今天我就来学习一下怎样实现自己定义ViewGroup

在Android中比較经常使用的布局LinearLayout,FrameLayout,RelativeLayout。

。。这些布局都是继承自ViewGroup,通过这些布局。我们差点儿能够实现Android中全部的界面开发,可是对于一些比較常见而且比較复杂的布局,使用这些基本布局开发的话,就会花大量的时间在一些反复的工作上。那么我们能不能模仿这些基本布局。依据自己的需求来实现一些自己的布局,以后须要的时候直接拿来用呢?当然是能够的。

相似扑克牌的布局

在斗地主的游戏中,我们会经常遇到相似这种布局。我就将这个布局叫级联布局吧,这个布局使用RelativeLayout和margin等熟悉是能够做出来的,可是不是非常方便,我们今天就这种需求为背景解说一下自己定义ViewGroup

在学习自己定义布局前,读者最好先了解一下Android的布局好似怎么绘画出来的,我推荐大家去了解一下:都是官网的一些文章
1、http://developer.android.com/guide/topics/ui/how-android-draws.html
2、http://developer.android.com/reference/android/view/ViewGroup.html
3、http://developer.android.com/reference/android/view/ViewGroup.LayoutParams.html

通过以上几篇文章,我们须要了解一下知识:
1、绘制布局是由两个过程组成:測量过程和布局过程。測量过程使用measure(int,int)方法完毕,遍历完毕后,全部的View的大小都确定了,布局过程使用layout方法完毕,就是通过View的大小。决定View放置在上面地方,只是通过源代码中measure和layout方法都是final类型的。所以我们是无法改写的,之所以定义成final的。就是避免开发人员破坏了布局的绘画流程,只是測量和布局的细节我们能够通过改写onMeasure和onLayout实现。

2、ViewGroup
在前面我就说过,Android中全部的布局都是继承自ViewGroup,ViewGroup就是一个View的容器,我们能够再里面放置任务的View,至于怎样放置,我们能够通过onMeasure和onLayout来定义,onMeasure在measure调用,onLayout是在layout中调用的

3、ViewGroup.LayoutParams

这个类主要是View用来告诉他的父容器它想怎么显示,如宽、高、居中等等。ViewGroup.LayoutParams里面最重要的两个參数就是width,height。假设你想使用margin属性。那么必须使用ViewGroup.MarginLayoutParams这个类,这个类继承自ViewGroup.LayoutParams。

增加了对margin属性的支持,假设你想增加很多其它的属性,能够自己定义一个LayoutParams类增加你须要的属性。其实LinearLayout等布局都是继承自ViewGroup.MarginLayoutParams,并增加了自己须要的属性。

实现自己的布局CascadeLayout.java

/**
* 自己定义布局,用来实现扑克牌效果
* com.myviewgroup.CascadeLayout
* @author yuanzeyao <br/>
* create at 2014年10月19日 下午4:15:42
*/
public class CascadeLayout extends ViewGroup
{
/**
* 水平偏移距离
*/
private int horizontal_space; /**
* 垂直偏移距离
*/
private int vertical_space; public CascadeLayout(Context context)
{
super(context);
} public CascadeLayout(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
initAttribute(context, attrs);
} public CascadeLayout(Context context, AttributeSet attrs)
{
super(context, attrs);
initAttribute(context, attrs);
} /**
* 依据xml文件里的属性对horizontal_space。vertical_space来赋值
* @param context
* @param attrs
*/
private void initAttribute(Context context,AttributeSet attrs)
{
TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.CascadeLayout);
horizontal_space=a.getDimensionPixelSize(R.styleable.CascadeLayout_horizontal_space,this.getResources().getDimensionPixelSize(R.dimen.cascade_horizontal_spacing));
vertical_space=a.getDimensionPixelSize(R.styleable.CascadeLayout_vertical_space, this.getResources().getDimensionPixelSize(R.dimen.cascade_vertical_spacing));
a.recycle();
} /**
* onMeasure在measure中调用,參数各自是CascadeLayout的宽度和高度
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//使用measureChildren对全部的孩子进行測量,你也能够使用for循环,然后掉哦弄个measurechild函数进行測量
measureChildren(widthMeasureSpec, heightMeasureSpec);
//将宽度和高度赋值为CascadeLayout的measureWidth。measureHeight变量
setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
} /**
* 在该函数中增加怎样布置各个View的逻辑
*/
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
for(int i=0;i<getChildCount();i++)
{
//依次遍历孩子节点
View child=getChildAt(i); // MarginLayoutParams mlp=(MarginLayoutParams) child.getLayoutParams();
LayoutParams lp=child.getLayoutParams();
//计算左边和顶部的距离
int left=horizontal_space*i;
int top=vertical_space*i; child.layout(left,top,left+child.getMeasuredWidth(),top+child.getMeasuredHeight());
}
} /**
* 改写生成LayoutParams的方法
*/
@Override
protected LayoutParams generateLayoutParams(LayoutParams p)
{
//return super.generateLayoutParams(p);
//return new ViewGroup.MarginLayoutParams(p.width,p.height);
return new ViewGroup.LayoutParams(p.width,p.height);
} @Override
public LayoutParams generateLayoutParams(AttributeSet attrs)
{
//return super.generateLayoutParams(attrs);
//return new ViewGroup.MarginLayoutParams(this.getContext(), attrs);
return new ViewGroup.LayoutParams(this.getContext(), attrs);
} }

在CascadeLayout中,我们定义了两个属性,horizontal_space,vertical_space。这两个属性用来记录该布局中每一个子View之前的垂直距离和水平距离。他们都是在构造函数中初始化。因为我们增加了属性。所以在res/values中定义attrs.xml文件

<?

xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CascadeLayout">
<attr name="horizontal_space" format="dimension"></attr>
<attr name="vertical_space" format="dimension"></attr>
</declare-styleable>
</resources>

在layout文件里使用CascadeLayout

<com.myviewgroup.CascadeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cascade ="http://schemas.android.com/apk/res/com.myviewgroup"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
cascade:horizontal_space="40dip"
cascade:vertical_space="40dip" > <View
android:layout_width="200dip"
android:layout_height="200dip"
android:background="@color/view1"
/> <View
android:layout_width="200dip"
android:layout_height="200dip"
android:background="@color/view2"
/> <View
android:layout_width="200dip"
android:layout_height="200dip"
android:background="@color/view3"
/>
</com.myviewgroup.CascadeLayout>

执行效果例如以下

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQveXVhbnpleWFv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

自己定义自己的LayoutParams

在CascadeLayout中,我们使用的是ViewGroup.LayoutParams类。可是这个类唯独width和height属性,假设我们想增加其它属性。那么我们须要自己定义LayoutParams类
以下我们自己定义自己的LayoutParams类,这个类继承ViewGroup.MarginLayoutParams,所以我自己定义的LayoutPrams具有margin的属性

在CascadeLayout中定义例如以下LayoutParams类

public static class LayoutParams extends ViewGroup.MarginLayoutParams
{
/**
* 定义在垂直方向的偏移距离,能够覆盖CascadeLayout中的vertical_space属性
*/
private int layout_vertical_spacing; public LayoutParams(Context c, AttributeSet attrs)
{
super(c, attrs);
TypedArray a = c.obtainStyledAttributes(attrs,
R.styleable.CascadeLayout_LayoutParams);
try {
layout_vertical_spacing = a
.getDimensionPixelSize(
R.styleable.CascadeLayout_LayoutParams_layout_vertical_spacing,
-1);
} finally {
a.recycle();
}
} public LayoutParams(int width, int height)
{
super(width, height);
}
}

该LayoutParams就支持了layout_vertical_spaceing属性了。
好了,先写到这里吧,有什么不懂的欢迎大家留言。

。。

版权声明:本文博客原创文章,博客,未经同意,不得转载。

定义你自己ViewGroup的更多相关文章

  1. 如何定义自己的ViewGroup

    在发展中,有时会遇到一些要求.布局和控制系统不仅提供使用,以满足我们的发展,所以这一次就行,通常是你自己的自定义布局(ViewGroup)并控制(View)该.我在这里,我们将用一个简单的例子,当他们 ...

  2. Android自己定义组件系列【1】——自己定义View及ViewGroup

    View类是ViewGroup的父类,ViewGroup具有View的全部特性.ViewGroup主要用来充当View的容器.将当中的View作为自己孩子,并对其进行管理.当然孩子也能够是ViewGr ...

  3. Android自己定义组件系列【2】——Scroller类

    在上一篇中介绍了View类的scrollTo和scrollBy两个方法,对这两个方法不太了解的朋友能够先看<自己定义View及ViewGroup> scrollTo和scrollBy尽管实 ...

  4. 转战WebApp: 最适合Android开发者的WebApp框架

    随着移动端设备越来越多, 微信应用号即将发布, 越来越多的页面需要被移动浏览器承载, HTML5开发大热, 我们需要掌握Web开发的技能来适应时代变化. 合适的WebApp框架 AndroidUI4W ...

  5. Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程

    上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑.on ...

  6. Android Touch系统简介(二):实例详解onInterceptTouchEvent与onTouchEvent的调用过程

    上一篇文章主要讲述了Android的TouchEvent的分发过程,其中有两个重要的函数:onInterceptTouchEvent和onTouchEvent,这两个函数可被重装以完成特定的逻辑.on ...

  7. View事件传递之父View和子View之间的那点事

    Android事件传递流程在网上可以找到很多资料,FrameWork层输入事件和消费事件,可以参考: Touch事件派发过程详解 这篇blog阐述了底层是如何处理屏幕输,并往上传递的.Touch事件传 ...

  8. 手势滑动结束 Activity(一)基本功能的实现

    喜欢听音乐的朋友可能都看过天天动听这款 app, 这款 app 有一个亮点就是在切换页面(Fragment)的时候能够通过手势滑动来结束当前页面.这里先说一下,我为什么会这么关心这个功能呢,由于前两天 ...

  9. Android应用Activity、Dialog、PopWindow、Toast窗体加入机制及源代码分析

    [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处.尊重劳动成果] 1 背景 之所以写这一篇博客的原因是由于之前有写过一篇<Android应用setCont ...

随机推荐

  1. zigbee学习:示例程序SampleApp中按键工作流程

    zigbee学习:示例程序SampleApp中按键工作流程 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:IAR8. ...

  2. c语言移位操作

    应该先看看C语言是指所有的位二进制算术位计算.即使输入的是十进制的数,在存储器存储为二进制形式. “<<”使用方法: 的格式是:a<<m,a和m式,要求m>=0. 功能: ...

  3. Android应用开发-小巫CSDN博客client之显示博文具体内容

    Android应用开发-小巫CSDN博客客户端之显示博文具体内容 上篇博文给大家介绍的是怎样嵌入有米广告而且获取收益,本篇博客打算讲讲关于怎样在一个ListView里显示博文的具体信息.这个可能是童鞋 ...

  4. 2014华为机试西安地区B组试题

    2014华为机试西安地区B组试题 题目一.亮着点灯的盏数 一条长廊里依次装有n(1≤n≤65535)盏电灯,从头到尾编号1.2.3.-n-1.n.每盏电灯由一个拉线开关控制.開始,电灯所有关着. 有n ...

  5. Qt中截图功能的实现

    提要 需求:载入一张图片并显示,能够放大缩小,能够截取图片的某个矩形并保存. 原以为蛮简单的一个功能,事实上还是有点小复杂. 最简单Qt图片浏览器能够參考Qt自带的Demo:Image Viewer ...

  6. 谈论高并发(二十二)解决java.util.concurrent各种组件(四) 深入了解AQS(二)

    上一页介绍AQS其基本设计思路以及两个内部类Node和ConditionObject实现 聊聊高并发(二十一)解析java.util.concurrent各个组件(三) 深入理解AQS(一) 这篇说一 ...

  7. 白学jquery Mobile《构建跨平台APP:jQuery Mobile移动应用实战》串行4(场景变化)

    作为一个真正的利用价格值应用,首先,你应该至少有两页,通过切换页面来实现很多其他互动.比如手机人人网,首先,打开后进入登录页面,将有登录后,新的东西.然后拉左侧面板.你可以看到相册.私人信息.像其他应 ...

  8. ant利用先进,ant订单具体解释,ant包,ant包装删除编译jar文件

    在日常的项目开发,经常需要我们可以打包测试.特别是,开发环境是windows.实际情况是linux. 这样的话.一个非常大的程序猿将包,其中将包,这些软件包可能非常大,这里是真正的代码会改变的一部分, ...

  9. HTML——博客页面布局

    HTML文件 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/htm ...

  10. ViewData ViewBag ViewModel

    ViewBag 里可以携带dynamic的数据. Model 是从control传过来的模型数据. 我自己感觉ViewBag 可以携带少量的数据,但是我同事喜欢部分页partial 请求,ViewBa ...