Android自定義ViewGroup之子控制元件的自動換行和新增刪除
常用的佈局型別並不能滿足所有需求,這時就會用到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);
}
}
}
佈局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:background="@drawable/item_bg">
<LinearLayout
android:id="@+id/linearlayout_back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:layout_marginLeft="5dp"
android:gravity="center"
android:orientation="horizontal">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/btn_back"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="報表"
android:textSize="@dimen/head_left_text_size"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:text="訂閱"
android:textSize="@dimen/head_center_text_size"/>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_bg"
android:orientation="horizontal"
android:paddingBottom="12dp"
android:paddingLeft="8dp"
android:paddingTop="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="已新增"
android:textSize="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="(點選刪除)"
android:textSize="13dp"/>
</LinearLayout>
<com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.ItemContainer
android:id="@+id/item_container_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_bg">
</com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.ItemContainer>
<LinearLayout
android:id="@+id/linearlayout_attention_null"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="35dp"
android:paddingBottom="35dp"
android:gravity="center"
android:background="@drawable/item_bg"
android:visibility="gone">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/attendance_null"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="13dp"
android:text="無報表資訊"/>
</LinearLayout>
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<LinearLayout
android:id="@+id/linearlayout_remove"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_bg"
android:orientation="horizontal"
android:layout_marginTop="@dimen/first_page_item_margin_top"
android:paddingBottom="12dp"
android:paddingLeft="8dp"
android:paddingTop="12dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="可新增"
android:textSize="16dp"/>
</LinearLayout>
<com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.ItemContainer
android:id="@+id/item_container_remove"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@drawable/item_bg">
</com.test.shiweiwei.myproject.selfish_view.self_defined_view_group.ItemContainer>
</LinearLayout>
</LinearLayout>
drawable下的檔案:
item_bg.xml:
<!--?xml version=1.0 encoding=utf-8?-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"></solid>
<stroke android:color="@color/stroke_vertical" android:width="0.3dp"></stroke>
</shape>
item_select_bg.xml:
<!--?xml version=1.0 encoding=utf-8?-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"></solid>
<stroke android:color="@color/dark_brow" android:width="0.3dp"></stroke>
<corners android:radius="4dp"></corners>
<padding android:bottom="12dp" android:top="12dp"></padding>
</shape>
item_select_bg_below.xml:
<!--?xml version=1.0 encoding=utf-8?-->
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/white"></solid>
<stroke android:color="@color/stroke_vertical" android:width="0.3dp"></stroke>
<corners android:radius="4dp"></corners>
</shape>
最後感謝原創者的無私奉獻精神。
相關文章
- Android自定義控制元件之自定義ViewGroup實現標籤雲Android控制元件View
- 新增了自定義的編輯和刪除按鈕
- android 滑動刪除的listview(自定義view)AndroidView
- Android動畫效果之自定義ViewGroup新增布局動畫Android動畫View
- Android自定義ViewGroup(一)AndroidView
- android自定義View&自定義ViewGroup(下)AndroidView
- android自定義View&自定義ViewGroup(上)AndroidView
- Android自定義View:ViewGroup(三)AndroidView
- Android ViewDragHelper 自定義 ViewGroup 神器AndroidView
- jQuery動態新增和刪除表格行jQuery
- Android自定義ViewGroup View的大小和座標控制AndroidView
- TextView 自動換行,每行排滿的自定義TextViewTextView
- android view 自定義viewgroup 例項--螢幕滑動AndroidView
- Android ViewDragHelper完全解析 自定義ViewGroup神器AndroidView
- jQuery table表格行的新增和刪除jQuery
- 【WPF】自定義一個自刪除的多功能ListBox
- 自定義ViewGroup,實現Android的側滑選單ViewAndroid
- Android自定義控制元件——自定義屬性Android控制元件
- Android自定義控制元件之自定義組合控制元件Android控制元件
- Android中ListView動態新增刪除項AndroidView
- JavaScript table表格行進行刪除和新增JavaScript
- Android開發教程:自定義ViewGroup方法總結AndroidView
- 批量新增、刪除控制元件組--【ssnc】控制元件
- Android自定義控制元件之自定義屬性Android控制元件
- js如何刪除和新增table中的行和列JS
- 織夢多行文字自定義欄位 支援自動換行
- JavaScript動態新增和刪除div元素JavaScript
- javascript如何動態新增和刪除元素JavaScript
- GridView 自定義模版自定義修改,刪除,分頁View
- PostgreSQL自定義自動型別轉換(CAST)SQL型別AST
- ViewGroup篇:玩一下自定義ViewGroupView
- Android技術分享| 自定義ViewGroup實現直播間大小屏無縫切換AndroidView
- Hyperledger Fabric組織的動態新增和刪除
- Hyperledger Fabric節點的動態新增和刪除
- Windows服務的手動新增和刪除方法Windows
- android 實現FlowLayout 流線佈局(自定義ViewGroup)AndroidView
- android:建立自定義控制元件Android控制元件
- jquery table 的新增和刪除jQuery