答案 0 :(得分:3)
我创建了自己的RadioGridLayout,其中包括RadioGroup代码并扩展了GridLayout。 您可以复制此代码。对我来说,工作做得很好。 之后,您可以在xml中使用此布局并像网格布局一样自定义。
对于R.styleable.RadioGridLayout_checked,我使用了如下代码:
<resources>
<declare-styleable name="RadioGridLayout">
<attr name="checked" format="integer" />
</declare-styleable>
</resources>
public class RadioGridLayout extends GridLayout {
private int mCheckedId = -1;
private CompoundButton.OnCheckedChangeListener mChildOnCheckedChangeListener;
private boolean mProtectFromCheckedChange = false;
private OnCheckedChangeListener mOnCheckedChangeListener;
private PassThroughHierarchyChangeListener mPassThroughListener;
private void setCheckedId(@IdRes int id) {
mCheckedId = id;
if (mOnCheckedChangeListener != null) {
mOnCheckedChangeListener.onCheckedChanged(this, mCheckedId);
}
AutofillManager afm = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
afm = getContext().getSystemService(AutofillManager.class);
}
if (afm != null) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
afm.notifyValueChanged(this);
}
}
}
public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
mOnCheckedChangeListener = listener;
}
public interface OnCheckedChangeListener {
void onCheckedChanged(RadioGridLayout group, @IdRes int checkedId);
}
private int mInitialCheckedId = View.NO_ID;
public RadioGridLayout(Context context) {
super(context);
setOrientation(VERTICAL);
init();
}
public RadioGridLayout(Context context, AttributeSet attrs) {
super(context, attrs);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (getImportantForAutofill() == IMPORTANT_FOR_AUTOFILL_AUTO) {
setImportantForAutofill(IMPORTANT_FOR_AUTOFILL_YES);
}
}
TypedArray attributes = context.obtainStyledAttributes(
attrs,
R.styleable.RadioGridLayout,
R.attr.radioButtonStyle, 0);
int value = attributes.getResourceId(R.styleable.RadioGridLayout_checked, View.NO_ID);
if (value != View.NO_ID) {
mCheckedId = value;
mInitialCheckedId = value;
}
attributes.recycle();
init();
}
private void init() {
mChildOnCheckedChangeListener = new CheckedStateTracker();
mPassThroughListener = new PassThroughHierarchyChangeListener();
super.setOnHierarchyChangeListener(mPassThroughListener);
}
@Override
public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
mPassThroughListener.mOnHierarchyChangeListener = listener;
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
if (mCheckedId != -1) {
mProtectFromCheckedChange = true;
setCheckedStateForView(mCheckedId, true);
mProtectFromCheckedChange = false;
setCheckedId(mCheckedId);
}
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (child instanceof RadioButton) {
final RadioButton button = (RadioButton) child;
if (button.isChecked()) {
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
setCheckedId(button.getId());
}
}
super.addView(child, index, params);
}
public void check(@IdRes int id) {
if (id != -1 && (id == mCheckedId)) {
return;
}
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
if (id != -1) {
setCheckedStateForView(id, true);
}
setCheckedId(id);
}
private void setCheckedStateForView(int viewId, boolean checked) {
View checkedView = findViewById(viewId);
if (checkedView != null && checkedView instanceof RadioButton) {
((RadioButton) checkedView).setChecked(checked);
}
}
@IdRes
public int getCheckedRadioButtonId() {
return mCheckedId;
}
public void clearCheck() {
check(-1);
}
@Override
public GridLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
return new GridLayout.LayoutParams(getContext(), attrs);
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
return p instanceof RadioGroup.LayoutParams;
}
@Override
protected GridLayout.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams();
}
@Override
public CharSequence getAccessibilityClassName() {
return RadioGroup.class.getName();
}
public static class LayoutParams extends GridLayout.LayoutParams {
public LayoutParams(Spec rowSpec, Spec columnSpec) {
super(rowSpec, columnSpec);
}
public LayoutParams() {
super();
}
public LayoutParams(ViewGroup.LayoutParams params) {
super(params);
}
public LayoutParams(MarginLayoutParams params) {
super(params);
}
public LayoutParams(GridLayout.LayoutParams source) {
super(source);
}
public LayoutParams(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void setBaseAttributes(TypedArray a,
int widthAttr, int heightAttr) {
if (a.hasValue(widthAttr)) {
width = a.getLayoutDimension(widthAttr, "layout_width");
} else {
width = WRAP_CONTENT;
}
if (a.hasValue(heightAttr)) {
height = a.getLayoutDimension(heightAttr, "layout_height");
} else {
height = WRAP_CONTENT;
}
}
}
private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (mProtectFromCheckedChange) {
return;
}
mProtectFromCheckedChange = true;
if (mCheckedId != -1) {
setCheckedStateForView(mCheckedId, false);
}
mProtectFromCheckedChange = false;
int id = buttonView.getId();
setCheckedId(id);
}
}
private class PassThroughHierarchyChangeListener implements
ViewGroup.OnHierarchyChangeListener {
private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;
@Override
public void onChildViewAdded(View parent, View child) {
if (parent == RadioGridLayout.this && child instanceof RadioButton) {
int id = child.getId();
if (id == View.NO_ID) {
id = View.generateViewId();
child.setId(id);
}
((RadioButton) child).setOnCheckedChangeListener(
mChildOnCheckedChangeListener);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewAdded(parent, child);
}
}
@Override
public void onChildViewRemoved(View parent, View child) {
if (parent == RadioGridLayout.this && child instanceof RadioButton) {
((RadioButton) child).setOnCheckedChangeListener(null);
}
if (mOnHierarchyChangeListener != null) {
mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
}
}
}
@Override
public void onProvideAutofillStructure(ViewStructure structure, int flags) {
super.onProvideAutofillStructure(structure, flags);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
structure.setDataIsSensitive(mCheckedId != mInitialCheckedId);
}
}
@Override
public void autofill(AutofillValue value) {
if (!isEnabled()) return;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (!value.isList()) {
Timber.w(value + " could not be autofilled into " + this);
return;
}
}
int index = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
index = value.getListValue();
}
final View child = getChildAt(index);
if (child == null) {
Timber.w("RadioGroup.autoFill(): no child with index %s", index);
return;
}
check(child.getId());
}
@Override
public int getAutofillType() {
return isEnabled() ? AUTOFILL_TYPE_LIST : AUTOFILL_TYPE_NONE;
}
@Override
public AutofillValue getAutofillValue() {
if (!isEnabled()) return null;
final int count = getChildCount();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getId() == mCheckedId) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
return AutofillValue.forList(i);
}
}
}
return null;
}
}
答案 1 :(得分:1)
创建两个radio group.one用于第一行,另一个用于第二行。然后在java代码中添加以下代码
mFirstGroup = (RadioGroup) findViewById(R.id.first_group);
mSecondGroup = (RadioGroup) findViewById(R.id.second_group);
mFirstGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId != -1 && isChecking) {
isChecking = false;
mSecondGroup.clearCheck();
mCheckedId = checkedId;
}
isChecking = true;
}
});
mSecondGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(RadioGroup group, int checkedId) {
if (checkedId != -1 && isChecking) {
isChecking = false;
mFirstGroup.clearCheck();
mCheckedId = checkedId;
}
isChecking = true;
}
});
答案 2 :(得分:1)
@Suhail k k描述了一种可能的解决方案 还看一下here(回答@Suhail k k的详细信息。)。
我可以提出另一个选择:
1)让你自己的视图(例如ImageView)并在你的布局中放置它们;在每个上放置android:标签(序列号,例如,从0到7);
2)为每个选择器制作选择器(状态正常/选择);
3)在运行时将onClickListener
放在这些项目上如下:
@Override
public void onClick(View v) {
images.get(currentSelected).setSelected(false);
currentSelected = (int) v.getTag();
images.get(currentSelected).setSelected(true);
}
你可以更容易地实施,imho。
希望你总有一个想法,你的实现可能会有所不同:)