自定义ViewGroup-自定义LayoutParams支持显示方位
来源:互联网 发布:linux 开启snmp 编辑:程序博客网 时间:2024/05/06 13:44
自定义属性:
<resources> <declare-styleable name="CustomViewGroup5"> <attr name="layout_position" format="enum"> <enum name="left_top" value="0" /> <enum name="right_top" value="1" /> <enum name="left_bottom" value="2" /> <enum name="right_bottom" value="3" /> </attr> </declare-styleable></resources>
方位包含 4 个方向:左上角、右上角、左下角、右下角,在 attrs.xml 文件中,定义一个名为layout_position 的属性,类型为 enum,枚举出这 4 个值。
activity_main:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:custom="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:padding="10dp"> <com.example.user.myapplication4.CustomViewGroup5 android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="#FFCCCCCC" android:padding="10dp"> <TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="10dp" android:background="@android:color/holo_blue_bright" android:gravity="center" android:text="A" android:textColor="#FFFFFFFF" custom:layout_position="right_bottom" /> <TextView android:layout_width="100dp" android:layout_height="100dp" android:background="@android:color/holo_blue_dark" android:gravity="center" android:text="B" android:textColor="#FFFFFFFF" custom:layout_position="left_bottom" /> <TextView android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="10dp" android:background="@android:color/holo_red_dark" android:gravity="center" android:text="C" android:textColor="#FFFFFFFF" custom:layout_position="right_top" /> <TextView android:layout_width="100dp" android:layout_height="100dp" android:background="@android:color/holo_green_light" android:gravity="center" android:text="D" android:textColor="#FFFFFFFF" custom:layout_position="left_top" /> </com.example.user.myapplication4.CustomViewGroup5></LinearLayout>
public class CustomViewGroup5 extends ViewGroup { public CustomViewGroup5(Context context) { super(context); } public CustomViewGroup5(Context context, AttributeSet attrs) { this(context, attrs, 0); } public CustomViewGroup5(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } /** * @param attrs * @return */ @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { Log.i("log", "generateLayoutParams:AttributeSet"); return new PositionLayoutParams(this.getContext(), attrs); } @Override protected LayoutParams generateLayoutParams(LayoutParams p) { Log.i("log", "generateLayoutParams:LayoutParams"); return new PositionLayoutParams(p); } /** * @return */ @Override protected LayoutParams generateDefaultLayoutParams() { Log.i("log", "generateDefaultLayoutParams"); return new PositionLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); } /** * 自定义LayoutParams */ public static class PositionLayoutParams extends ViewGroup.MarginLayoutParams { public static final int LEFT_TOP = 0; public static final int RIGHT_TOP = 1; public static final int LEFT_BOTTOM = 2; public static final int RIGHT_BOTTOM = 3; public static final int NONE = -1; public int position; public PositionLayoutParams(Context c, AttributeSet attrs) { super(c, attrs); TypedArray typedArray = c.obtainStyledAttributes(attrs, R.styleable.CustomViewGroup5); position = typedArray.getInt(R.styleable.CustomViewGroup5_layout_position, NONE); typedArray.recycle(); } public PositionLayoutParams(int width, int height) { super(width, height); } public PositionLayoutParams(MarginLayoutParams source) { super(source); } public PositionLayoutParams(LayoutParams source) { super(source); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); //测量所有的子View measureChildren(widthMeasureSpec, heightMeasureSpec); //测量自己的宽高 int width = measureWidth(widthMeasureSpec); int height = measureHeight(heightMeasureSpec); setMeasuredDimension(width, height); } private int measureHeight(int widthMeasureSpec) { //父控件建议自己测量的值 int measureMode = MeasureSpec.getMode(widthMeasureSpec); int measureSize = MeasureSpec.getSize(widthMeasureSpec); int width = 0; if (measureMode == MeasureSpec.EXACTLY) { width = measureSize; } else if (measureMode == MeasureSpec.AT_MOST) { int aWidth = 0; int bWidth = 0; int cWidth = 0; int dWidth = 0; int haMargin = 0; int hbMargin = 0; int hcMargin = 0; int hdMargin = 0; for (int i = 0; i < getChildCount(); i++) { MarginLayoutParams layoutParams = (MarginLayoutParams) getChildAt(i).getLayoutParams(); if (i == 0) { aWidth = getChildAt(i).getMeasuredWidth();//左边View的宽度 haMargin += layoutParams.topMargin + layoutParams.bottomMargin; } else if (i == 1) { bWidth = getChildAt(i).getMeasuredWidth(); hbMargin += layoutParams.topMargin + layoutParams.bottomMargin; } else if (i == 2) { cWidth = getChildAt(i).getMeasuredWidth(); hcMargin += layoutParams.topMargin + layoutParams.bottomMargin; } else if (i == 3) { dWidth = getChildAt(i).getMeasuredWidth(); hdMargin = layoutParams.topMargin + layoutParams.bottomMargin; } } //getPaddingTop:top离top的内边距 getPaddingBottom:bottom离底的内边距 width = Math.max(aWidth, bWidth) + Math.max(cWidth, dWidth) + getPaddingTop() + getPaddingBottom() + Math.max(haMargin, hbMargin) + Math.max(hcMargin, hdMargin);//取到宽度的最大值 } return width; } private int measureWidth(int heightMeasureSpec) { int measureMode = MeasureSpec.getMode(heightMeasureSpec); int measureSize = MeasureSpec.getSize(heightMeasureSpec); int height = 0; if (measureMode == MeasureSpec.EXACTLY) { height = measureSize; } else if (measureMode == MeasureSpec.AT_MOST) { int aHeight = 0; int bHeight = 0; int cHeight = 0; int dHeight = 0; int waMargin = 0; int wbMargin = 0; int wcMargin = 0; int wdMargin = 0; for (int i = 0; i < getChildCount(); i++) { MarginLayoutParams layoutParams = (MarginLayoutParams) getChildAt(i).getLayoutParams(); if (i == 0) { aHeight = getChildAt(i).getMeasuredHeight(); waMargin = layoutParams.leftMargin + layoutParams.rightMargin; } else if (i == 1) { bHeight = getChildAt(i).getMeasuredHeight(); wbMargin = layoutParams.leftMargin + layoutParams.rightMargin; } else if (i == 2) { cHeight = getChildAt(i).getMeasuredHeight(); wcMargin = layoutParams.leftMargin + layoutParams.rightMargin; } else if (i == 3) { dHeight = getChildAt(i).getMeasuredHeight(); wdMargin = layoutParams.leftMargin + layoutParams.rightMargin; } } height = Math.max(aHeight, bHeight) + Math.max(cHeight, dHeight) + getPaddingLeft() + getPaddingRight() + Math.max(waMargin, wbMargin) + Math.max(wcMargin, wdMargin);//取到宽度的最大值 } return height; } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int leftPadding = getPaddingLeft(); int rightPadding = getPaddingRight(); int topPadding = getPaddingTop(); int bottomPadding = getPaddingBottom(); for (int i = 0; i < getChildCount(); i++) { View childView = getChildAt(i);//某一个子View PositionLayoutParams layoutParams = (PositionLayoutParams) childView.getLayoutParams(); int leftMargin = layoutParams.leftMargin; int topMargin = layoutParams.topMargin; int rightMargin = layoutParams.rightMargin; int bottomMargin = layoutParams.bottomMargin; int position = layoutParams.position; if (i == 0 && position == PositionLayoutParams.NONE || position == PositionLayoutParams.LEFT_TOP) { childView.layout(leftPadding + leftMargin, topPadding + topMargin, childView.getMeasuredWidth() + leftPadding + leftMargin, childView.getMeasuredHeight() + topPadding + topMargin); } else if (i == 1 && position == PositionLayoutParams.NONE || layoutParams.position == PositionLayoutParams.RIGHT_TOP) { childView.layout(getMeasuredWidth() - childView.getMeasuredWidth() - rightPadding - rightMargin, topPadding + topMargin, getMeasuredWidth() - rightPadding - rightMargin, childView.getMeasuredHeight() + topPadding + topMargin); } else if (i == 2 && position == PositionLayoutParams.NONE || layoutParams.position == PositionLayoutParams.LEFT_BOTTOM) { childView.layout(leftPadding + leftMargin, getMeasuredHeight() - childView.getMeasuredHeight() - bottomPadding - bottomMargin, childView.getMeasuredWidth() + leftPadding + leftMargin, getMeasuredHeight() - bottomPadding - bottomMargin); } else if (i == 3 && position == PositionLayoutParams.NONE || layoutParams.position == PositionLayoutParams.RIGHT_BOTTOM) { childView.layout(getMeasuredWidth() - childView.getMeasuredWidth() - rightPadding - rightMargin, getMeasuredHeight() - childView.getMeasuredHeight() - bottomPadding - bottomMargin, getMeasuredWidth() - rightPadding - rightMargin, getMeasuredHeight() - bottomPadding - bottomMargin); } } }}
PositionLayoutParams(Context c, AttributeSet attrs)读取了 layout_position 属性值,保存在 position成员变量中,如果未读取到该属性,则默认值为 NONE。其次定义了 4 个常量与 layout_position属性的 4 个枚举值相对应。ViewGroup 类重写的 generateLayoutParams()和 generateDefaultLayoutParams()方法返回的LayoutParams 为 PositionLayoutParams 对象。 其 中 public LayoutParams generateLayoutParams(AttributeSetattrs)方法将 attrs 传入 public PositionLayoutParams(Context c, AttributeSet attrs)构造方法,所以,PositionLayoutParams 才能读取到 layout_position 的属性值。在 onLayout()方法中,我们需要根据当前子组件的 PositionLayoutParams 的 position 属性来确定方位,这里有两种情况:一种是没有为组件定义方位时,依旧按照从左往右、从上往下的方式进行放置;另一种是如果组件定义了特定方位,如 right_bottom,则将该组件显示在容器的右下角。
结果显示:
- 自定义ViewGroup-自定义LayoutParams支持显示方位
- 自定义ViewGroup 支持Margin
- 自定义LayoutParams
- 自定义ViewGroup显示历史搜索
- android控件显示LayoutParams&PopupWindow &自定义title
- 【自定义控件】自定义ViewGroup 在ViewGroup中显示TextView
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义viewGroup
- 自定义viewgroup
- 自定义viewgroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 自定义ViewGroup
- 控制公司(dfs)
- Hibernate中Session.load/get方法
- 总结的前端入门方法
- eclipse 当中,小白们所不知道的 CRTL+1 快捷键
- JSP文件和Servlet在文件目录以及服务器中配置的不同
- 自定义ViewGroup-自定义LayoutParams支持显示方位
- 排序
- 应用java mail和阿里云发送邮件和上传附件
- 使用HTML5制作云层效果
- TNS:listener could not find available handler with matching protocol stack 解决办法
- 斐波那契额数列
- 机器学习之-分类性能指标-准确率-召回率-ROC曲线
- ZARCHIVE_WRITE(限制用于Z表)
- FFMPEG 图像拉伸缩放及数据格式转换