Android自定义viewgroup实现自定义布局
2017-08-14 16:12
465 查看
有时候为了实现自己业务相关的一些操作或者一些布局,用Android自身的布局方式去做的话,代码控制比较多,或者维护很麻烦,在这种情况下就要根据自己的需求定义一个否和自己业务需求的layout。首先肯定 的是,要继承viewgroup,然后重写里面的重要方法,不说了直接上代码把
定义属性,在values目录下的attrs文件下定义:
<declare-styleable name="MyLayout">
<attr name="lineCount" format="integer" />
<attr name="lineChildCount" format="integer" />
<attr name="lineGap" format="dimension" />
<attr name="childViewGap" format="dimension" />
</declare-styleable>
然后在xml中就可以直接使用了:
<com.example.srcb04178.vrplayer.ui.MyLayout
android:id="@+id/liveWraper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:childViewGap="30dp"
app:lineChildCount="3"
app:lineCount="1"
app:lineGap="30dp">
<!--views-->
</com.example.srcb04178.vrplayer.ui.MyLayout>
public class MyLayout extends ViewGroup { private static final String TAG = "MyLayout"; private int lineCount;//最大显示行数,0表示不限制行数 private int lineChildCount;//每行最大显示个数 private int lineGap;//行间距 private int childViewGap;//view间距 public MyLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public MyLayout(Context context) { super(context); } public MyLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyLayout); lineCount = typedArray.getInteger(R.styleable.MyLayout_lineCount, 1); lineChildCount = typedArray.getInteger(R.styleable.MyLayout_lineChildCount, 3); lineGap = (int) typedArray.getDimension(R.styleable.MyLayout_lineGap, 50); childViewGap = (int) typedArray.getDimension(R.styleable.MyLayout_childViewGap, 50); typedArray.recycle(); } public void setLineCount(int lineCount) { this.lineCount = lineCount; } public int getLineCount() { return lineCount; } public void setLineChildCount(int lineChildCount) { this.lineChildCount = lineChildCount; this.notify(); } public int getLineChildCount() { return lineChildCount; } public void setLineGap(int lineGap) { this.lineGap = lineGap; this.invalidate(); } public int getLineGap() { return lineGap; } public int getChildViewGap() { return childViewGap; } public void setChildViewGap(int childViewGap) { this.childViewGap = childViewGap; } /** * 计算所有ChildView的宽度和高度 然后根据ChildView的计算结果,设置自己的宽和高 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { /** * 获得此ViewGroup上级容器为其推荐的宽和高,以及计算模式 */ int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); // 计算出所有的childView的宽和高 measureChildren(widthMeasureSpec, heightMeasureSpec); /** * 记录如果是wrap_content是设置的宽和高,那么就需要将mylayout的宽和高计算出来才行 * 现在项目中的宽肯定是match_parent,高度是wrap,因此需要计算高度值 */ int childCount = getChildCount(); int a = childCount / lineChildCount; int b = childCount % lineChildCount; int trueLineCount = b == 0 ? a : a + 1;//真正显示几行,linecount是最大限制并不是真正显示的行数 if (lineCount!=0){ if (trueLineCount>lineCount){ trueLineCount=lineCount; } } int height; if (childCount == 0) { height = 0; } else { int childHeight = getChildAt(0).getMeasuredHeight(); height = childHeight * trueLineCount + lineGap * (trueLineCount - 1); } /** * 如果是wrap_content设置为我们计算的值 * 否则:直接设置为父容器计算的值 */ // System.out.println("width: "+sizeWidth+" height: "+sizeHeight); setMeasuredDimension(sizeWidth, (heightMode == MeasureSpec.EXACTLY) ? sizeHeight : height); } // abstract method in viewgroup @Override protected void onLayout(boolean changed, int l, int t, int r, int b) {这个方法在之前的myview 自定义view中也出现了,自定义view中这个方法是绘制自已
想要的view的形状,但是这个layout就不一样了,这里是在确定layout下的控件或者layout下的子view的位置,你想让你的子view怎么摆放你就怎么放。 if (getChildCount() != 0) { int cWidth = getChildAt(0).getMeasuredWidth(); int cHeight = getChildAt(0).getMeasuredHeight(); int width = getWidth(); int height = getHeight(); int margin = (width - lineChildCount * cWidth - (lineChildCount - 1) * childViewGap) / 2; for (int i = 0; i < getChildCount(); i++) { View childView = getChildAt(i); int atLine = i / lineChildCount; int lineIndex = i % lineChildCount; int cl = 0, ct = 0, cr = 0, cb = 0; cl = margin + lineIndex * cWidth + childViewGap * lineIndex; ct = lineGap * atLine + atLine * cHeight; cr = cl + cWidth; cb = ct + cHeight; childView.setVisibility(VISIBLE); childView.layout(cl, ct, cr, cb); } } } @Override public LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @Override protected LayoutParams generateDefaultLayoutParams() { Log.e(TAG, "generateDefaultLayoutParams"); return new MarginLayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT); } @Override protected LayoutParams generateLayoutParams( LayoutParams p) { Log.e(TAG, "generateLayoutParams p"); return new MarginLayoutParams(p); } /* * if (heightMode == MeasureSpec.UNSPECIFIED) { int tmpHeight = 0 ; LayoutParams lp = getLayoutParams(); if (lp.height == LayoutParams.MATCH_PARENT) { Rect outRect = new Rect(); getWindowVisibleDisplayFrame(outRect); tmpHeight = outRect.height(); }else { tmpHeight = getLayoutParams().height ; } height = Math.max(height, tmpHeight); } */ }
定义属性,在values目录下的attrs文件下定义:
<declare-styleable name="MyLayout">
<attr name="lineCount" format="integer" />
<attr name="lineChildCount" format="integer" />
<attr name="lineGap" format="dimension" />
<attr name="childViewGap" format="dimension" />
</declare-styleable>
然后在xml中就可以直接使用了:
<com.example.srcb04178.vrplayer.ui.MyLayout
android:id="@+id/liveWraper"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:childViewGap="30dp"
app:lineChildCount="3"
app:lineCount="1"
app:lineGap="30dp">
<!--views-->
</com.example.srcb04178.vrplayer.ui.MyLayout>
相关文章推荐
- android之自定义ViewGroup和自动换行的布局的实现(支持按钮间隔)
- android之自定义ViewGroup和自动换行的布局的实现
- android之自定义ViewGroup和自动换行的布局的实现
- Android 自定义ViewGroup 实现FlowLayout,动态添加布局
- android之自定义ViewGroup和自动换行的布局的实现
- android之自定义ViewGroup和自动换行的布局的实现
- Android自定义ViewGroup实现流式布局
- android自定义viewgroup实现等分格子布局
- android之自定义ViewGroup和自动换行的布局的实现
- 在Android中,可以自定义类,继承ViewGroup等容器类,以实现自己需要的布局显示。
- android之自定义ViewGroup和自动换行的布局的实现
- android自定义viewgroup实现等分格子布局
- android自定义viewgroup实现等分格子布局
- android之自定义ViewGroup和自动换行的布局的实现
- android之自定义ViewGroup和自动换行的布局的实现
- android自定义viewgroup实现等分格子布局
- android之自定义ViewGroup和自动换行的布局的实现
- android之自定义ViewGroup和自动换行的布局的实现
- android之自定义ViewGroup和自动换行的布局的实现
- android自定义viewgroup实现等分格子布局