单选按钮的自定义布局

时间:2013-05-13 06:05:07

标签: android radio-button radio-group

有什么方法可以改变RadioButton的布局并且仍然让RadioGroup识别它吗?

我需要的是布局将包含几个EditText字段,以便当用户选择该按钮时这些字段变为活动状态。 我知道我可以基于LinearLayout构建自定义零件并使用以下方法设置我自己的布局: (LinearLayout)LayoutInflater.from(context).inflate(R.layout.my_layout,this,true) 但无法弄清楚如何用单选按钮做同样的事情。

我尝试过在RadioGroup之外添加额外字段并使用按钮排列它们的选项,但它根本不起作用。 它似乎与设备有关。

这就是原始布局的样子:

    <RadioGroup
    android:id="@+id/time_selector_radio_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_hours_prompt"
    android:layout_below="@id/time_selector_hours_prompt"
    android:layout_alignParentRight="true"
    android:gravity="right"
    android:orientation="vertical"
    android:checkedButton="@+id/time_selector_first_radio"
    >

    <RadioButton
        android:id="@+id/time_selector_first_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />
    <RadioButton
        android:id="@+id/time_selector_second_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />
    <RadioButton
        android:id="@+id/time_selector_third_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />
    <RadioButton
        android:id="@+id/time_selector_hours_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@drawable/radio_button_selector"
        />

</RadioGroup>
<TextView
    android:id="@+id/time_selector_all_day_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_radio_group"
    android:layout_below="@id/time_selector_hours_prompt"
    android:layout_marginTop="11dip"
    android:text="@string/time_all_day"
    />
<TextView
    android:id="@+id/time_selector_before_noon_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_radio_group"
    android:layout_below="@id/time_selector_all_day_prompt"
    android:layout_marginTop="19dip"
    android:text="@string/time_before_noon"
    />
<TextView
    android:id="@+id/time_selector_after_noon_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_radio_group"
    android:layout_below="@id/time_selector_before_noon_prompt"
    android:layout_marginTop="19dip"
    android:text="@string/time_after_noon"
    />
<TextView
    android:id="@+id/time_selector_starting_time_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_starting_date_prompt"
    android:layout_below="@id/time_selector_after_noon_prompt"
    android:layout_marginTop="20dip"
    android:layout_marginLeft="2dip"
    android:text="@string/advanced_time_selector_dialog_starting_time_prompt"
    />
<EditText
    android:id="@+id/time_selector_starting_time"
    android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_starting_date"
    android:layout_alignBaseline="@id/time_selector_starting_time_prompt"
    android:textSize="14sp"
    android:paddingRight="10dip"
    android:paddingLeft="10dip"
    android:gravity="center"
    android:singleLine="true"
    android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
    android:background="@drawable/text_field_bg"
    android:inputType="datetime"
    />
<TextView
    android:id="@+id/time_selector_ending_time_prompt"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_ending_date_prompt"
    android:layout_alignBottom="@id/time_selector_starting_time_prompt"
    android:layout_alignBaseline="@id/time_selector_starting_time_prompt"
    android:layout_marginRight="2dip"
    android:layout_marginLeft="2dip"
    android:text="@string/ending_date_prompt"
    />
<EditText
    android:id="@+id/time_selector_ending_time"
    android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
    android:layout_height="wrap_content"
    android:layout_alignRight="@id/time_selector_ending_date"
    android:layout_alignBaseline="@id/time_selector_ending_time_prompt"
    android:textSize="14sp"
    android:paddingRight="10dip"
    android:paddingLeft="10dip"
    android:gravity="center"
    android:singleLine="true"
    android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
    android:background="@drawable/text_field_bg"
    android:inputType="datetime"
    />

请注意,该按钮没有任何文本,它会添加到TextView中,以便我们可以将其放在左侧。 发生的事情是文本正在“爬行”。

所以,我改变它看起来像这样:

<RadioGroup
    android:id="@+id/time_selector_radio_group"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_toLeftOf="@id/time_selector_hours_prompt"
    android:layout_below="@id/time_selector_hours_prompt"
    android:layout_alignParentRight="true"
    android:layout_marginRight="30dip"
    android:gravity="right"
    android:orientation="vertical"
    android:checkedButton="@+id/time_selector_first_radio"
    >

    <RadioButton
        android:id="@+id/time_selector_all_day_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@null"
        android:drawableRight="@drawable/radio_button_selector"
        android:text="@string/time_all_day"
        android:textColor="@color/content_text_color"
        />
    <RadioButton
        android:id="@+id/time_selector_before_noon_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@null"
        android:drawableRight="@drawable/radio_button_selector"
        android:text="@string/time_before_noon"
        android:textColor="@color/content_text_color"
        />

    <RadioButton
        android:id="@+id/time_selector_after_noon_radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="1dip"
        android:button="@null"
        android:drawableRight="@drawable/radio_button_selector"
        android:text="@string/time_after_noon"
        android:textColor="@color/content_text_color"
        />

    <RelativeLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">   
        <RadioButton
            android:id="@+id/time_selector_hours_radio"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginTop="1dip"
            android:button="@null"
            android:drawableRight="@drawable/radio_button_selector"
            android:layout_alignParentRight="true"
            android:text="@string/advanced_time_selector_dialog_starting_time_prompt"
            android:textColor="@color/content_text_color"
            android:layout_marginLeft="-1dip"
            android:paddingLeft="-1dip"
            />  
        <RelativeLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_toLeftOf="@id/time_selector_hours_radio"
            android:layout_alignParentLeft="true">            
            <EditText
                android:id="@+id/time_selector_starting_time"
                android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:paddingRight="10dip"
                android:paddingLeft="10dip"
                android:gravity="center"
                android:singleLine="true"
                android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
                android:background="@drawable/text_field_bg"
                android:layout_alignParentRight="true"
                android:layout_alignBaseline="@id/time_selector_hours_radio"
                android:inputType="datetime"
                />
            <TextView
                android:id="@+id/time_selector_ending_time_prompt"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginRight="2dip"
                android:layout_marginLeft="2dip"
                android:text="@string/ending_date_prompt"
                android:layout_alignBaseline="@id/time_selector_hours_radio"
                android:layout_toLeftOf="@id/time_selector_starting_time"
                />
            <EditText
                android:id="@+id/time_selector_ending_time"
                android:layout_width="@dimen/advanced_time_selector_edit_texts_width"
                android:layout_height="wrap_content"
                android:textSize="14sp"
                android:paddingRight="10dip"
                android:paddingLeft="10dip"
                android:gravity="center"
                android:singleLine="true"
                android:maxWidth="@dimen/advanced_time_selector_edit_texts_width"
                android:layout_toLeftOf="@id/time_selector_ending_time_prompt"
                android:layout_alignBaseline="@id/time_selector_hours_radio"
                android:background="@drawable/text_field_bg"
                android:inputType="datetime"
                />
        </RelativeLayout>
    </RelativeLayout>

</RadioGroup>

它仍然不完美,当然,它不承认它是一个RadioGroup。

我想继续扩展RadioButton的方向,但不知道如何更改那里的布局。

3 个答案:

答案 0 :(得分:8)

我写了一个名为RadioGroup的自定义RadioGroupPlus,它将遍历它的子项并找到RadioButton,无论RadioButton嵌套的深度如何,它都将链接所有RadioButton一起找到了。

您可以在此处找到回购:https://github.com/worker8/RadioGroupPlus

回购的README涵盖了如何使用它,它实际上就像你想象的那样,例如:

<worker8.com.github.radiogroupplus.RadioGroupPlus
    android:id="@+id/radio_group_plus"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">
    <LinearLayout...>
       <ImageView...>
       <TextView...>
       <RadioButton...>
    </LinearLayout>
    <LinearLayout...>
       <ImageView...>
       <TextView...>
       <RadioButton...>
    </LinearLayout>
    <LinearLayout...>
       <ImageView...>
       <TextView...>
       <RadioButton...>
    </LinearLayout>
</worker8.com.github.radiogroupplus.RadioGroupPlus>

会给你这样的东西:

在您的情况下,由于您已经拥有xml布局文件,请尝试按照guide here下载RadioGroupPlus

将此添加到顶级build.gradle:

allprojects {
    repositories {
        maven { url "https://jitpack.io" }
    }
}

在依赖项下添加:

compile 'com.github.worker8:RadioGroupPlus:v1.0.1'

然后在您的xml中,将RadioGroup更改为worker8.com.github.radiogroupplus.RadioGroupPlus。现在,RadioButton下的所有RadioGroupPlus都应该链接在一起。

希望它有所帮助!

答案 1 :(得分:4)

您必须创建扩展RadioGroup的类,并覆盖 addView PassThroughHierarchyChangeListener ,才能使用自定义布局你的单选按钮。默认情况下,RadioGroup假定其子节点是单选按钮,请参阅RadioGroup类中的以下代码:

@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);
}

private class PassThroughHierarchyChangeListener implements
        ViewGroup.OnHierarchyChangeListener {
    private ViewGroup.OnHierarchyChangeListener mOnHierarchyChangeListener;

    /**
     * {@inheritDoc}
     */
    public void onChildViewAdded(View parent, View child) {
        if (parent == RadioGroup.this && child instanceof RadioButton) {
            int id = child.getId();
            // generates an id if it's missing
            if (id == View.NO_ID) {
                id = View.generateViewId();
                child.setId(id);
            }
            ((RadioButton) child).setOnCheckedChangeWidgetListener(
                    mChildOnCheckedChangeListener);
        }

        if (mOnHierarchyChangeListener != null) {
            mOnHierarchyChangeListener.onChildViewAdded(parent, child);
        }
    }

    /**
     * {@inheritDoc}
     */
    public void onChildViewRemoved(View parent, View child) {
        if (parent == RadioGroup.this && child instanceof RadioButton) {
            ((RadioButton) child).setOnCheckedChangeWidgetListener(null);
        }

        if (mOnHierarchyChangeListener != null) {
            mOnHierarchyChangeListener.onChildViewRemoved(parent, child);
        }
    }
}

答案 2 :(得分:1)

这个问题可能已经有十年了,但我放弃它是为了帮助陷入这种情况的其他人。

我使用 TextView 代替 Radio Button创建一个类来将它们分组,它可能是旧风格,但我发现它对我来说是最优雅和灵活的方式.

TextView 布局的 XML:

<RelativeLayout...>
    <TextView... android:id="@+id/o1">
    <TextView... android:id="@+id/o2">
    <ImageView...>
    <TextView... android:id="@+id/o3">
    <TextView... android:id="@+id/o4">
</RelativeLayout>

ButtonGroup.java

import java.util.ArrayList;
...

public class ButtonGroup {
    ArrayList<TextView> mOptions;
    int cur=0;
    int colorOn = Color.BLUE;
    int colorOff = Color.GRAY;
    ButtonGroup(ArrayList<TextView> options) {
        mOptions = options;
    }

    public void turnOn(int i){
        if(i!=cur){
            TextView pre = mOptions.get(cur);
            pre.setTextColor(colorOff);
            cur=i;
        }

        TextView next = mOptions.get(i);
        next.setTextColor(colorOn);
    }
}

Activity的onCreate方法:

protected void onCreate(Bundle savedInstanceState) {
    int current = 0;
    ArrayList<TextView> optionList = new ArrayList<>();
    optionList.add((TextView) findViewById(R.id.o1));
    optionList.add((TextView) findViewById(R.id.o2));
    optionList.add((TextView) findViewById(R.id.o3));
    optionList.add((TextView) findViewById(R.id.o4));
    ButtonGroup options = new ButtonGroup(optionList);
    options.turnOn(current);
}

它会给出类似的东西

enter image description here