android自定义View&自定义ViewGroup(下)
来源:互联网 发布:程序员什么时候跳槽好 编辑:程序博客网 时间:2024/05/20 23:34
接上篇,android自定义View&自定义ViewGroup(上)
上篇主要是自定义View,本篇来看看自定义ViewGroup。
先来复习一下一般自定义ViewGroup中需要复写的方法:
void onMeasure(int widthMeasureSpec, int heightMeasureSpec)void onSizeChanged(int w, int h, int oldw, int oldh)void onLayout(boolean changed, int left, int top, int right, int bottom)void onDraw(Canvas canvas)
注:ViewGroup的onLayout方法是必须重写的,而onDraw方法默认是不会调用的,如果想执行onDraw方法,可以通过下面两种方法:
1.设置透明背景:
在构造函数中:setBackgroundColor(Color.TRANSPARENT);
或者在xml中:android:background="@color/transparent"
2.或者可以在构造函数中添加setWillNotDraw(false);
自定义ViewGroup中如果需要获得自定义属性,方法和上篇自定义View中获取方法是一样的,请参照上篇。
ViewGroup常用重写方法:
onMeasure
measureChildren方法触发所有子View的onMeasure方法测量自己并把测量结果回传给ViewGroup(ViewGroup传递给子View建议宽高和测量模式,如果子View的宽高是wrap_content,那么只有子View测量出自己的宽和高),当所有子View测量完毕后,再调用setMeasuredDimension将ViewGroup自身的宽和高传给它的父View。onSizeChanged
在onMeasure()后执行,只有大小发生了变化才会执行onSizeChangeonLayout
排列所有子View的位置
通过getChildCount()获取所有子view,getChildAt获取childview调用各自的layout(int, int, int, int)方法来排列自己。onDraw
上面已经提到,自定义ViewGroup默认不会触发onDraw方法,需要设置背景色或者setWillNotDraw(false)来手动触发。
自定义ViewGroup例子,先上图:
代码已上传到github:自定义ViewGroup(五环图)
思路:首先是5个自定义圆环,在自定义ViewGroup的onLayout中排列他们,在onDraw中写文字。
核心代码:
public class CustomFiveRings extends ViewGroup { private Context mContext; private TextPaint mPaint; private int startX;//圆环起始X轴 private int startY;//圆环起始Y轴 private int mWidth;//ViewGroup的宽 private int mHeight;//ViewGroup的高 public CustomFiveRings(Context context) { this(context, null); } public CustomFiveRings(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomFiveRings(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setBackgroundColor(Color.TRANSPARENT); mContext = context; mPaint = new TextPaint(); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setTextSize(50); mPaint.setColor(Color.BLACK); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //触发所有子View的onMeasure函数去测量宽高 measureChildren(widthMeasureSpec, heightMeasureSpec); //MeasureSpec封装了父View传递给子View的布局要求 int wMode = MeasureSpec.getMode(widthMeasureSpec); int wSize = MeasureSpec.getSize(widthMeasureSpec); int hMode = MeasureSpec.getMode(heightMeasureSpec); int hSize = MeasureSpec.getSize(heightMeasureSpec); switch (wMode) { case MeasureSpec.EXACTLY: mWidth = wSize; break; case MeasureSpec.AT_MOST: //这里应该先计算所有子view的宽度,暂时先写死 mWidth = wSize; break; case MeasureSpec.UNSPECIFIED: break; } switch (hMode) { case MeasureSpec.EXACTLY: mHeight = hSize; break; case MeasureSpec.AT_MOST: //这里应该先计算所有子view的高度,暂时先写死 mHeight = hSize; // mHeight = getCircleHeight() / 2 * 3; break; case MeasureSpec.UNSPECIFIED: break; } setMeasuredDimension(mWidth, mHeight); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childNum = getChildCount(); startX = startY = 0; int gap = 10;//同一行圆圈之间的间隔 int screenWidth = DpUtil.getScreenSizeWidth(mContext); int firstTotalWidth = 0;//第一行子View的总宽度 int secondTotalWidth = 0;//第二行子View的总宽度 for (int i = 0; i < childNum; i++) { View childView = getChildAt(i); int childWidth = childView.getMeasuredWidth(); if (i <= 2) { //前三个总宽度 firstTotalWidth += childWidth; } else { //后两个总宽度 secondTotalWidth += childWidth; } } int leftFMargin = (screenWidth - firstTotalWidth - gap * 2) / 2; int leftSMargin = (screenWidth - secondTotalWidth - gap) / 2; for (int i = 0; i < childNum; i++) { View childView = getChildAt(i); int childWidth = childView.getMeasuredWidth(); int childHeight = childView.getMeasuredHeight(); if (i <= 2) { //排列前三个圆圈 if (i == 0) { childView.layout(leftFMargin + startX, startY, leftFMargin + startX + childWidth, startY + childHeight); startX += childWidth; } else { childView.layout(leftFMargin + startX + gap, startY, leftFMargin + startX + gap + childWidth, startY + childHeight); startX += (childWidth + gap); } if (i == 2) { startX = 0; startY += childHeight / 2; } } else { //排列后两个圆圈 if (i == 3) { childView.layout(leftSMargin + startX, startY, leftSMargin + startX + childWidth, startY + childHeight); startX += childWidth; } else { childView.layout(leftSMargin + startX + gap, startY, leftSMargin + startX + gap + childWidth, startY + childHeight); startX += (childWidth + gap); } } } } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); int screenWidth = DpUtil.getScreenSizeWidth(mContext); String upStr = "同一个世界,同一个梦想"; String downStr = "One World,One Dream"; canvas.drawText(upStr, (screenWidth - mPaint.measureText(upStr)) / 2, getCircleHeight() / 2 * 3 + 60, mPaint); canvas.drawText(downStr, (screenWidth - mPaint.measureText(downStr)) / 2, getCircleHeight() / 2 * 3 + 120, mPaint); } /** * 获得圆环高度 * * @return 圆环高度 */ private int getCircleHeight() { //5个圆环大小是一样的,这里就直接取第一个了 View childView = getChildAt(0); return childView.getMeasuredHeight(); }}
0 0
- android自定义View&自定义ViewGroup(下)
- android自定义View&自定义ViewGroup(下)
- android自定义View(viewGroup)
- android自定义View、ViewGroup
- Android 自定义View 和 ViewGroup
- Android 自定义View和ViewGroup
- Android自定义View和ViewGroup
- android自定义View&自定义ViewGroup(上)
- android自定义View&自定义ViewGroup(上)
- 【Android 应用开发】自定义View 和 ViewGroup
- android view 自定义viewgroup 实例--屏幕滑动
- android中自定义View及ViewGroup 学习心得
- Android控件:自定义View和ViewGroup相关
- Android自定义View(四)继承ViewGroup
- Android自定义View或ViewGroup的流程
- Android笔记【3】--ViewGroup & 自定义view
- Android中自定义View、ViewGroup理论基础详解
- Android View体系(十一)自定义ViewGroup
- 面向对象
- Android 基于Key-Value的缓存管理
- Charles 从入门到精通
- Rxjava详解
- 面试-一道经典的sql语句题
- android自定义View&自定义ViewGroup(下)
- cooseek使用总结
- LeetCode 485. Max Consecutive Ones
- The C++ Programming Language 读书笔记(三)
- 为JFileChooser设定扩展名过滤
- Java ---自定义标签
- thymeleaf模板整合shiro标签
- 新手第一步
- 儿童信仰问答 翻译:煦译自: First Catechism--Biblical Truth for God's Children --Published by Great Commission Pu