Android自定義佈局-自動換行的RadioGroup
本文介紹一種可根據屏幕寬度,自動換行排列的RadioGroup控件。如下圖所示:
自定義控件類MyRadioGroup:
package com.wonder.collectionsystem.view;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.RadioGroup;
/**
* @author M.xang
* @時間 2018年11月12日
* @描述 自動換行RadioGroup
*/
public class MyRadioGroup extends RadioGroup {
public MyRadioGroup(Context context) {
super(context);
}
public MyRadioGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
// 調用ViewGroup的方法,測量子view
measureChildren(widthMeasureSpec, heightMeasureSpec);
// 最大的寬
int maxWidth = 0;
// 累計的高
int totalHeight = 0;
// 當前這一行的累計行寬
int lineWidth = 0;
// 當前這行的最大行高
int maxLineHeight = 0;
// 用於記錄換行前的行寬和行高
int oldHeight;
int oldWidth;
int count = getChildCount();
// 假設 widthMode和heightMode都是AT_MOST
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
// 得到這一行的最高
oldHeight = maxLineHeight;
// 當前最大寬度
oldWidth = maxWidth;
int deltaX = child.getMeasuredWidth() + params.leftMargin + params.rightMargin;
if (lineWidth + deltaX + getPaddingLeft() + getPaddingRight() > widthSize) {
// 如果換行,height增加和目前最大的寬度比較,得到最寬。不能加上當前的child的寬,所以用的是oldWidth
maxWidth = Math.max(lineWidth, oldWidth);
// 重置寬度
lineWidth = deltaX;
// 累加高度
totalHeight += oldHeight;
// 重置行高,當前這個View,屬於下一行,因此當前最大行高爲這個child的高度加上margin
maxLineHeight = child.getMeasuredHeight() + params.topMargin + params.bottomMargin;
} else {
// 不換行,累加寬度
lineWidth += deltaX;
// 不換行,計算行最高
int deltaY = child.getMeasuredHeight() + params.topMargin + params.bottomMargin;
maxLineHeight = Math.max(maxLineHeight, deltaY);
}
if (i == count - 1) {
// 前面沒有加上下一行的高,如果是最後一行,還要再疊加上最後一行的最高的值
totalHeight += maxLineHeight;
// 計算最後一行和前面的最寬的一行比較
maxWidth = Math.max(lineWidth, oldWidth);
}
}
// 加上當前容器的padding值
maxWidth += getPaddingLeft() + getPaddingRight();
totalHeight += getPaddingTop() + getPaddingBottom();
/**
* wrap_content --- MeasureSpec.AT_MOST
* match_parent --- MeasureSpec.EXACTLY
* -具體值--- MeasureSpec.UNSPECIFIED
*/
// 設置當前View的寬高
setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : maxWidth,
heightMode == MeasureSpec.EXACTLY ? heightSize : totalHeight);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
int count = getChildCount();
// pre爲前面所有的child的相加後的位置
int preLeft = getPaddingLeft();
int preTop = getPaddingTop();
// 記錄每一行的最高值
int maxHeight = 0;
for (int i = 0; i < count; i++) {
View child = getChildAt(i);
MarginLayoutParams params = (MarginLayoutParams) child.getLayoutParams();
// r-l爲當前容器的寬度。如果子view的累積寬度大於容器寬度,就換行。
if (preLeft + params.leftMargin + child.getMeasuredWidth() + params.rightMargin
+ getPaddingRight() > (r - l)) {
// 重置
preLeft = getPaddingLeft();
// 要選擇child的height最大的作爲設置
preTop = preTop + maxHeight;
maxHeight = getChildAt(i).getMeasuredHeight() + params.topMargin + params.bottomMargin;
} else { // 不換行,計算最大高度
maxHeight = Math.max(maxHeight,
child.getMeasuredHeight() + params.topMargin + params.bottomMargin);
}
// left座標
int left = preLeft + params.leftMargin;
// top座標
int top = preTop + params.topMargin;
int right = left + child.getMeasuredWidth();
int bottom = top + child.getMeasuredHeight();
// 爲子view佈局
child.layout(left, top, right, bottom);
// 計算佈局結束後,preLeft的值
preLeft += params.leftMargin + child.getMeasuredWidth() + params.rightMargin;
}
}
}
在佈局中的使用:
<com.view.MyRadioGroup
android:id="@+id/rg_deviceChoose"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<RadioButton
style="@style/SearchRBtnStyle"
android:text="@string/zbzd" />
<RadioButton
style="@style/SearchRBtnStyle"
android:text="@string/jzq1" />
<RadioButton
style="@style/SearchRBtnStyle"
android:text="@string/jzq2" />
<RadioButton
style="@style/SearchRBtnStyle"
android:text="@string/cjq" />
<RadioButton
style="@style/SearchRBtnStyle"
android:text="@string/dnb" />
</com.view.MyRadioGroup>
SearchRBtnStyle樣式佈局:
<!-- 搜索界面,方框字的格式 -->
<style name="SearchRBtnStyle">
<item name="android:button">@null</item>
<item name="android:layout_width">wrap_content</item>
<item name="android:layout_height">wrap_content</item>
<item name="android:paddingLeft">20dp</item>
<item name="android:paddingRight">20dp</item>
<item name="android:paddingTop">8dp</item>
<item name="android:paddingBottom">8dp</item>
<item name="android:layout_marginLeft">10dp</item>
<item name="android:layout_marginTop">10dp</item>
<item name="android:textColor">@color/textcolor_black_white</item>
<item name="android:background">@drawable/selector_gray_green_recent</item>
</style>
textcolor_black_white佈局:該文件位置放在res-color文件夾下,color是自己創建的一個文件夾。
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_focused="true" android:color="@color/white"></item>
<item android:state_checked="true" android:color="@color/white"></item>
<item android:state_pressed="true" android:color="@color/white"></item>
<item android:color="@color/black_light"/>
</selector>
selector_gray_green_recent:RadioButton點擊背景色
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 默認時的背景 -->
<item android:drawable="@drawable/gray_recent" android:state_checked="false"/>
<!-- 選擇時的背景 -->
<item android:drawable="@drawable/greenbg_recent" android:state_checked="true"/>
</selector>
gray_recent:正常狀態背景。<color name="gray_mid">#dbdbdb</color>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 填充的顏色 -->
<solid android:color="@color/white" />
<!-- 邊框寬度及顏色 -->
<stroke
android:width="2dp"
android:color="@color/gray_mid" />
<!-- 畫圓角 -->
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
</shape>
greenbg_recent:RadioButton被選中時候背景。<color name="stategridcolor">#00aa95</color> <!-- 國網色 -淺色-->
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 填充的顏色 -->
<solid android:color="@color/stategridcolor" />
<!-- 邊框寬度及顏色 -->
<stroke
android:width="2dp"
android:color="@color/stategridcolor" />
<!-- 畫圓角 -->
<corners
android:bottomLeftRadius="5dp"
android:bottomRightRadius="5dp"
android:topLeftRadius="5dp"
android:topRightRadius="5dp" />
</shape>
在Activity中使用,與其他控件一樣,進行實例化就行了。