【问题标题】:Preparing customized radio group type of layout准备自定义无线电组类型的布局
【发布时间】:2013-12-08 17:12:28
【问题描述】:

我正在尝试在下图中准备自定义 radiogroup 布局。我有将近 8-10 行来做这件事。因此,我准备了一个水平方向的linear layout,并以编程方式添加了imageviewtextviewradiobutton

所以如果我选中一个radio button,其他单选按钮应该会自动取消选中。在执行该任务之前,我遇到了另一个问题,如果我的单选按钮被选中一次,那么即使单击了单选按钮,单选按钮也不是不可选中的。下面是我的代码。

public class MainActivity extends Activity{

RadioButton[] radioBtns = new RadioButton[10];

    String texts[] = {"text1", "text2", .... "text10"};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);


        entireLayout = (LinearLayout)findViewById(R.id.main_layout);


        for(int i =0; i<10; i++)
        {
            LinearLayout rowLayout=new LinearLayout(this);
            radioBtns[i] = new RadioButton(this);

            radioBtns[i].setId(i);
            radioBtns[i].setOnCheckedChangeListener(cblistener);
            ImageView imageView = new ImageView(this);


            TextView tv = new TextView(this);
            tv.setText(texts[i]);

            rowLayout.addView(imageView);
            rowLayout.addView(tv);
                        rowLayout.addView(radioBtns[i]);

            entireLayout.addView(rowLayout);

                View line = new View(this); 
                line.setBackgroundColor(getResources().getColor(R.color.horizontallinecolor));
                entireLayout.addView(line, new ViewGroup.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 1));


        }
         }

CompoundButton.OnCheckedChangeListener cblistener = new CompoundButton.OnCheckedChangeListener()
    {
      public void onCheckedChanged(CompoundButton checkedbutton, boolean paramAnonymousBoolean)
      {

        switch (checkedbutton.getId())
        {

        case 0:
          Log.d("tag", "checked 0th position");

          break;
          ..........................
          ..........................
        }
      }
     };
}

我通过记录日志观察到。控件在被选中时第一次进入 onCheckedChanged() ,但在未选中时则不会。我想知道这些是如何无法检查的。

根据我的要求,我还有一个想法来准备这个布局,就像我为 xml 中的行准备一个布局一样。然后将视图膨胀 10 次。但是,我怎样才能只检查一个单选按钮,以便取消选中其他选定的单选按钮。有人可以建议我如何通过最好的方式实现这种radiogroup吗?

注意:我保留上面的代码是为了展示我尝试过的内容。如果这是完全错误的方式,请放轻松,请建议我如何完成。

【问题讨论】:

  • 请把版面贴出来好吗?因此,要更轻松地了解您想要做什么。
  • @Klaus66 感谢您的评论。除了线性布局外,我在主布局中什么都没有。我所做的只是动态添加视图,这已经在我的上面的代码中了。我正在尝试实现图像中显示的内容。

标签: android radio-button radio-group


【解决方案1】:

根据我的经验,使用这些定制的 RadioGroup 有点麻烦。我已经为您准备了一些代码,这将是我解决您想要完成的事情的方法。希望它对你有用!

首先你必须在你的 onCreate() 中调用这个函数(或者在你创建视图的任何地方)

 private void addRadioButtons() {
    LinearLayout llGroup = (LinearLayout) findViewById(R.id.linearLayoutGroup);
    for(int i=0; i<10; i++){
        MyRadioButton mrb = new MyRadioButton(this);
        mrb.setText(String.valueOf(i));
        llGroup.addView(mrb.getView());
    }
}

类应该是

private static class MyRadioButton implements View.OnClickListener{

    private ImageView iv;
    private TextView tv;
    private RadioButton rb;
    private View view;

    public MyRadioButton(Context context) {

        view = View.inflate(context, R.layout.my_radio_button, null);
        rb = (RadioButton) view.findViewById(R.id.radioButton1);
        tv = (TextView) view.findViewById(R.id.textView1);
        iv = (ImageView) view.findViewById(R.id.imageView1);

        view.setOnClickListener(this);
        rb.setOnCheckedChangeListener(null);

    }


    public View getView() {
        return view;
    }

    @Override
    public void onClick(View v) {

        boolean nextState = !rb.isChecked();

        LinearLayout lGroup = (LinearLayout)view.getParent();
        if(lGroup != null){
            int child = lGroup.getChildCount();
            for(int i=0; i<child; i++){
                //uncheck all
                ((RadioButton)lGroup.getChildAt(i).findViewById(R.id.radioButton1)).setChecked(false);
            }
        }

        rb.setChecked(nextState);
    }

    public void setImage(Bitmap b){
        iv.setImageBitmap(b);
    }

    public void setText(String text){
        tv.setText(text);
    }

    public void setChecked(boolean isChecked){
        rb.setChecked(isChecked);
    }


}

以及要膨胀的 xml,类似于:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:gravity="center_vertical"
    android:orientation="horizontal" >
    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/ic_launcher" />
    <TextView
        android:id="@+id/textView1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="Medium Text"
        android:textAppearance="?android:attr/textAppearanceMedium" />
    <RadioButton
        android:id="@+id/radioButton1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</LinearLayout>

【讨论】:

  • 这段代码和我已经得到的一样。我的问题是,如果我曾经检查过单选按钮,该按钮不会被取消选中:(请提出建议。
  • +1 并接受您的回答。保持 clickable=false 就可以了。我也发布了答案。谢谢。
  • 这实际上在方向改变时会出现问题。你观察了吗?请提出建议。
  • xml 仅用于说明目的。您可以为纵向/横向模式提供不同的资源,为目标屏幕尺寸提供不同的尺寸等。您还必须了解活动中的 configChanges。问候。
  • 这与屏幕大小无关。改变方向时会泄漏资源。
【解决方案2】:

回答有点晚了,但我遇到了同样的问题,出于沮丧,我写了一个名为RadioGroupPlus 的新类来解决这个问题,我想分享一下。

回购可以在这里找到:https://github.com/worker8/RadioGroupPlus/

如何安装

在您的顶级build.gradle中添加库:

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

在您的 app/build.gradle 中,将其添加为依赖项:

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

如何使用

在您的 xml 中,使用 &lt;worker8.com.github.radiogroupplus.RadioGroupPlus 包装您的自定义布局,例如:

<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>

我故意省略了细节,以便更容易阅读。我在README 页面中写了更多关于如何使用RadioGroupPlus 的信息。此外,我还写了一个如何使用它的简单示例。所以如果你需要了解更多,可以在RadioGroupPlus repo了解更多。

希望对你有帮助!

【讨论】:

  • 当孩子是包含 RadioButtons 的自定义视图时,该库似乎不起作用,例如: ...
  • @EduBarbas,您的CustomRadioButton 是从RadioButton 扩展而来的吗?只有当CustomRadioButton 继承自RadioButton 时,它才应该起作用。看看RadioGroupPlus.java 中的traverseTree()。它这样做:view instanceof RadioButton。您可以尝试将RadioGroupPlus.java复制到您的项目中,并将文件中找到的全部 RadioButton更改为CustomRadioButton,我没有尝试过,但它可能会工作。
  • 我的自定义视图与此线程的开头问题中使用的非常相似 - 左侧是单选按钮,中间是一些文本,右侧是图像视图,只有一个细微差别:我在该自定义视图中使用数据绑定。我尝试将视图的布局直接添加到 中,并且工作正常。这会导致问题吗?
  • 忘了提及:我直接在 中添加了视图布局,没有数据绑定,并且工作正常。我会查看代码,看看是否能找到一些东西:-)
  • 哦,我明白了,因为我看不到它,所以看看代码找出自己会很棒。无论如何,如果你不能解决它,你可以在 Github 中分叉 repo 并将你的布局与 data binding 包含在另一个分支中,然后我也可以看看。我没有使用数据绑定的经验,所以我现在不确定出了什么问题。
【解决方案3】:

棘手的部分是您希望按钮在右侧
为此,我在每个按钮中删除了原始按钮将 Right drawable 设置为按钮
Left drawable 没什么好说的。

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffff"
    android:padding="8dp"
    >
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:padding="4dp"
        >
        <RadioGroup
            android:layout_gravity="center_horizontal"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/rgOne"
            >
            <RadioButton
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/rdo1"
                android:text="RadioButton 1"
                android:button="@null"
                android:drawableRight="@android:drawable/btn_radio"
                android:drawableLeft="@drawable/ic_launcher"
                android:checked="true"
                android:onClick="onRadioButtonClicked"
            />
            <RadioButton
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/rdo2"
                android:text="RadioButton 2"
                android:button="@null"
                android:drawableRight="@android:drawable/btn_radio"
                android:drawableLeft="@drawable/ic_launcher"
                android:onClick="onRadioButtonClicked"
            />
            <RadioButton
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:id="@+id/rdo3"
                android:text="RadioButton 3"
                android:button="@null"
                android:drawableRight="@android:drawable/btn_radio"
                android:drawableLeft="@drawable/ic_launcher"
                android:onClick="onRadioButtonClicked"
            />
        </RadioGroup>
    </RelativeLayout>
</RelativeLayout>

这是代码:

package com.example.aaa;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity
extends Activity
{

    @Override
    protected void onCreate(final Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // If you need to fire RadioButtonClick event:
        onRadioButtonClicked(findViewById(R.id.rdo1));
        // Otherwise, remove previous line
    }

    public final void onRadioButtonClicked(final View v)
    {
        String str = "1";
        switch(v.getId())
        {
            case R.id.rdo1:
            {
                // do something
                str = "1";
                break;
            }
            case R.id.rdo2:
            {
                // do something
                str = "2";
                break;
            }
            case R.id.rdo3:
            {
                // do something
                str = "3";
                break;
            }
            default:
            {
                // do something
                str = "that doesn' exist";
                break;
            }
        }
        Toast.makeText
        (
            getApplicationContext(), "RadioButton " + str, Toast.LENGTH_LONG
            ).show();
    }
}

【讨论】:

  • 感谢您的回答。我已经在问题中使用我的代码获得了该布局。但我的问题是,如果我曾经检查过单选按钮,该按钮不会被取消选中。
  • 如果你使用我的布局,检查会从一个单选按钮移动到另一个。也就是说,您永远不会在 RadioGroup 中拥有 COMPLETE EMPTYNESS(没有选中单选按钮)。尽管如此,您不会强制取消选中所有 RadioButtons(您在代码中创建一个循环并设置选中 = false)。
【解决方案4】:

编辑了布局删除了第二部分,这对您的目的毫无用处。
如果您查看布局,您会发现将按钮放在右侧的诀窍是什么。
如果您不想使用布局,这也可以在代码中进行(为什么?)
使用我的布局(不需要自定义类),你会得到的结果是......

与您的目标非常相似,不是吗?

您希望在代码中复制的棘手行(再次,为什么?)是:

android:button="@null"
android:drawableRight="@android:drawable/btn_radio" // or your selector, with custom on/off pngs
android:drawableLeft="@drawable/ic_launcher" // or whatever

【讨论】:

  • 非常感谢您的努力。我发布了我的答案。为您的两个答案+1 :)
  • 谢谢。我愿意尽我所能提供帮助。
【解决方案5】:

实现您的自定义 RadioGroup 类以满足您的要求并不难。您还可以实现自定义 RadioButton。定义自定义组件可以更轻松地扩展和绕过默认组件的限制。

我已经在this tutorial 中描述了创建自定义 RadioGroup 和自定义 RadioButton 的过程。我也上传了我的代码to Github

【讨论】:

    【解决方案6】:

    @Junior Buckeridge 的回答对我有用。我只想加上我的 2 美分。如果您的线性布局中有任何可点击的视图,请确保添加 android:descendantFocusability="blocksDescendants" 到您的线性布局和 android:focusable="false" 到您的视图(可以是按钮、单选按钮等)

    【讨论】:

      【解决方案7】:

      我的布局与您的相同,但在我的情况下,行数限制为四行。 我发现让 radioButtons 一起工作的最简单方法是使用简单的方法循环遍历 radioButtons 数组并检查 ALL 其中的 OFF 然后检查 ON the one 这是需要的。

      这就是所有人(c)

      您不需要使用常规 RadioGroup 也不需要创建自定义无线电组类,也不需要 setOnCheckChangedListeners。

          final RadioButton radio1 = (RadioButton) findViewById(R.id.radio_1);
          final RadioButton radio2 = (RadioButton) findViewById(R.id.radio_2);
          final RadioButton radio3 = (RadioButton) findViewById(R.id.radio_3);
          final RadioButton radio4 = (RadioButton) findViewById(R.id.radio_4);
      
          final RadioButton[] radios = {radio1, radio2, radio3, radio4};
      
          View.OnClickListener buttonListener = new View.OnClickListener(){
              @Override
              public void onClick(View v) {
                  for(RadioButton radio : radios){
                      radio.setChecked(false);
                  }
      
                  switch (v.getId()){
                      case R.id.button_1:
                          radio1.setChecked(true);
                          break;
                      case R.id.button_2:
                          radio2.setChecked(true);
                          break;
                      case R.id.button_3:
                          radio3.setChecked(true);
                          break;
                      case R.id.button_4:
                          radio4.setChecked(true);
                          break;
                  }
              }
          };
      
      
          RelativeLayout button1 = (RelativeLayout) findViewById(R.id.button_1);
          button1.setOnClickListener(buttonListener);
      
          RelativeLayout button2 = (RelativeLayout) findViewById(R.id.button_2);
          button2.setOnClickListener(buttonListener);
      
          RelativeLayout button3 = (RelativeLayout) findViewById(R.id.button_3);
          button3.setOnClickListener(buttonListener);
      
          RelativeLayout button4 = (RelativeLayout) findViewById(R.id.button_4);
          button4.setOnClickListener(buttonListener);
      

      *提示:别忘了设置

      android:text=""
      android:checked="false"
      android:clickable="false"
      

      到每个 RadioButton 的布局。并以编程方式为应该检查的单选按钮设置初始状态。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-10
        • 1970-01-01
        • 2017-02-15
        • 1970-01-01
        • 2020-12-26
        • 2016-11-12
        相关资源
        最近更新 更多