Android-automatically wrap ViewGroup based on the size of child controls, android-viewgroup
1. Custom ViewGroup
1/** 2 * Created by Administrator on 2016/2/26. 3*4 * -------- automatically wrap ViewGroup ----------- 5 */6 public class LineWrapLayout extends ViewGroup {7 private static final boolean DEBUG = true; 8 private static final String TAG = "AutoLineFeedLayout "; 9 10/** 11 * left margin 12 */13 private int paddingLeft = 10; 14/** 15 * right margin 16 */17 private int paddingRight = 10; 18/** 19*20 */21 private int paddin GTop = 10; 22/** 23*24 */25 private int paddingBottom = 10; 26 27/** 28 * horizontal spacing 29 */30 private int horizontalSpace = 10; 31/** 32 * row spacing 33 */34 private int verticalSpace = 5; 35 36 37 private List <Integer> listX; 38 private List <Integer> listY; 39 40 public LineWrapLayout (Context context) {41 super (context); 42 43} 44 public LineWrapLayout (Context context, AttributeSet attrs) {45 supe R (context, attrs); 46 init (attrs); 47} 48 49 public LineWrapLayout (Context context, AttributeSet attrs, int defStyle) {50 super (context, attrs, defStyle ); 51 init (attrs); 52} 53 54 55 @ Override 56 protected void onLayout (boolean changed, int l, int t, int r, int B) {57 if (DEBUG) log. d (TAG, "--- onLayout changed:" + changed + "l:" + l + ", t:" + t + ", r:" + r + ", B: "+ B); 58 int count = g EtChildCount (); 59 int width = getWidth (); 60 Log. I (TAG, "width:" + width); 61 62 63 int startOffsetX = paddingLeft; // the abscissa starts with 64 int startOffsety = 0; // start with 65 int rowCount = 1; 66 67 int preEndOffsetX = startOffsetX; 68 69 for (int I = 0; I <count; I ++) {70 final View childView = getChildAt (I ); 71 72 int w = childView. getMeasuredWidth (); 73 int h = childView. getMeasuredHeight (); 74 75 int x = listX. Get (I); 76 int y = listY. get (I); 77 78 // layout child control 79 childView. layout (x, y, x + w, y + h); 80} 81} 82 @ Override 83 protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {84 if (DEBUG) log. v (TAG, "--- onMeasure ()"); 85 86 int count = getChildCount (); 87 int width = measureWidth (widthMeasureSpec); 88 Log. I (TAG, "width:" + width); 89 90 91 int startOffsetX = paddingLeft; // the abscissa starts 92 int s. TartOffsety = 0 + paddingTop; // start with Y coordinate 93 int rowCount = 1; 94 95 int preEndOffsetX = startOffsetX; 96 97 listX. clear (); 98 listY. clear (); 99 for (int I = 0; I <count; I ++) {100 Log. v (TAG, "----"); 101 final View childView = getChildAt (I); 102 // set the Child's width and height to 103 childView. measure (104); 105/* get the Child's width and height */int childWidth = childView. getMeasuredWidth (); 106 int childHeight = childView. getMeasuredHe Ight (); 107 Log. v (TAG, "Maid:" + childWidth + "childHeight:" + childHeight); 108 preEndOffsetX = startOffsetX + childWidth/* + CHILD_MARGIN */; 109 // TODO [yaojian] margin attributes? 110 if (preEndOffsetX> width-paddingRight) {111 if (startOffsetX> paddingLeft) {112/* line feed */113 startOffsetX = paddingLeft; 114 startOffsety + = childHeight + verticalSpace; 115 rowCount ++; 116} 117} 118 Log. d (TAG, "measure child:" + startOffsetX + "," + startOffsety + "," + preEndOffsetX + "," + (startOffsety + childHeight); 119 listX. add (startOffsetX); 120 listY. add (startOffsety); 121 122 // childView. layout (st Values, values, preEndOffsetX, values + childHeight); 123 startOffsetX = startOffsetX + childWidth + horizontalSpace; 124} 125 int lastLineHeight = 0; 126 View lastChild = getChildAt (count-1 ); 127 if (null! = LastChild) {128 lastLineHeight = lastChild. getMeasuredHeight (); 129} 130 setMeasuredDimension (measureWidth (widthMeasureSpec), startOffsety + lastLineHeight + paddingBottom); 131 // super. onMeasure (widthMeasureSpec, gauge); 132 133 // pay attention to usage of counter and resolveSize 134 // counter (resolveSize (measuredWidth, widthMeasureSpec), 135 // resolveSize (top, heightMeasureSpec )); 136} 137 138 private int measureWidth (int measureSpec) {139 int specMode = MeasureSpec. getMode (measureSpec); 140 int specSize = MeasureSpec. getSize (measureSpec); 141 142 143 // Default size if no limits are specified.144 int result = 400; 145 146 if (specMode = MeasureSpec. AT_MOST) {147 // Calculate the ideal size of your control148 // within this maximum size.149 // If your control fills the available space150 // return the outer bound.151 result = specSize; 152} else if (specMode = MeasureSpec. EXACTLY) {153 // If your control can fit within these bounds return that value.154 result = specSize; 155} 156 return result; 157} 158 159 private void init (AttributeSet attrs) {160 TypedArray attrArray = getContext (). obtainStyledAttributes (attrs, R. styleable. autoLineFeedLayout); 161 int attrCount = attrArray. getIndexCount (); 162 for (int I = 0; I <attrCount; I ++) {163 int attrId = attrArray. getIndex (I); 164 switch (attrId) {165 case R. styleable. autoLineFeedLayout_horizontalSpacing: {166 float dimen = attrArray. getDimension (attrId, 0); 167 horizontalSpace = (int) dimen; 168} 169 break; 170 case R. styleable. autoLineFeedLayout_verticalSpacing: {171 float dimen = attrArray. getDimension (attrId, 0); 172 verticalSpace = (int) dimen; 173} 174 break; 175 case R. styleable. autoLineFeedLayout_paddingBottom: {176 float dimen = attrArray. getDimension (attrId, 0); 177 paddingBottom = (int) dimen; 178} 179 break; 180 case R. styleable. autoLineFeedLayout_paddingLeft: {181 float dimen = attrArray. getDimension (attrId, 0); 182 paddingLeft = (int) dimen; 183} 184 break; 185 case R. styleable. autoLineFeedLayout_paddingRight: {186 float dimen = attrArray. getDimension (attrId, 0); 187 paddingRight = (int) dimen; 188} 189 break; 190 case R. styleable. autoLineFeedLayout_paddingTop: {191 float dimen = attrArray. getDimension (attrId, 0); 192 paddingTop = (int) dimen; 193} 194 break; 195 case R. styleable. autoLineFeedLayout_debug: {196 197} 198 break; 199 200 201 default: 202 break; 203} 204 205 206 listX = new ArrayList <Integer> (); 207 listY = new ArrayList <Integer> (); 208} 209}
2. Some custom attributes are available for attrs. xml.
<declare-styleable name="AutoLineFeedLayout"> <attr name="debug" format="boolean"></attr> <attr name="paddingLeft" format="reference|dimension"/> <attr name="paddingRight" format="reference|dimension"/> <attr name="paddingTop" format="reference|dimension"/> <attr name="paddingBottom" format="reference|dimension"/> <attr name="verticalSpacing" format="reference|dimension"/> <attr name="horizontalSpacing" format="reference|dimension"/> </declare-styleable>
3. Use the same layout file as the common ViewGroup
4. dynamically Add a View or ViewGroup to the Activity
for (int i = 0;i < myData.getList().length;i++){ View child = View.inflate(ZhuanTiActivity.this,R.layout.item_mygridview_layout,null); TextView textView = (TextView) child.findViewById(R.id.tv_title_item); textView.setText(myData.getList()[i].getName()); textView.setTextColor(Color.argb(255, colorR, colorG, colorB)); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Log.d("aaa",textView.getText()); } }); custom_index_zhuanTiActivity.addView(child); }