您好,登錄后才能下訂單哦!
由于前段時間項目中使用到了自動換行的線性布局,本來打算用表格布局在里面一個個的用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; } }
效果截圖:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。