RadioButton'ı farklı LinearLayouts'tan nasıl gruplayabilirim?


93

Her birini aynı yapıyı koruyarak RadioButtonbenzersiz bir şekilde gruplamanın mümkün olup olmadığını merak ediyordum RadioGroup. Yapım şuna benziyor:

  • LinearLayout_main
    • LinearLayout_1
      • RadioButton1
    • LinearLayout_2
      • RadioButton2
    • LinearLayout_3
      • RadioButton3

Gördüğünüz gibi, şimdi her RadioButtonbiri farklı bir çocuk LinearLayout. Aşağıdaki yapıyı kullanmayı denedim ama çalışmıyor:

  • Radiogroup
    • LinearLayout_main
      • LinearLayout_1
        • RadioButton1
      • LinearLayout_2
        • RadioButton2
      • LinearLayout_3
        • RadioButton3

14
@coding crow, sormak zorunda kalırsanız, UI akışı için hiç bir tasarımcıyla çalışmadınız (ve radyo düğmelerinizin muhtemelen çok karmaşık olmadığını tahmin ediyorum). Biri başlık ve diğeri alt metin olmak üzere iki metin parçasının yanında duran bir radyo düğmesini (yapabiliyorsanız) hayal edin. Şimdi bunlardan 5 tanesini üst üste hayal edin. Bunu nasıl başarırsınız? Ah doğru ... yapamazsın. Bu kadar süslü hiçbir şeye ihtiyaç duyulmaması iyi bir şeydir veya google, aksi takdirde kapsamlı düzen araç setinde bu kadar temel düzen işlevini gözden kaçırdığı için gerçekten aptal görünecektir.
Yevgeny Simkin

3
@ DrDredel vay, ne dediğine (radioButtons kullanımı) katılıyorum, ama belki tepkiniz çok duygusal oldu? :)
infografnet

14
Duygusal değildi, açıkça sinir bozucu değildi. Bu yorum OP'ye ne sunuyor? Genel olarak konuya ne sunuyor? Sorunun değersiz, sabırsız ve alaycı olduğunu ima ediyor. "Bunu neden yapmak isteyeceğinizi lütfen açıklar mısınız" diye başlatmış olsaydı, bu hem uygun hem de kibar olurdu. "Sormaya zorlandım", "ne tür bir salağın bu tuhaf kluge'a ihtiyacı olur?" A ince örtülü bir alternatiftir. En azından ben öyle okudum.
Yevgeny Simkin

1
Android devi neden hala RadioGroup içinde LinearLayout kullanımına izin vermiyor? Marshmallow yayınlandı.
Shan Xeeshi

1
Hala doğru cevap yok mu? Bir çözüm arıyordum
neena

Yanıtlar:


49

Görünüşe göre Google / Android'deki iyi insanlar, RadioButtons'u kullandığınızda, Android kullanıcı arayüzü / düzen sisteminin diğer tüm yönleriyle gelen esnekliğe ihtiyacınız olmadığını varsayıyorlar. Basitçe söylemek gerekirse: düzenleri ve radyo düğmelerini iç içe geçirmenizi istemiyorlar. İç çekmek.

Bu yüzden problemi çözmelisin. Bu, radyo düğmelerini kendi başınıza uygulamanız gerektiği anlamına gelir.

Bu gerçekten çok zor değil. OnCreate () öğenizde, RadioButton'larınızı kendi onClick () ile ayarlayın, böylece etkinleştirildiklerinde, diğer düğmeler içinChecked (true) değerini ayarlarlar ve tam tersini yaparlar. Örneğin:

class FooActivity {

    RadioButton m_one, m_two, m_three;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        m_one = (RadioButton) findViewById(R.id.first_radio_button);
        m_two = (RadioButton) findViewById(R.id.second_radio_button);
        m_three = (RadioButton) findViewById(R.id.third_radio_button);

        m_one.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(true);
                m_two.setChecked(false);
                m_three.setChecked(false);
            }
        });

        m_two.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(false);
                m_two.setChecked(true);
                m_three.setChecked(false);
            }
        });

        m_three.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
                m_one.setChecked(false);
                m_two.setChecked(false);
                m_three.setChecked(true);
            }
        });

        ...     
    } // onCreate() 

}

Evet, biliyorum - eski usul. Ama işe yarıyor. İyi şanslar!


34
çıldırtan. Bunun bir "radyo düğmesi" kadar sıradan bir şey yapmak için gerekli olan klugery seviyesi olması sadece inanılmaz. Google'ın bize neredeyse tamamen yararsız olan şeyler için (Animasyonlar widget'ının% 80'i gibi) çok sayıda kısa yol sağladığına ve ardından kendi radyo düğmelerimizi bir araya getirmemize izin verdiğine inanılamayacak kadar çok. (tükürmek!).
Yevgeny Simkin

3
@ Dr.Dredel: Evet, birçok UI seçiminin tuhaf olduğuna katılıyorum . Bu sınırlama hakkındaki tek tahminim, "Bunu elle yapmak gerçekten o kadar da zor değil" diye düşünüyor olabilirler. Ancak bu özellik eksikliğini en azından biraz (bir eğitim sayfası gibi?) Belgeleseler iyi olurdu. Sizin de belirttiğiniz gibi, diğer neredeyse işe yaramaz şeylerde (evcil hayvan projeleri, belki?) Denize düştüler.
SMBiggs

3
Sadece tahmin edebilirim, ancak genel izlenimim, Android'in kullanıcı arayüzü ekibinin ya kısa süreliğine ya da genel olarak oldukça zayıf olduğu yönünde. Google evreninde neyin "zarif" olduğunu düşünün. Hepsi gerçekten spartan ve faydacı. Apple hayranı değilim çünkü stil yerine işlevselliği tercih ederim, ancak görünüşünü ve hissini yeniden düşünmek için para yığınları olan bir mega şirkete ihtiyaç duyarsa (zincir boyunca) Google.
Yevgeny Simkin

1
Bu, şimdiye kadarki en güvenilir ve basit çözümlerden biri ... tarih öncesi olmasına rağmen, Google'ın daha verimli bir şey uygulamaması utanç verici ...
TV

3
Evet .. Radyo düğmesi kimliklerini manuel olarak Radyo Grubuna atamak gibi bir şey bekliyordum ya da radyo grubu içinde radyo düğmeleri içermeyen ekstra görüntüleme gruplarında otomatik geçişin maliyeti yüksek olsaydı bir şey olurdu .. bu var, bu yüzden aramaya başladım. Şimdi bu görevi çaresizlik içinde bırakıyorum.
Dreamingwhale

28

Oluşturduğum bu sınıfı kullan. Hiyerarşinizdeki tüm kontrol edilebilir çocukları bulacaktır.

import java.util.ArrayList;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class MyRadioGroup extends LinearLayout {

private ArrayList<View> mCheckables = new ArrayList<View>();

public MyRadioGroup(Context context) {
    super(context);
}

public MyRadioGroup(Context context, AttributeSet attrs) {
    this(context, attrs, 0);
}

public MyRadioGroup(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
}

@Override
public void addView(View child, int index,
        android.view.ViewGroup.LayoutParams params) {
    super.addView(child, index, params);
    parseChild(child);
}

public void parseChild(final View child)
{
    if(child instanceof Checkable)
    {
        mCheckables.add(child);
        child.setOnClickListener(new OnClickListener() {

            public void onClick(View v) {
                for(int i = 0; i < mCheckables.size();i++)
                {
                    Checkable view = (Checkable) mCheckables.get(i);
                    if(view == v)
                    {
                        ((Checkable)view).setChecked(true);
                    }
                    else
                    {
                        ((Checkable)view).setChecked(false);
                    }
                }
            }
        });
    }
    else if(child instanceof ViewGroup)
    {
        parseChildren((ViewGroup)child);
    }
}

public void parseChildren(final ViewGroup child)
{
    for (int i = 0; i < child.getChildCount();i++)
    {
        parseChild(child.getChildAt(i));
    }
}
}

bu kod verildiğinde, mevcut seçili düğmeyi nasıl alırım?
j2emanue

((Kontrol edilebilir) görünümü) .setChecked (true) ayarladığınızda bir değişken mCheckedview koydum; ve hangisinin kontrol edildiğini bilmem gerektiğinde bu değişkeni iade ediyorum. şimdi iyi görünüyor ancak varsayılan olarak "performClick ()" yapmam gerekiyor. teşekkürler
j2emanue

17

Ben bu basit dersi yazdım.

Sadece şu şekilde kullanın:

// add any number of RadioButton resource IDs here
GRadioGroup gr = new GRadioGroup(this, 
    R.id.radioButton1, R.id.radioButton2, R.id.radioButton3);

veya

GRadioGroup gr = new GRadioGroup(rb1, rb2, rb3);
// where RadioButton rb1 = (RadioButton) findViewById(R.id.radioButton1);
// etc.

Örneğin onCreate () Aktivite içinde çağırabilirsiniz. Hangisini RadioButtontıklarsanız tıklayın, diğerleri kontrol edilmeyecek. Ayrıca, bazıları bazılarının içinde RadioButtonsise önemli değilRadioGroup değil.

İşte sınıf:

package pl.infografnet.GClasses;

import java.util.ArrayList;
import java.util.List;

import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewParent;
import android.widget.RadioButton;
import android.widget.RadioGroup;

public class GRadioGroup {

    List<RadioButton> radios = new ArrayList<RadioButton>();

    /**
     * Constructor, which allows you to pass number of RadioButton instances,
     * making a group.
     * 
     * @param radios
     *            One RadioButton or more.
     */
    public GRadioGroup(RadioButton... radios) {
        super();

        for (RadioButton rb : radios) {
            this.radios.add(rb);
            rb.setOnClickListener(onClick);
        }
    }

    /**
     * Constructor, which allows you to pass number of RadioButtons 
     * represented by resource IDs, making a group.
     * 
     * @param activity
     *            Current View (or Activity) to which those RadioButtons 
     *            belong.
     * @param radiosIDs
     *            One RadioButton or more.
     */
    public GRadioGroup(View activity, int... radiosIDs) {
        super();

        for (int radioButtonID : radiosIDs) {
            RadioButton rb = (RadioButton)activity.findViewById(radioButtonID);
            if (rb != null) {
                this.radios.add(rb);
                rb.setOnClickListener(onClick);
            }
        }
    }

    /**
     * This occurs everytime when one of RadioButtons is clicked, 
     * and deselects all others in the group.
     */
    OnClickListener onClick = new OnClickListener() {

        @Override
        public void onClick(View v) {

            // let's deselect all radios in group
            for (RadioButton rb : radios) {

                ViewParent p = rb.getParent();
                if (p.getClass().equals(RadioGroup.class)) {
                    // if RadioButton belongs to RadioGroup, 
                    // then deselect all radios in it 
                    RadioGroup rg = (RadioGroup) p;
                    rg.clearCheck();
                } else {
                    // if RadioButton DOES NOT belong to RadioGroup, 
                    // just deselect it
                    rb.setChecked(false);
                }
            }

            // now let's select currently clicked RadioButton
            if (v.getClass().equals(RadioButton.class)) {
                RadioButton rb = (RadioButton) v;
                rb.setChecked(true);
            }

        }
    };

}

1
Güzel. RadioButton'ı süper sınıf CompoundButton ile değiştirirseniz, daha sonra gruba değiştirilebilir düğmeler (ToggleButton gibi) ekleyebileceğiniz için daha da iyidir!
Neromancer

1
Radyo düğmeleri doğrudan radyo grubuna yerleştirilmemişse, normal radyo grubunuzdan getCheckedRadioButtonId () işlevini gerçekleştirmenin artık çalışmayacağını (her zaman -1 döndürür) belirtmek gerekir. Yukarıdaki sınıfa aşağıdaki gibi başka bir yöntem ekledim: `/ ** * İşaretlenen radyo düğmesinin kimliğini veya hiçbiri işaretlenmemişse -1 döndürür * @return * / public int getCheckedRadioButtonId () {int checkedId = -1; // (RadioButton rb: radios) için her radyo düğmesini döngüye al {if (rb.isChecked ()) {return rb.getId (); }} dönüş checkId; } `
sham

15

İşte benim çözümüm @lostdev çözümüne ve RadioGroup. Alt düzenlerin içine yerleştirilmiş RadioButtons (veya diğer CompoundButtons) ile çalışmak üzere değiştirilmiş bir RadioGroup'tur.

import android.content.Context;
import android.os.Build;
import android.support.annotation.IdRes;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;

import java.util.concurrent.atomic.AtomicInteger;

/**
 * This class is a replacement for android RadioGroup - it supports
 * child layouts which standard RadioGroup doesn't.
 */
public class RecursiveRadioGroup extends LinearLayout {

    public interface OnCheckedChangeListener {
        void onCheckedChanged(RecursiveRadioGroup group, @IdRes int checkedId);
    }

    /**
     * For generating unique view IDs on API < 17 with {@link #generateViewId()}.
     */
    private static final AtomicInteger sNextGeneratedId = new AtomicInteger(1);

    private CompoundButton checkedView;

    private CompoundButton.OnCheckedChangeListener childOnCheckedChangeListener;

    /**
     * When this flag is true, onCheckedChangeListener discards events.
     */
    private boolean mProtectFromCheckedChange = false;

    private OnCheckedChangeListener onCheckedChangeListener;

    private PassThroughHierarchyChangeListener mPassThroughListener;

    public RecursiveRadioGroup(Context context) {
        super(context);
        setOrientation(HORIZONTAL);
        init();
    }

    public RecursiveRadioGroup(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RecursiveRadioGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        childOnCheckedChangeListener = new CheckedStateTracker();
        mPassThroughListener = new PassThroughHierarchyChangeListener();

        super.setOnHierarchyChangeListener(mPassThroughListener);
    }

    @Override
    public void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
        mPassThroughListener.mOnHierarchyChangeListener = listener;
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();

        // checks the appropriate radio button as requested in the XML file
        if (checkedView != null) {
            mProtectFromCheckedChange = true;
            setCheckedStateForView(checkedView, true);
            mProtectFromCheckedChange = false;
            setCheckedView(checkedView);
        }
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        parseChild(child);

        super.addView(child, index, params);
    }

    private void parseChild(final View child) {
        if (child instanceof CompoundButton) {
            final CompoundButton checkable = (CompoundButton) child;

            if (checkable.isChecked()) {
                mProtectFromCheckedChange = true;
                if (checkedView != null) {
                    setCheckedStateForView(checkedView, false);
                }
                mProtectFromCheckedChange = false;
                setCheckedView(checkable);
            }
        } else if (child instanceof ViewGroup) {
            parseChildren((ViewGroup) child);
        }
    }

    private void parseChildren(final ViewGroup child) {
        for (int i = 0; i < child.getChildCount(); i++) {
            parseChild(child.getChildAt(i));
        }
    }

    /**
     * <p>Sets the selection to the radio button whose identifier is passed in
     * parameter. Using -1 as the selection identifier clears the selection;
     * such an operation is equivalent to invoking {@link #clearCheck()}.</p>
     *
     * @param view the radio button to select in this group
     * @see #getCheckedItemId()
     * @see #clearCheck()
     */
    public void check(CompoundButton view) {
        if(checkedView != null) {
            setCheckedStateForView(checkedView, false);
        }

        if(view != null) {
            setCheckedStateForView(view, true);
        }

        setCheckedView(view);
    }

    private void setCheckedView(CompoundButton view) {
        checkedView = view;

        if(onCheckedChangeListener != null) {
            onCheckedChangeListener.onCheckedChanged(this, checkedView.getId());
        }
    }

    private void setCheckedStateForView(View checkedView, boolean checked) {
        if (checkedView != null && checkedView instanceof CompoundButton) {
            ((CompoundButton) checkedView).setChecked(checked);
        }
    }

    /**
     * <p>Returns the identifier of the selected radio button in this group.
     * Upon empty selection, the returned value is -1.</p>
     *
     * @return the unique id of the selected radio button in this group
     * @attr ref android.R.styleable#RadioGroup_checkedButton
     * @see #check(CompoundButton)
     * @see #clearCheck()
     */
    @IdRes
    public int getCheckedItemId() {
        return checkedView.getId();
    }

    public CompoundButton getCheckedItem() {
        return checkedView;
    }

    /**
     * <p>Clears the selection. When the selection is cleared, no radio button
     * in this group is selected and {@link #getCheckedItemId()} returns
     * null.</p>
     *
     * @see #check(CompoundButton)
     * @see #getCheckedItemId()
     */
    public void clearCheck() {
        check(null);
    }

    /**
     * <p>Register a callback to be invoked when the checked radio button
     * changes in this group.</p>
     *
     * @param listener the callback to call on checked state change
     */
    public void setOnCheckedChangeListener(RecursiveRadioGroup.OnCheckedChangeListener listener) {
        onCheckedChangeListener = listener;
    }

    /**
     * Generate a value suitable for use in {@link #setId(int)}.
     * This value will not collide with ID values generated at build time by aapt for R.id.
     *
     * @return a generated ID value
     */
    public static int generateViewId() {
        for (; ; ) {
            final int result = sNextGeneratedId.get();
            // aapt-generated IDs have the high byte nonzero; clamp to the range under that.
            int newValue = result + 1;
            if (newValue > 0x00FFFFFF) newValue = 1; // Roll over to 1, not 0.
            if (sNextGeneratedId.compareAndSet(result, newValue)) {
                return result;
            }
        }
    }

    private class CheckedStateTracker implements CompoundButton.OnCheckedChangeListener {

        @Override
        public void onCheckedChanged(CompoundButton view, boolean b) {
            if (mProtectFromCheckedChange) {
                return;
            }

            mProtectFromCheckedChange = true;
            if (checkedView != null) {
                setCheckedStateForView(checkedView, false);
            }
            mProtectFromCheckedChange = false;

            int id = view.getId();
            setCheckedView(view);
        }
    }

    private class PassThroughHierarchyChangeListener implements OnHierarchyChangeListener {

        private OnHierarchyChangeListener mOnHierarchyChangeListener;

        @Override
        public void onChildViewAdded(View parent, View child) {
            if (child instanceof CompoundButton) {
                int id = child.getId();

                if (id == View.NO_ID) {
                    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
                        child.setId(generateViewId());
                    } else {
                        child.setId(View.generateViewId());
                    }
                }

                ((CompoundButton) child).setOnCheckedChangeListener(childOnCheckedChangeListener);

                if (mOnHierarchyChangeListener != null) {
                    mOnHierarchyChangeListener.onChildViewAdded(parent, child);
                }
            } else if(child instanceof ViewGroup) {
                // View hierarchy seems to be constructed from the bottom up,
                // so all child views are already added. That's why we
                // manually call the listener for all children of ViewGroup.
                for(int i = 0; i < ((ViewGroup) child).getChildCount(); i++) {
                    onChildViewAdded(child, ((ViewGroup) child).getChildAt(i));
                }
            }
        }

        @Override
        public void onChildViewRemoved(View parent, View child) {
            if (child instanceof RadioButton) {
                ((CompoundButton) child).setOnCheckedChangeListener(null);
            }

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

}

RadioGroupİç içe RadioButtongörünümlerle de çalışması dışında, onu mizanpajınızda normal bir şekilde kullanabilirsiniz :

<RecursiveRadioGroup
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="16dp"
    android:layout_marginBottom="16dp"
    android:layout_marginLeft="16dp"
    android:layout_marginRight="16dp"
    android:orientation="horizontal">

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rbNotEnoughProfileInfo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Not enough profile information"/>

        <RadioButton
            android:id="@+id/rbNotAGoodFit"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Not a good fit"/>

        <RadioButton
            android:id="@+id/rbDatesNoLongerAvailable"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Dates no longer available"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/rbOther"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Other"/>

        <android.support.v7.widget.AppCompatEditText
            android:id="@+id/etReason"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_below="@+id/tvMessageError"
            android:textSize="15sp"
            android:gravity="top|left"
            android:hint="Tell us more"
            android:padding="16dp"
            android:background="@drawable/edit_text_multiline_background"/>
    </LinearLayout>

</RecursiveRadioGroup>

6

Bu çözüm gönderilmedi, bu nedenle şu şekilde gönderiliyor:

Adım 0: Bir CompoundButton previousCheckedCompoundButton; Global bir değişken oluşturun.

1. Adım: OnCheckedChangedListenerRadyo düğmeleri için oluşturun

CompoundButton.OnCheckedChangeListener onRadioButtonCheckedListener = new CompoundButton.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
            if (!isChecked) return;
            if (previousCheckedCompoundButton != null) {
                previousCheckedCompoundButton.setChecked(false);
                previousCheckedCompoundButton = buttonView;
            } else {
                previousCheckedCompoundButton = buttonView;
            }
        }
    };

3. Adım: Tüm radyo düğmelerine dinleyici ekleyin:

radioButton1.setOnCheckedChangeListener(onRadioButtonCheckedListener);
radioButton2.setOnCheckedChangeListener(onRadioButtonCheckedListener);
radioButton3.setOnCheckedChangeListener(onRadioButtonCheckedListener);
radioButton4.setOnCheckedChangeListener(onRadioButtonCheckedListener);

Bu kadar!! sen bittin.


5

Ah .. Gerçekten Android'in böyle temel bir işlevselliğe sahip olmadığını suçlayın.

@ScottBiggs yanıtından uyarlanan, Kotlin ile bunu yapmanın muhtemelen en kısa yolu:

var currentSelected = button1
listOf<RadioButton>(
    button1, button2, button3, ...
).forEach {
    it.setOnClickListener { _ ->
        currentSelected.isChecked = false
        currentSelected = it
        currentSelected.isChecked = true
    }
}

Cevabınızın içinde mantık yok daha dikkatli kontrol edin
Edgar Khimich

@EdgarKhimich "mantıksız" derken neyi kastediyorsunuz ..? kodum, birkaç radyo düğmesinin nasıl gruplandırılacağıyla ilgili orijinal soruyu basit ve zarif bir şekilde yanıtlıyor. basit bir kontrol geçişi dışında herhangi bir onclicklistener ayarlamıyoruz.
yani

Bu mükemmel ... bir cazibe gibi çalışıyor ve fazla kod eklemiyor.
kwishnu

3

Bu sorunu çözmek için bu iki yöntemi yarattım. Tüm yapmanız gereken, RadioButton'ların olduğu (RadioGroup, LinearLayout, RelativeLayout, vb. Olabilir) ViewGroup'u iletmektir ve OnClick olaylarını özel olarak ayarlar, yani, RadioButton'lardan biri ViewGroup'un alt öğesi ( herhangi bir iç içe geçmiş düzeyde) seçilirse, diğerlerinin seçimi kaldırılır. İstediğiniz kadar iç içe geçmiş düzen ile çalışır.

public class Utils {
    public static void setRadioExclusiveClick(ViewGroup parent) {
        final List<RadioButton> radios = getRadioButtons(parent);

        for (RadioButton radio: radios) {
            radio.setOnClickListener(new OnClickListener() {

                @Override
                public void onClick(View v) {
                    RadioButton r = (RadioButton) v;
                    r.setChecked(true);
                    for (RadioButton r2:radios) {
                        if (r2.getId() != r.getId()) {
                            r2.setChecked(false);
                        }
                    }

                }
            });
        }
    }

    private static List<RadioButton> getRadioButtons(ViewGroup parent) {
        List<RadioButton> radios = new ArrayList<RadioButton>();
        for (int i=0;i < parent.getChildCount(); i++) {
            View v = parent.getChildAt(i);
            if (v instanceof RadioButton) {
                radios.add((RadioButton) v);
            } else if (v instanceof ViewGroup) {
                List<RadioButton> nestedRadios = getRadioButtons((ViewGroup) v);
                radios.addAll(nestedRadios);
            }
        }
        return radios;
    }
}

Bir aktivite içindeki kullanım şu şekilde olacaktır:

ViewGroup parent = findViewById(R.id.radios_parent);
Utils.setRadioExclusiveClick(parent);

2

İç içe geçmiş radyo düğmeleri içermesine izin veren kendi radyo grubu sınıfımı yazdım. Bunu kontrol et. Hata bulursanız lütfen bana bildirin.

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;

/**
 * This class is used to create a multiple-exclusion scope for a set of compound
 * buttons. Checking one compound button that belongs to a group unchecks any
 * previously checked compound button within the same group. Intially, all of
 * the compound buttons are unchecked. While it is not possible to uncheck a
 * particular compound button, the group can be cleared to remove the checked
 * state. Basically, this class extends functionality of
 * {@link android.widget.RadioGroup} because it doesn't require that compound
 * buttons are direct childs of the group. This means you can wrap compound
 * buttons with other views. <br>
 * <br>
 * 
 * <b>IMPORTATNT! Follow these instruction when using this class:</b><br>
 * 1. Each direct child of this group must contain one compound button or be
 * compound button itself.<br>
 * 2. Do not set any "on click" or "on checked changed" listeners for the childs
 * of this group.
 */
public class CompoundButtonsGroup extends LinearLayout {

 private View checkedView;
 private OnCheckedChangeListener listener;
 private OnHierarchyChangeListener onHierarchyChangeListener;

 private OnHierarchyChangeListener onHierarchyChangeListenerInternal = new OnHierarchyChangeListener() {

  @Override
  public final void onChildViewAdded(View parent, View child) {
   notifyHierarchyChanged(null);
   if (CompoundButtonsGroup.this.onHierarchyChangeListener != null) {
    CompoundButtonsGroup.this.onHierarchyChangeListener.onChildViewAdded(
      parent, child);
   }
  }

  @Override
  public final void onChildViewRemoved(View parent, View child) {
   notifyHierarchyChanged(child);
   if (CompoundButtonsGroup.this.onHierarchyChangeListener != null) {
    CompoundButtonsGroup.this.onHierarchyChangeListener.onChildViewRemoved(
      parent, child);
   }
  }
 };

 public CompoundButtonsGroup(Context context) {
  super(context);
  init();
 }

 public CompoundButtonsGroup(Context context, AttributeSet attrs) {
  super(context, attrs);
  init();
 }

 public CompoundButtonsGroup(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);
  init();
 }

 private void init() {
  super.setOnHierarchyChangeListener(this.onHierarchyChangeListenerInternal);
 }

 @Override
 public final void setOnHierarchyChangeListener(OnHierarchyChangeListener listener) {
  this.onHierarchyChangeListener = listener;
 }

 /**
  * Register a callback to be invoked when the checked view changes in this
  * group.
  * 
  * @param listener
  *            the callback to call on checked state change.
  */
 public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
  this.listener = listener;
 }

 /**
  * Returns currently selected view in this group. Upon empty selection, the
  * returned value is null.
  */
 public View getCheckedView() {
  return this.checkedView;
 }

 /**
  * Returns index of currently selected view in this group. Upon empty
  * selection, the returned value is -1.
  */
 public int getCheckedViewIndex() {
  return (this.checkedView != null) ? indexOfChild(this.checkedView) : -1;
 }

 /**
  * Sets the selection to the view whose index in group is passed in
  * parameter.
  * 
  * @param index
  *            the index of the view to select in this group.
  */
 public void check(int index) {
  check(getChildAt(index));
 }

 /**
  * Clears the selection. When the selection is cleared, no view in this
  * group is selected and {@link #getCheckedView()} returns null.
  */
 public void clearCheck() {
  if (this.checkedView != null) {
   findCompoundButton(this.checkedView).setChecked(false);
   this.checkedView = null;
   onCheckedChanged();
  }
 }

 private void onCheckedChanged() {
  if (this.listener != null) {
   this.listener.onCheckedChanged(this.checkedView);
  }
 }

 private void check(View child) {
  if (this.checkedView == null || !this.checkedView.equals(child)) {
   if (this.checkedView != null) {
    findCompoundButton(this.checkedView).setChecked(false);
   }

   CompoundButton comBtn = findCompoundButton(child);
   comBtn.setChecked(true);

   this.checkedView = child;
   onCheckedChanged();
  }
 }

 private void notifyHierarchyChanged(View removedView) {
  for (int i = 0; i < getChildCount(); i++) {
   View child = getChildAt(i);
   child.setOnClickListener(new OnClickListener() {

    @Override
    public void onClick(View v) {
     check(v);
    }
   });
   CompoundButton comBtn = findCompoundButton(child);
   comBtn.setClickable(comBtn.equals(child));
  }

  if (this.checkedView != null && removedView != null
    && this.checkedView.equals(removedView)) {
   clearCheck();
  }
 }

 private CompoundButton findCompoundButton(View view) {
  if (view instanceof CompoundButton) {
   return (CompoundButton) view;
  }

  if (view instanceof ViewGroup) {
   for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) {
    CompoundButton compoundBtn = findCompoundButton(((ViewGroup) view)
      .getChildAt(i));
    if (compoundBtn != null) {
     return compoundBtn;
    }
   }
  }

  return null;
 }

 /**
  * Interface definition for a callback to be invoked when the checked view
  * changed in this group.
  */
 public interface OnCheckedChangeListener {

  /**
   * Called when the checked view has changed.
   * 
   * @param checkedView
   *            newly checked view or null if selection was cleared in the
   *            group.
   */
  public void onCheckedChanged(View checkedView);
 }

}

2

İki şey yapmanız gerekiyor:

  1. Kullanım mListView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
  2. Özel satır görünümünüzü uygulayın Checkable.

Bu yüzden, daha iyi çözümün Checkable'ı iç LinearLayout'unuzun içine uygulamak olduğunu düşünüyorum: (daichan4649 sayesinde, https://gist.github.com/daichan4649/5245378 linkinden, aşağıda yapıştırılan tüm kodu aldım)

CheckableLayout.java

package daichan4649.test;

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.Checkable;
import android.widget.LinearLayout;

public class CheckableLayout extends LinearLayout implements Checkable {

    private static final int[] CHECKED_STATE_SET = { android.R.attr.state_checked };

    public CheckableLayout(Context context) {
        super(context, null);
    }

    public CheckableLayout(Context context, AttributeSet attrs) {
        super(context, attrs, 0);
    }

    public CheckableLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    private boolean checked;

    @Override
    public boolean isChecked() {
        return checked;
    }

    @Override
    public void setChecked(boolean checked) {
        if (this.checked != checked) {
            this.checked = checked;
            refreshDrawableState();

            for (int i = 0; i < getChildCount(); i++) {
                View child = getChildAt(i);
                if (child instanceof Checkable) {
                    ((Checkable) child).setChecked(checked);
                }
            }
        }
    }

    @Override
    public void toggle() {
        setChecked(!checked);
    }

    @Override
    protected int[] onCreateDrawableState(int extraSpace) {
        final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
        if (isChecked()) {
            mergeDrawableStates(drawableState, CHECKED_STATE_SET);
        }
        return drawableState;
    }
}

inflater_list_column.xml

<?xml version="1.0" encoding="utf-8"?>
<daichan4649.test.CheckableLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/check_area"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center_vertical">

    <TextView
        android:id="@+id/text"
        android:layout_width="0dip"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:layout_weight="1"
        android:gravity="center_vertical" />

    <RadioButton
        android:id="@+id/radio"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:clickable="false"
        android:focusable="false"
        android:focusableInTouchMode="false" />

</daichan4649.test.CheckableLayout>

TestFragment.java

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {

    View view = inflater.inflate(R.layout.fragment_test, container, false);

    // 表示データ
    List<String> dataList = new ArrayList<String>();

    // 初期選択位置
    int initSelectedPosition = 3;

    // リスト設定
    TestAdapter adapter = new TestAdapter(getActivity(), dataList);
    ListView listView = (ListView) view.findViewById(R.id.list);
    listView.setAdapter(adapter);
    listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
    listView.setItemChecked(initSelectedPosition, true);

    listView.setOnItemClickListener(new OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
            // 選択状態を要素(checkable)へ反映
            Checkable child = (Checkable) parent.getChildAt(position);
            child.toggle();
        }
    });
    return view;
}

private static class TestAdapter extends ArrayAdapter<String> {

    private LayoutInflater inflater;

    public TestAdapter(Context context, List<String> dataList) {
        super(context, 0, dataList);
        inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        final ViewHolder holder;
        if (convertView == null) {
            convertView = inflater.inflate(R.layout.inflater_list_column, null);
            holder = new ViewHolder();
            holder.text = (TextView) convertView.findViewById(R.id.text);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        // bindData
        holder.text.setText(getItem(position));
        return convertView;
    }
}

private static class ViewHolder {
    TextView text;
}

2

4 farklı radyo düğmesini iki farklı doğrusal düzene yerleştirmek istediğim için aynı sorunla karşılaştım ve bu düzen radyo grubunun alt öğesi olacak. RadioGroup'ta arzu davranışını elde etmek için addView işlevini aşırı yükledim

İşte çözüm

public class AgentRadioGroup extends RadioGroup
{

    public AgentRadioGroup(Context context) {
        super(context);
    }

    public AgentRadioGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    public void onViewAdded(View child) {
        if( child instanceof ViewGroup)
        {
            ViewGroup viewGroup = (ViewGroup) child;
            for(int i=0; i<viewGroup.getChildCount(); i++)
            {
                View subChild = viewGroup.getChildAt(i);
                if( subChild instanceof ViewGroup )
                {
                    onViewAdded(subChild);
                }
                else
                {
                    if (subChild instanceof RadioButton) {
                        super.onViewAdded(subChild);
                    }
                }
            }
        }
        if (child instanceof RadioButton)
        {
            super.onViewAdded(child);
        }
    }
}

1

Sizi bu düzen yapısını uygulamaktan alıkoyan hiçbir şey yoktur ( RadioGroupaslında bir alt sınıfıdır LinearLayout) ama yapmamalısınız. Her şeyden önce bir yapıya 4 düzeyleri derin senin eğer, ikinci ve (Bunu optimize olabilir başka düzen yapısı kullanılarak) oluşturmak RadioButtonsbir doğrudan çocuklar değildir RadioGroup, gruptaki seçilen yalnızca bir öğe olmaz çalışır. Bu Radiobutton, bu düzenden bir tane seçerseniz ve ardından başka bir RadioButtontane RadioButtonsseçerseniz, son seçilen yerine iki tane seçeceğiniz anlamına gelir .

O düzende ne yapmak istediğinizi açıklarsanız belki size bir alternatif önerebilirim.


Luksprog, Açıklamanız için teşekkürler. RadioButton'ların bir radyo grubunun doğrudan çocukları olmadığını doğru anlarsam çalışmaz.
marcoqf73

1
@ marcoqf73 Evet, daha basit bir ifadeyle, eğer mizanpajda RadioButtonsve ebeveyn arasında herhangi bir şey varsa, RadioGroupbu her zamanki gibi çalışmayacak ve temelde bir LinearLayoutdolu ile sonuçlanacaksınız RadioButtons.
kullanıcı

2
Böyle bir şey yapmak için pek çok neden var. Örneğin, düzenleriniz üzerinde basit bir LinearLayout'tan daha fazla kontrole sahip olmak isteyebilirsiniz; benim durumumda, birden çok RadioButtons satırı yapmak istiyorum. Yerleşim düzenleri, hemen hemen HER Android düzeninin nasıl çalıştığıdır. Bah, her geçen gün edindiğim bu UI tuhaflıklarına çözüm ararken "Bunu yapamazsın" ı duymaktan bıktım. :(
SMBiggs

@ScottBiggs Bunu yapamazsın demedim, soruyu soran kullanıcının ne yapacağını denemenin işe yaramayacağını söyledim. Kendi düzeninizi uygulamakta özgürsünüz (ama doğru yapmak o kadar da kolay değil) veya benim stackoverflow.com/questions/10425569/… ' nin bu cevabındaki gibi bir numara kullanmakta özgürsünüz .
kullanıcı

Tablo düzenini genişleten ve radiogroup sınıfından özellikler ekleyen bir radiogroup sınıfı oluşturdum. Radyo düğmelerini dinamik olarak ekleyen sınırsız sayıda sütunla oldukça iyi çalışır. stackoverflow.com/questions/10425569/…
Kristy Welsh

1

@İnfografnet ve @lostdev'e dayalı 0,02 dolarım (Bileşik Düğme önerisi için @Neromancer'e de teşekkürler!)

public class AdvRadioGroup {
    public interface OnButtonCheckedListener {
        void onButtonChecked(CompoundButton button);
    }

    private final List<CompoundButton> buttons;
    private final View.OnClickListener onClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            setChecked((CompoundButton) v);
        }
    };

    private OnButtonCheckedListener listener;
    private CompoundButton lastChecked;


    public AdvRadioGroup(View view) {
        buttons = new ArrayList<>();
        parseView(view);
    }

    private void parseView(final View view) {
        if(view instanceof CompoundButton) {
            buttons.add((CompoundButton) view);
            view.setOnClickListener(onClick);
        } else if(view instanceof ViewGroup) {
            final ViewGroup group = (ViewGroup) view;
            for (int i = 0; i < group.getChildCount();i++) {
                parseView(group.getChildAt(i));
            }
        }
    }

    public List<CompoundButton> getButtons() { return buttons; }

    public CompoundButton getLastChecked() { return lastChecked; }

    public void setChecked(int index) { setChecked(buttons.get(index)); }

    public void setChecked(CompoundButton button) {
        if(button == lastChecked) return;

        for (CompoundButton btn : buttons) {
            btn.setChecked(false);
        }

        button.setChecked(true);

        lastChecked = button;

        if(listener != null) {
            listener.onButtonChecked(button);
        }
    }

    public void setOnButtonCheckedListener(OnButtonCheckedListener listener) { this.listener = listener; }
}

Kullanım (dahil dinleyiciyle):

AdvRadioGroup group = new AdvRadioGroup(findViewById(R.id.YOUR_VIEW));
group.setOnButtonCheckedListener(new AdvRadioGroup.OnButtonCheckedListener() {
    @Override
    public void onButtonChecked(CompoundButton button) {
        // do fun stuff here!
    }
});

Bonus: Son kontrol edilen düğmeyi, tüm düğmelerin listesini alabilir ve bununla herhangi bir düğmeyi indeksleyerek kontrol edebilirsiniz!


harika çözüm! benim için çalışıyor. sadece yeni bir onClick dinleyicisi içindeki doğrusal düzenleri atamanız gerekir, çünkü yalnızca radyo düğmesinin dairesine dokunursanız seçim değişir.
benoffi7

1
    int currentCheckedRadioButton = 0;
    int[] myRadioButtons= new int[6];
    myRadioButtons[0] = R.id.first;
    myRadioButtons[1] = R.id.second;
    //..
    for (int radioButtonID : myRadioButtons) {
        findViewById(radioButtonID).setOnClickListener(
                    new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (currentCheckedRadioButton != 0)
                    ((RadioButton) findViewById(currentCheckedRadioButton)).setChecked(false);
                currentCheckedRadioButton = v.getId();

            }
        });
    }

1

Bu basit RadioGroup uzantı kodunu kullanabilirsiniz. RadioButtons ile birlikte içindeki düzenleri / görünümleri / resimleri bırakın ve çalışacaktır.

Seçili RadioButton'ı indeksiyle birlikte döndüren seçim geri aramasını içerir ve seçimi indeks veya id'ye göre programatik olarak ayarlayabilirsiniz:

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RadioButton;
import android.widget.RadioGroup;

import java.util.ArrayList;

public class EnhancedRadioGroup extends RadioGroup implements View.OnClickListener {

    public interface OnSelectionChangedListener {
        void onSelectionChanged(RadioButton radioButton, int index);
    }

    private OnSelectionChangedListener selectionChangedListener;
    ArrayList<RadioButton> radioButtons = new ArrayList<>();

    public EnhancedRadioGroup(Context context) {
        super(context);
    }

    public EnhancedRadioGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        if (changed) {
            getRadioButtons();
        }
    }

    private void getRadioButtons() {
        radioButtons.clear();
        checkForRadioButtons(this);
    }

    private void checkForRadioButtons(ViewGroup viewGroup) {
        if (viewGroup == null) {
            return;
        }
        for (int i = 0; i < viewGroup.getChildCount(); i++) {
            View v = viewGroup.getChildAt(i);
            if (v instanceof RadioButton) {
                v.setOnClickListener(this);
                // store index of item
                v.setTag(radioButtons.size());
                radioButtons.add((RadioButton) v);
            }
            else if (v instanceof ViewGroup) {
                checkForRadioButtons((ViewGroup)v);
            }
        }
    }

    public RadioButton getSelectedItem() {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        for (RadioButton radioButton : radioButtons) {
            if (radioButton.isChecked()) {
                return radioButton;
            }
        }
        return null;
    }

    public void setOnSelectionChanged(OnSelectionChangedListener selectionChangedListener) {
        this.selectionChangedListener = selectionChangedListener;
    }

    public void setSelectedById(int id) {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        for (RadioButton radioButton : radioButtons) {
            boolean isSelectedRadioButton = radioButton.getId() == id;
            radioButton.setChecked(isSelectedRadioButton);
            if (isSelectedRadioButton && selectionChangedListener != null) {
                selectionChangedListener.onSelectionChanged(radioButton, (int)radioButton.getTag());
            }
        }
    }

    public void setSelectedByIndex(int index) {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        if (radioButtons.size() > index) {
            setSelectedRadioButton(radioButtons.get(index));
        }
    }

    @Override
    public void onClick(View v) {
        setSelectedRadioButton((RadioButton) v);
    }

    private void setSelectedRadioButton(RadioButton rb) {
        if (radioButtons.isEmpty()) {
            getRadioButtons();
        }
        for (RadioButton radioButton : radioButtons) {
            radioButton.setChecked(rb == radioButton);
        }
        if (selectionChangedListener != null) {
            selectionChangedListener.onSelectionChanged(rb, (int)rb.getTag());
        }
    }
}

Xml düzeninizde kullanın:

    <path.to.your.package.EnhancedRadioGroup>
       Layouts containing RadioButtons/Images/Views and other RadioButtons
    </path.to.your.package.EnhancedRadioGroup>

Geri aramayı kaydetmek için:

        enhancedRadioGroupInstance.setOnSelectionChanged(new EnhancedRadioGroup.OnSelectionChangedListener() {
            @Override
            public void onSelectionChanged(RadioButton radioButton, int index) {

            }
        });

0

Bu daha eski bir konu olabilir, ancak yazdığım basit hacky kodunu hızlıca paylaşmak istiyorum .. Bu herkes için değil ve bazı iyileştirmelerle de yapabilirdi ..

Bu kodu kullanmak için durum?
Bu kod, benim durumumda aşağıdaki gibi orijinal soru veya benzeri bir düzeni olan kişiler içindir. Bu kişisel olarak kullandığım bir Dialog içindi.

  • LinLayout_Main
    • LinLayout_Row1
      • Resim görünümü
      • Radyo düğmesi
    • LinLayout_Row2
      • Resim görünümü
      • Radyo düğmesi
    • LinLayout_Row3
      • Resim görünümü
      • Radyo düğmesi

Kod kendi başına ne yapıyor?
Bu kod, "LinLayout_Main" in tüm Alt Öğelerini numaralandıracak ve "Doğrusal Yerleşim" olan her çocuk için, o Görünümü herhangi bir RadioButton için numaralandıracaktır.

Basitçe, üst "LinLayout_Main" e bakacak ve herhangi bir Alt Doğrusal Düzende bulunan tüm RadioButton'ları bulacaktır.

MyMethod_ShowDialog
, bulduğu her RadioButton için "setOnClickListener" ayarına bakarken, bir XML düzen dosyası içeren bir iletişim kutusu gösterecektir.

MyMethod_ClickRadio
her RadioButton'ı "MyMethod_ShowDialog" ile aynı şekilde döngüye sokacak, ancak "setOnClickListener" ayarı yerine her RadioButton'ı temizlemek için "setChecked (false)" yapacak ve son adım olarak RadioButton'a "setChecked (false)" olacaktır. tıklama olayı olarak adlandırılır.

public void MyMethod_ShowDialog(final double tmpLat, final double tmpLng) {
        final Dialog dialog = new Dialog(actMain);
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
        dialog.setContentView(R.layout.layout_dialogXML);

        final LinearLayout tmpLayMain = (LinearLayout)dialog.findViewById(R.id.LinLayout_Main);
        if (tmpLayMain!=null) {
            // Perform look for each child of main LinearLayout
            int iChildCount1 = tmpLayMain.getChildCount();
            for (int iLoop1=0; iLoop1 < iChildCount1; iLoop1++){
                View tmpChild1 = tmpLayMain.getChildAt(iLoop1);
                if (tmpChild1 instanceof LinearLayout) {
                    // Perform look for each LinearLayout child of main LinearLayout
                    int iChildCount2 = ((LinearLayout) tmpChild1).getChildCount();
                    for (int iLoop2=0; iLoop2 < iChildCount2; iLoop2++){
                        View tmpChild2 = ((LinearLayout) tmpChild1).getChildAt(iLoop2);
                        if (tmpChild2 instanceof RadioButton) {
                            ((RadioButton) tmpChild2).setOnClickListener(new RadioButton.OnClickListener() {
                                public void onClick(View v) {
                                    MyMethod_ClickRadio(v, dialog);
                                }
                            });
                        }
                    }
                }
            }

            Button dialogButton = (Button)dialog.findViewById(R.id.LinLayout_Save);
            dialogButton.setOnClickListener(new Button.OnClickListener() {
                public void onClick(View v) {
                    dialog.dismiss();
                }
            });
        }
       dialog.show();
}


public void MyMethod_ClickRadio(View vRadio, final Dialog dDialog) {

        final LinearLayout tmpLayMain = (LinearLayout)dDialog.findViewById(R.id.LinLayout_Main);
        if (tmpLayMain!=null) {
            int iChildCount1 = tmpLayMain.getChildCount();
            for (int iLoop1=0; iLoop1 < iChildCount1; iLoop1++){
                View tmpChild1 = tmpLayMain.getChildAt(iLoop1);
                if (tmpChild1 instanceof LinearLayout) {
                    int iChildCount2 = ((LinearLayout) tmpChild1).getChildCount();
                    for (int iLoop2=0; iLoop2 < iChildCount2; iLoop2++){
                        View tmpChild2 = ((LinearLayout) tmpChild1).getChildAt(iLoop2);
                        if (tmpChild2 instanceof RadioButton) {
                            ((RadioButton) tmpChild2).setChecked(false);
                        }
                    }
                }
            }
        }

        ((RadioButton) vRadio).setChecked(true);
}

Projeden kopyalanan ve Boşluklar / XML / Kimlik olarak yeniden adlandırılan hatalar olabilir.

Hangi öğelerin kontrol edildiğini bulmak için aynı tür döngüyü de çalıştırabilirsiniz.


Bunu çalıştırabildin mi? Normal bir düğmenin yanında bir radyo düğmesi olan alt doğrusal düzenlere sahip bir radyo grubu oluşturmaya çalışıyorum. Çalışmasını sağlayamadım ve postaladım , ancak radyo grubunun radyo düğmesi olmayan tüm çocuklara çarpacağı söylendi.
2014

0

Bu, @ Infografnet çözümünün değiştirilmiş bir sürümüdür. Basit ve kullanımı kolaydır.

RadioGroupHelper group = new RadioGroupHelper(this,R.id.radioButton1,R.id.radioButton2); group.radioButtons.get(0).performClick(); //programmatically

Sadece kopyalayıp yapıştırın

package com.qamar4p.farmer.ui.custom;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.RadioButton;

public class RadioGroupHelper {

    public List<CompoundButton> radioButtons = new ArrayList<>();

    public RadioGroupHelper(RadioButton... radios) {
        super();
        for (RadioButton rb : radios) {
            add(rb);
        }
    }

    public RadioGroupHelper(Activity activity, int... radiosIDs) {
        this(activity.findViewById(android.R.id.content),radiosIDs);
    }

    public RadioGroupHelper(View rootView, int... radiosIDs) {
        super();
        for (int radioButtonID : radiosIDs) {
            add((RadioButton)rootView.findViewById(radioButtonID));
        }
    }

    private void add(CompoundButton button){
        this.radioButtons.add(button);
        button.setOnClickListener(onClickListener);
    }

    View.OnClickListener onClickListener = v -> {
        for (CompoundButton rb : radioButtons) {
            if(rb != v) rb.setChecked(false);
        }
    };
}

0

Yanıtlarda gösterildiği gibi, çözüm basit bir özel hack'tir. İşte Kotlin'deki minimalist versiyonum.

import android.widget.RadioButton

class SimpleRadioGroup(private val radioButtons: List<RadioButton>) {

    init {
        radioButtons.forEach {
            it.setOnClickListener { clickedButton ->
                radioButtons.forEach { it.isChecked = false }
                (clickedButton as RadioButton).isChecked = true
            }
        }
    }

    val checkedButton: RadioButton?
        get() = radioButtons.firstOrNull { it.isChecked }
}

o zaman etkinliğinizin onCreate veya parçasının onViewCreated'ında böyle bir şey yapmanız yeterlidir:

SimpleRadioGroup(listOf(radio_button_1, radio_button_2, radio_button_3))

0

Bu, içinde RadioButton bulunan özel düzen için Kotlin'deki çözümüm.

tipInfoContainerFirst.radioButton.isChecked = true

var prevSelected = tipInfoContainerFirst.radioButton
prevSelected.isSelected = true

listOf<RadioButton>(
    tipInfoContainerFirst.radioButton,
    tipInfoContainerSecond.radioButton,
    tipInfoContainerThird.radioButton,
    tipInfoContainerForth.radioButton,
    tipInfoContainerCustom.radioButton
).forEach {
    it.setOnClickListener { _it ->
    if(!it.isSelected) {
        prevSelected.isChecked = false
        prevSelected.isSelected = false
        it.radioButton.isSelected = true
        prevSelected = it.radioButton
    }
  }
}

0

Aynı sorunu yaşıyorum, cinsiyet için Radyo düğmesini kullanmam gerekiyor ve hepsinde bir resim ve bir metin vardı, bu yüzden aşağıdaki yolu kullanarak çözmeye çalıştım.

xml dosyası:

<RadioGroup
       android:layout_marginTop="40dp"
       android:layout_marginEnd="23dp"
       android:id="@+id/rgGender"
       android:layout_width="match_parent"
       android:layout_below="@id/tvCustomer"
       android:orientation="horizontal"
       android:layout_height="wrap_content">

       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:gravity="center_horizontal"
           android:layout_weight="1">
       <RadioButton
           android:id="@+id/rbMale"
           android:layout_width="80dp"
           android:layout_height="60dp"
           android:background="@drawable/male_radio_btn_selector"
           android:button="@null"
           style="@style/RadioButton.Roboto.20sp"/>

           <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="Male"
               style="@style/TextView.RobotoLight.TxtGrey.18sp"
               android:layout_margin="0dp"
               android:textSize="@dimen/txtsize_20sp"/>
       </LinearLayout>
       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:gravity="center_horizontal"
           android:layout_weight="1">
       <RadioButton
           android:layout_weight="1"
           android:gravity="center"
           android:id="@+id/rbFemale"
           android:layout_width="80dp"
           android:layout_height="60dp"
           android:button="@null"
           android:background="@drawable/female_radio_btn_selector"
           style="@style/RadioButton.Roboto.20sp"
           android:textColor="@color/light_grey"/>
           <TextView
               android:layout_width="wrap_content"
               android:layout_height="wrap_content"
               android:text="Female"
               android:layout_margin="0dp"
               style="@style/TextView.RobotoLight.TxtGrey.18sp"
               android:textSize="@dimen/txtsize_20sp"/>
       </LinearLayout>
       <LinearLayout
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:orientation="vertical"
           android:gravity="center_horizontal"
           android:layout_weight="1">
       <RadioButton
           android:layout_weight="1"
           android:gravity="center"
           android:id="@+id/rbOthers"
           android:layout_width="80dp"
           android:layout_height="60dp"
           android:button="@null"
           android:background="@drawable/other_gender_radio_btn_selector"
           style="@style/RadioButton.Roboto.20sp"/>
          <TextView
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Other"
              android:layout_margin="0dp"
              style="@style/TextView.RobotoLight.TxtGrey.18sp"
              android:textSize="@dimen/txtsize_20sp"/>
      </LinearLayout>
   </RadioGroup>

Java dosyasında: 3 radyo düğmesinin hepsinde setOnCheckedChangeListener'ı ayarladım ve aşağıda belirtildiği gibi geçersiz kılma yöntemi ve benim için iyi çalışıyor.

@Override
    public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
   switch (compoundButton.getId()){
       case R.id.rbMale:
           if(rbMale.isChecked()){
               rbMale.setChecked(true);
               rbFemale.setChecked(false);
               rbOther.setChecked(false);
           }
           break;
       case R.id.rbFemale:
           if(rbFemale.isChecked()){
               rbMale.setChecked(false);
               rbFemale.setChecked(true);
               rbOther.setChecked(false);
           }
           break;
       case R.id.rbOthers:
           if(rbOther.isChecked()){
               rbMale.setChecked(false);
               rbFemale.setChecked(false);
               rbOther.setChecked(true);
           }
           break;

   }
    }

0

MixedCompoundButtonGroup sizin için yapın!

MixedCompoundButtonGroup ana fikri

fun setAll() {
    for (i in 0 until childCount) {
        val child = getChildAt(i)
        setCompoundButtonListener(child)
    }
}  


private fun setCompoundButtonListener(view: View?) {
    if (view == null) return
    if (view is CompoundButton) {
        view.setOnCheckedChangeListener(compoundButtonCheckedChangedListener)
    } else if (view is ViewGroup && view !is RadioGroup) { // NOT RadioGroup!
        for (i in 0 until view.childCount) {
            setCompoundButtonListener(view.getChildAt(i))
        }
    }
}

private fun initCompoundButtonListener() {
    compoundButtonCheckedChangedListener = CompoundButton.OnCheckedChangeListener { compoundButton, isChecked ->
        setChecked(compoundButton, isChecked)
    }
}

private fun setChecked(compoundButton: CompoundButton, isChecked: Boolean) {
    if (isChecked.not()) return
    if (currentCompoundButton != null) {
        currentCompoundButton!!.isChecked = false
        currentCompoundButton = compoundButton
    } else {
        currentCompoundButton = compoundButton
    }
    checkedChangedListener?.onCheckedChanged(currentCompoundButton!!)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.