自定义ViewGroup及其属性
来源:互联网 发布:me544j支持什么网络 编辑:程序博客网 时间:2024/05/29 08:06
闲来无事自定义个viewGroup的控件来练练手。
比如说现在有这么个需求,一左一右分别有个textView,然后外面一个控件直接包裹这两个;
1:现在给这个自定义控件(本文中名叫RcLinearLayout)自定义一个属性,然后去通过这个属性去确定这两个textView是否需要处于同一水平线上。
①先建立values文件夹下的attrs.xml文件,如:
<?xml version="1.0" encoding="utf-8"?><resources> <declare-styleable name="c_view"> <attr name="gravity"> <enum name="CENTER_VERTICAL" value="0"/> </attr> </declare-styleable></resources>当然了,你还可以增加别的属性,然后根据你设的属性去确定child的位置
2.重要的地方来了,就是自定义控件了,主要是重写onMeasure方法和onLayout方法,onMeasure方法主要是测量出容器的宽与高,而onlayout方法则是确定child的位置,代码如下:
public class RcLinearLayout extends ViewGroup{ private int mGravity;//这个用来标记布局中是否设置了垂直居中的属性 public RcLinearLayout(Context context) { this(context,null); } public RcLinearLayout(Context context, AttributeSet attrs) { this(context,attrs,0); } public RcLinearLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.c_view); mGravity = ta.getInt(R.styleable.c_view_gravity,-1); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //获得此控件的宽和高,以及计算模式 int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); //计算所有child的高和宽 measureChildren(widthMeasureSpec,heightMeasureSpec); //记录如果是wrap_content是设置的宽和高 int width = 0; int height = 0; int cCount = getChildCount(); int cWidth = 0; int cHeight = 0; MarginLayoutParams cParams = null; // 用于计算左边的childView的高度 int lHeight = 0; // 用于计算右边的childView的高度,最终高度取二者之间大值 int rHeight = 0; // 用于计算两个childView的宽度 int tWidth = 0; /** * 根据childView计算的出的宽和高,以及设置的margin计算容器的宽和高,主要用于容器是warp_content时 */ for (int i = 0; i < cCount; i++) { View childView = getChildAt(i); cWidth = childView.getMeasuredWidth(); cHeight = childView.getMeasuredHeight(); cParams = (MarginLayoutParams) childView.getLayoutParams(); // 得出两个childView的宽 tWidth += cWidth + cParams.leftMargin + cParams.rightMargin; if(i==0) { lHeight += cHeight + cParams.topMargin + cParams.bottomMargin; }else { rHeight +=cHeight + cParams.topMargin +cParams.bottomMargin; } } //高取两个childView的取大值 height = Math.max(lHeight,rHeight); width = tWidth; /** * 如果是wrap_content设置为我们计算的值 * 否则:直接设置为父容器计算的值 */ setMeasuredDimension((widthMode == MeasureSpec.EXACTLY) ? sizeWidth : width, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight : height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int cCount = getChildCount(); int cWidth = 0; int cHeight = 0; MarginLayoutParams cParams = null;//这个用来获取child的参数 //遍历所有childView根据其宽和高,以及margin进行布局 for (int i = 0; i < cCount; i++){ View childView = getChildAt(i); cWidth = childView.getMeasuredWidth(); cHeight = childView.getMeasuredHeight(); cParams = (MarginLayoutParams) childView.getLayoutParams(); int cl = 0, ct = 0, cr = 0, cb = 0; if(mGravity==-1) { switch (i) { case 0://第一个childview cl = cParams.leftMargin + getPaddingLeft(); ct = cParams.topMargin + getPaddingTop(); break; case 1://第二个childview cl = getWidth() - cWidth - cParams.leftMargin - cParams.rightMargin - getPaddingRight(); ct = cParams.topMargin + getPaddingTop(); break; } }else switch (i){ case 0: cl = cParams.leftMargin + getPaddingLeft(); ct = getHeight()/2-cHeight/2; break; case 1: cl = getWidth() - cWidth - cParams.leftMargin - cParams.rightMargin - getPaddingRight(); ct = getHeight()/2-cHeight/2; break; } cr = cl + cWidth; cb = cHeight + ct; childView.layout(cl, ct, cr, cb); } } @Override public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); }}3.接下来是在布局文件中使用了
<?xml version="1.0" encoding="utf-8"?><com.example.administrator.CustomView.widget.RcLinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:c_view="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="60dp" android:background="#123456" c_view:gravity="CENTER_VERTICAL"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="昵称" /> <TextView android:id="@+id/id_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="赵四" android:textSize="24sp" /></com.example.administrator.CustomView.widget.RcLinearLayout>嗯,基本上就这么多了。
0 0
- 自定义ViewGroup及其属性
- 自定义viewgroup的FadingEdge属性问题
- 自定义组件及其属性
- 自定义View或者ViewGroup的自定义属性使用技巧
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义viewGroup
- 自定义viewgroup
- 自定义viewgroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 关于String,StringBuilder的总结
- Android真机调试时,Device的连接容易断开
- #Android学习#Animation之布局动画
- 面向对象基础——static关键字和代码块的使用
- 随机模拟
- 自定义ViewGroup及其属性
- 1创业时我为什么选择PhoneGap?
- Android studio 报错 Plugin with id 'com.android.application' not found
- Android5.0 之 SnackBar
- 手速赛
- acm 1002 田忌赛马
- BCGControlBar介绍
- 2016 [Offer收割]编程练习赛3
- ubuntu maven环境安装配置以及工程创建