自定义多行选择器SelectorGroup 代码如下:
package com.example.myapplication;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.widget.ImageView;
import android.widget.RadioButton;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.IdRes;
/**
* 自定义多行选择器,RadioGroup只能单行单列显示,用此自定义SelectorGroup来多行显示子项
*/
public class SelectorGroup extends RelativeLayout {
private int columnCount; //列数
private int horizontalSpace; //左右边距
private int verticalSpace; //上下边距
private boolean customLayout; //是否自定义子View位置,否则用RelativeLayout的位置
private int mCheckedId;
private OnCheckedChangeListener mOnCheckedChangeListener;
public SelectorGroup(Context context) {
this(context, null);
}
public SelectorGroup(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SelectorGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SelectorGroup);
columnCount = typedArray.getInteger(R.styleable.SelectorGroup_columnCount, -1);
horizontalSpace = typedArray.getDimensionPixelOffset(R.styleable.SelectorGroup_horizontalSpace,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));
verticalSpace = typedArray.getDimensionPixelOffset(R.styleable.SelectorGroup_verticalSpace,
(int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 0, getResources().getDisplayMetrics()));
customLayout = typedArray.getBoolean(R.styleable.SelectorGroup_custom, false);
typedArray.recycle();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
setCheckedId(view.getId());
}
});
}
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!customLayout) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (i > 0) {
RelativeLayout.LayoutParams layoutParams = (LayoutParams) child.getLayoutParams();
if (columnCount <= 0 || i % columnCount != 0) {
layoutParams.addRule(RelativeLayout.END_OF, getChildAt(i - 1).getId());
layoutParams.setMarginStart(horizontalSpace);
}
if (columnCount > 0 && i >= columnCount) {
layoutParams.addRule(RelativeLayout.BELOW, getChildAt(i - columnCount).getId());
layoutParams.topMargin = verticalSpace;
}
child.setLayoutParams(layoutParams);
}
}
}
}
private void setCheckedId(@IdRes int checkedId) {
mCheckedId = checkedId;
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
if (view instanceof RadioButton) {
((RadioButton) view).setChecked(view.getId() == checkedId);
}
view.setSelected(view.getId() == checkedId);
if (view.getId() == checkedId && mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChange(SelectorGroup.this, checkedId, i);
}
}
}
public void setTextArrays(String[] arrays) {
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
if (view instanceof RadioButton && arrays.length > i) {
((RadioButton) view).setText(arrays[i]);
} else if (view instanceof TextView && arrays.length > i) {
((TextView) view).setText(arrays[i]);
}
}
}
public void setImageResourceArrays(int[] resIds) {
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
if (view instanceof ImageView && resIds.length > i) {
((ImageView) view).setImageResource(resIds[i]);
}
}
}
public void setSelectedIndex(int index) {
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
view.setSelected(i == index);
}
}
public int getSelectedIndex() {
for (int i = 0; i < getChildCount(); i++) {
final View view = getChildAt(i);
if (view.isSelected()) {
return i;
}
}
return -1;
}
public void clearSelect() {
setCheckedId(-1);
}
public void selectId(@IdRes int checkedId) {
if (checkedId != -1 && checkedId != mCheckedId) {
setCheckedId(checkedId);
}
}
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
}
public interface OnCheckedChangeListener {
void onCheckedChange(SelectorGroup selectorGroup, @IdRes int checkedId, int index);
}
}
自定义View的属性attrs.xml的代码如下:
<declare-styleable name="SelectorGroup">
<!--是否自定义子View位置-->
<attr name="custom" format="boolean"/>
<!--列数-->
<attr name="columnCount" format="integer"/>
<!--左右边距-->
<attr name="horizontalSpace" format="dimension"/>
<!--上下边距-->
<attr name="verticalSpace" format="dimension"/>
</declare-styleable>
布局文件的代码如下:
<com.example.myapplication.SelectorGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
app:custom="false"
app:columnCount="3"
app:horizontalSpace="10dp"
app:verticalSpace="10dp">
<TextView
android:id="@+id/tv_test1"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@drawable/text_bg_selector"
android:gravity="center"
android:text="测试文本1"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_test2"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@drawable/text_bg_selector"
android:gravity="center"
android:text="测试文本2"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_test3"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@drawable/text_bg_selector"
android:gravity="center"
android:text="测试文本3"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_test4"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@drawable/text_bg_selector"
android:gravity="center"
android:text="测试文本4"
android:textColor="@android:color/white" />
<TextView
android:id="@+id/tv_test5"
android:layout_width="100dp"
android:layout_height="60dp"
android:background="@drawable/text_bg_selector"
android:gravity="center"
android:text="测试文本5"
android:textColor="@android:color/white" />
</com.example.myapplication.SelectorGroup>
其中custom属性代码是否选哟自定义子View位置(默认为false),为true时自定义子View边距和位置,相当于RelativeLayout 嵌套的使用;为false时采用columnCount、horizontalSpace、verticalSpace属性来设置列数和边距。
cutom为false,columeCount不设置或小于等于0时效果如下:
cutom为false,columeCount为3时效果如下: