編輯:關於Android編程
常用的布局類型並不能滿足所有需求,這時就會用到ViewGroup。
ViewGroup作為一個放置View的容器,並且我們在寫布局xml的時候,會告訴容器(凡是以layout為開頭的屬性,都是為用於告訴容器的),我們的寬度(layout_width)、高度(layout_height)、對齊方式(layout_gravity)等;當然還有margin等;於是乎,ViewGroup需要做的事情是:給childView計算出建議的寬和高和測量模式 ;決定childView的位置;為什麼只是建議的寬和高,而不是直接確定呢,別忘了childView寬和高可以設置為wrap_content,這樣只有childView才能計算出自己的寬和高。
博客名已經說明了這篇博客要將給出的內容,不用贅述。
先看效果圖:
代碼注釋很詳細,直接看代碼即可,沒貼源碼,因為這是從一個項目裡面摳出來的。
先寫一個自定義LinearLayout,它的功能是自適應子控件:
public class ItemContainer extends LinearLayout {
private int width;//組件寬
private int height;//組件高
private int childCount;
private int childMarginLeft = SizeConvert.dip2px(getContext(),8);//子控件相對左邊控件的距離
private int childMarginHorizonTal = SizeConvert.dip2px(getContext(),10);//子控件相對最左、最右的距離
private int childMarginTop = SizeConvert.dip2px(getContext(),8);//子控件相對頂部控件的距離
private int childWidth;//子控件寬
private int childHeight;//子控件高
public ItemContainer(Context context) {
super(context);
}
public ItemContainer(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
childCount = getChildCount();//得到子控件數量
if(childCount>0) {
childWidth = (width - childMarginLeft * 4) / 3;
childHeight = SizeConvert.dip2px(getContext(),42);//給子控件的高度一個定值
//根據子控件的高和子控件數目得到自身的高
height = childHeight * ((childCount-1)/ 3+1) + childMarginHorizonTal * 2 + childMarginTop*((childCount-1)/3);
Log.d(childHeight,childHeight+);
}else {
//如果木有子控件,自身高度為0,即不顯示
height = 0;
}
width = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec);
Log.d(height,height+);
//根據自身的寬度約束子控件寬度
measureChildren(widthMeasureSpec, heightMeasureSpec);
//設置自身寬度
setMeasuredDimension(width, height);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
/**
* 遍歷所有子控件,並設置它們的位置和大小
* 每行只能有三個子控件,且高度固定,寬度相同,且每行正好布滿
*/
for (int i = 0; i < childCount; i++) {
View childView = getChildAt(i);//得到當前子控件
childView.layout((i%3) * childWidth + (i%3+1)*childMarginLeft
, (i / 3)*childHeight + childMarginHorizonTal + (i / 3)*childMarginTop
, (i%3+1) * childWidth + (i%3+1)*childMarginLeft
, (i / 3+1)*childHeight + childMarginHorizonTal + (i / 3)*childMarginTop);
}
}
}
主活動完成的功能就是上面貼圖演示的功能,讓兩個自定義ViewGroup能夠添加刪除子控件,子控件是在代碼中動態搭建的,下面會給出方法:
活動:
public class ItemOperateActivity extends BaseActivity {
private LinearLayout mContentNoItem;
private LinearLayout mContentItemRemove;
private ItemContainer mItemContainerAdd;
private ItemContainer mItemContainerRemove;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_item_operate);
mContentNoItem = (LinearLayout) findViewById(R.id.linearlayout_attention_null);
mContentItemRemove = (LinearLayout) findViewById(R.id.linearlayout_remove);
mItemContainerAdd = (ItemContainer) findViewById(R.id.item_container_add);
mItemContainerRemove = (ItemContainer) findViewById(R.id.item_container_remove);
initItems(new String[]{隨時定位, 客戶拜訪}, new String[]{新增客戶, 客戶總量});
}
/**
* 添加條目時需要調用的方法
* @param name
*/
private void addItem(String name) {
mContentNoItem.setVisibility(View.GONE);
Button button = new Button(getApplicationContext());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
, 0);
button.setLayoutParams(params);
button.setText(name);
button.setGravity(Gravity.CENTER);
button.setBackgroundResource(R.drawable.item_select_bg);
button.setTextSize(13);
button.setTextColor(Color.argb(255, 47, 79, 79));//鉛灰色
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mItemContainerAdd.removeView(v);
removeItem(((Button) v).getText().toString());
if (mItemContainerAdd.getChildCount()== 0) {
mContentNoItem.setVisibility(View.VISIBLE);
}
}
});
mItemContainerAdd.addView(button);
}
/**
* 刪除條目時需要調用的方法
* @param name
*/
private void removeItem(String name) {
mContentItemRemove.setVisibility(View.VISIBLE);
Button button = new Button(getApplicationContext());
ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT
, 0);
button.setLayoutParams(params);
button.setText(name);
button.setGravity(Gravity.CENTER);
button.setBackgroundResource(R.drawable.item_select_bg_below);
button.setTextSize(13);
button.setTextColor(Color.argb(255, 47, 79,79));//鉛灰色
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
/**
* 點擊按鈕時,刪除
*/
mItemContainerRemove.removeView(v);
addItem(((Button) v).getText().toString());
if (mItemContainerRemove.getChildCount() == 0) {
mContentItemRemove.setVisibility(View.GONE);
}
}
});
mItemContainerRemove.addView(button);
}
/**
* 初始化子控件
* @param itemsAdd 已添加的子控件名數組
* @param itemsRemove 可添加的子控件名數組
*/
private void initItems(String[] itemsAdd, String[] itemsRemove) {
for (String itemAdd : itemsAdd) {
addItem(itemAdd);
}
for (String itemRemove : itemsRemove) {
removeItem(itemRemove);
}
}
}
布局:
drawable下的文件:
item_bg:
item_select_bg:
item_select_bg_below:
簡述Qt Network 模塊中提供了一些高級別的類,例如:QNetworkRequest、QNetworkReply 和 QNetworkAccessManager,使
簡介最近因為項目需求,要實現一款雷達圖來表示用戶的各種成就值雷達圖的繪制很簡單,只要思路清晰按部就班的繪制就可以了,其中使用得最多,是路徑path類的使用,使用這個類可以
本文github地址:https://github.com/YoungBear/MyBlog/blob/master/VolleyLearn.mdVolley是Andro
Android實際開發中,在加載大量圖片的時候,比如ViewPager、GridView、ListView中,加載了大量的比較大圖片就容易出現OOM(內存溢出)的異常,這