標籤:自動 運算元 tla param adapter set line top
由於前段時間項目中使用到了自動換行的線性布局,本來打算用表格版面配置在裡面一個個的用Java代碼添加ImageView的,但是添加的View控制項是不確定的,因為得靠伺服器的資料返回,就這樣手動用Java代碼畫布局的方式就這樣夭折了,因為在表哥布局中我無法確定一行顯示多少個ImageView的數目,所以無法動態添加,最後自能自己去看看那種能夠換行的線性布局了,線性布局比較不好的是不能自動換行,也就是當設定LinearLayout的orentation 設定為vertical 為豎直方向也就是只有一列,每行只能顯示一個View或者View的子類,當設定LinearLayout的orentitation為Horizontal,LinearLayout的只能顯示為一行,橫向顯示,當螢幕滿了的時候,View控制項並不會自動換行,所以我們要做的就是在LinearLayout滿的時候自動換行。
需要瞭解的是怎麼樣繪製根據子控制項的長寬繪製父控制項的寬度與高度,所以需要傳入的參數控制項的高度,視圖分為兩種一種是View類型的,代表控制項有TextView,Button,EditText 等等,還有一種是裝視圖的容器控制項繼承自ViewGroup的控制項,如LinearLayout,RelativeLayout,TabHost等等控制項,需要自動換行的線性布局的話,就需要根據子控制項的高度與寬度,來動態載入父控制項的高度與寬度,所以需要在建構函式中傳入每一個子控制項的固定的高度,或者是動態設定子控制項的高度與寬度。
將自訂的LinearLayout 也繼承自ViewGroup 並且重寫抽象類別ViewGrouop的幾個方法:onMeasure(),onLayout(),dispathDraw() 三個方法的意思分別是:第一個onMeasure()是用來計算控制項以及子控制項所佔用的地區,第二個onLayout()是控制子控制項的換行,第三個可寫可不寫,主要是用來繪製控制項的邊框,
自訂LinearLayout的代碼如下:
package com.huanglong.mylinearlayout; import android.content.Context;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup; /** * @author huanglong 2013-5-28 自訂自動換行LinearLayout */public class FixGridLayout extends ViewGroup { private int mCellWidth; private int mCellHeight; public FixGridLayout(Context context) { super(context); } public FixGridLayout(Context context, AttributeSet attrs) { super(context, attrs); } public FixGridLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public void setmCellWidth(int w) { mCellWidth = w; requestLayout(); } public void setmCellHeight(int h) { mCellHeight = h; requestLayout(); } /** * 控制子控制項的換行 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int cellWidth = mCellWidth; int cellHeight = mCellHeight; int columns = (r - l) / cellWidth; if (columns < 0) { columns = 1; } int x = 0; int y = 0; int i = 0; int count = getChildCount(); for (int j = 0; j < count; j++) { final View childView = getChildAt(j); // 擷取子控制項Child的寬高 int w = childView.getMeasuredWidth(); int h = childView.getMeasuredHeight(); // 計運算元控制項的頂點座標 int left = x + ((cellWidth - w) / 2); int top = y + ((cellHeight - h) / 2); // int left = x; // int top = y; // 布局子控制項 childView.layout(left, top, left + w, top + h); if (i >= (columns - 1)) { i = 0; x = 0; y += cellHeight; } else { i++; x += cellWidth; } } } /** * 計算控制項及子控制項所佔地區 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 建立測量參數 int cellWidthSpec = MeasureSpec.makeMeasureSpec(mCellWidth, MeasureSpec.AT_MOST); int cellHeightSpec = MeasureSpec.makeMeasureSpec(mCellHeight, MeasureSpec.AT_MOST); // 記錄ViewGroup中Child的總個數 int count = getChildCount(); // 設定子空間Child的寬高 for (int i = 0; i < count; i++) { View childView = getChildAt(i); /* * 090 This is called to find out how big a view should be. 091 The * parent supplies constraint information in the width and height * parameters. 092 The actual mesurement work of a view is performed * in onMeasure(int, int), 093 called by this method. 094 Therefore, * only onMeasure(int, int) can and must be overriden by subclasses. * 095 */ childView.measure(cellWidthSpec, cellHeightSpec); } // 設定容器控制項所佔地區大小 // 注意setMeasuredDimension和resolveSize的用法 setMeasuredDimension(resolveSize(mCellWidth * count, widthMeasureSpec), resolveSize(mCellHeight * count, heightMeasureSpec)); // setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); // 不需要調用父類的方法 // super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * 為控制項添加邊框 */ @Override protected void dispatchDraw(Canvas canvas) { // 擷取布局控制項寬高 int width = getWidth(); int height = getHeight(); // 建立畫筆 Paint mPaint = new Paint(); // 設定畫筆的各個屬性 mPaint.setColor(Color.BLUE); mPaint.setStyle(Paint.Style.STROKE); mPaint.setStrokeWidth(10); mPaint.setAntiAlias(true); // 建立矩形框 Rect mRect = new Rect(0, 0, width, height); // 繪製邊框 canvas.drawRect(mRect, mPaint); // 最後必須調用父類的方法 super.dispatchDraw(canvas); } }
然後在Xml檔案中引用自己定義的控制項,在Java代碼中調用:
package com.huanglong.mylinearlayout; import android.os.Bundle;import android.app.Activity;import android.view.Menu;import android.view.MenuItem;import android.widget.CheckBox;import android.widget.SimpleAdapter;import android.support.v4.app.NavUtils; public class MainActivity extends Activity { private SimpleAdapter adapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FixGridLayout fixGridLayout = (FixGridLayout) findViewById(R.id.ll); fixGridLayout.setmCellHeight(30); fixGridLayout.setmCellWidth(100); for (int i = 0; i < 7; i++) { CheckBox box = new CheckBox(MainActivity.this); box.setText("第"+i+"個"); fixGridLayout.addView(box); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
效果:
Android LinearLayout 自動換行