Android自定義佈局-自動換行的RadioGroup

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中使用,與其他控件一樣,進行實例化就行了。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章