GridViewにラジオグループを実装して、グリッドの要素から1つのアイテムのみを選択できるようにします。
助けてください。
グリッドからの要素の選択を制限する目的は、次のように実行できます。
1.グリッド要素の作成。
<LinearLayout
android:id="@+id/item_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center">
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" />
<RadioButton
android:id="@+id/radiobtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Image" />
</LinearLayout>
2.アダプタをカスタマイズするgetView()メソッドでこのxmlを膨らませます。
public class MyAdapter extends BaseAdapter {
Context mCtx;
int[] mImg;
LayoutInflater layoutInflater;
RadioGroup rgp;
private RadioButton mSelectedRB;
private int mSelectedPosition = -1;
public MyAdapter(Context context, int[] img) {
this.mCtx = context;
this.mImg = img;
rgp = new RadioGroup(context);
layoutInflater = (LayoutInflater) mCtx
.getSystemService(LAYOUT_INFLATER_SERVICE);
}
@Override
public int getCount() {
return mImg.length;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View convertView,
ViewGroup parent) {
View view = convertView;
Holder holder;
if (view == null) {
view = layoutInflater.inflate(R.layout.element, null);
holder = new Holder();
holder.image = (ImageView) view.findViewById(R.id.imageView);
holder.radioButton = (RadioButton) view
.findViewById(R.id.radiobtn);
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
holder.radioButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if ((position != mSelectedPosition && mSelectedRB != null)) {
mSelectedRB.setChecked(false);
}
mSelectedPosition = position;
mSelectedRB = (RadioButton) v;
}
});
if (mSelectedPosition != position) {
holder.radioButton.setChecked(false);
} else {
holder.radioButton.setChecked(true);
if (mSelectedRB != null && holder.radioButton != mSelectedRB) {
mSelectedRB = holder.radioButton;
}
}
return view;
}
}
private class Holder {
ImageView image;
RadioButton radioButton;
}
これに対する別のアプローチRadioButton
は、追加のXML属性(などgroup
)を持つ独自のサブクラスを作成することです。これは、ボタンが属するグループを(文字列として)指定します。次に、サブクラスで、特定のグループ内で1つのラジオボタンのみが選択されていることを確認します。
これは次のように実行できます。
res/values/attrs.xml
まず、次のようなファイルを作成します。
<resources>
<declare-styleable name="GroupedRadioButton">
<attr name="group" format="string"/>
</declare-styleable>
</resources>
次に、サブクラスを作成しますGroupedRadioButton
。
public class GroupedRadioButton extends RadioButton {
public GroupedRadioButton(Context context, AttributeSet attrs) {
super(context, attrs);
processAttributes(context, attrs);
setOnClickListener(internalListener, true);
}
...
}
肉付けされたら(以下を参照)、レイアウトファイルで次のようにこの新しいクラスを使用できます。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res/com.example.app"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.example.app.GroupedRadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Option 1"
custom:group="group1" />
<com.example.app.GroupedRadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Option 2"
custom:group="group1" />
<com.example.app.GroupedRadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Option 3"
custom:group="group1" />
<com.example.app.GroupedRadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Option A"
custom:group="group2" />
<com.example.app.GroupedRadioButton
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Option B"
custom:group="group2" />
...
ラジオボタンは、レイアウトのどこにでも配置できます(例:)GridView
。xmlns:custom
カスタム属性を使用しているため、タグが必要であることに注意してください。
上記のレイアウトでは、オプション1、2、および3が相互に排他的になり、オプションAとBが相互に排他的になります。
GroupedRadioButton
これは、各グループ内で現在選択されているものを(静的に)追跡することによって実現されます。
public class GroupedRadioButton extends RadioButton {
private static Map<String, WeakReference<GroupedRadioButton>> buttonMap;
static {
buttonMap = new HashMap<String, WeakReference<GroupedRadioButton>>();
}
...
}
ここでは、ボタンへの強い参照を保持しないように注意する必要があります。そうしないと、ボタンがガベージコレクションされることはありません。
上記processAttributes()
のコンストラクターで指定されたメソッドは、指定したXMLから属性を掘り出し、group
これをインスタンスデータとして設定します。
private void processAttributes(Context context, AttributeSet attrs) {
TypedArray attributes = context.obtainStyledAttributes(attrs,
R.styleable.GroupedRadioButton);
int attributeCount = attributes.getIndexCount();
for (int i = 0; i < attributeCount; ++i) {
int attr = attributes.getIndex(i);
switch (attr) {
case R.styleable.GroupedRadioButton_group:
this.groupName = attributes.getString(attr);
break;
}
}
attributes.recycle();
}
OnClickListener
このクラスのメインを定義します。
private OnClickListener internalListener = new OnClickListener() {
@Override
public void onClick(View view) {
processButtonClick(view);
}
};
呼び出す:
private void processButtonClick(View view) {
if (!(view instanceof GroupedRadioButton))
return;
GroupedRadioButton clickedButton = (GroupedRadioButton) view;
String groupName = clickedButton.groupName;
WeakReference<GroupedRadioButton> selectedButtonReference = buttonMap.get(groupName);
GroupedRadioButton selectedButton = selectedButtonReference == null ? null : selectedButtonReference.get();
if (selectedButton != clickedButton) {
if (selectedButton != null)
selectedButton.setChecked(false);
clickedButton.setChecked(true);
buttonMap.put(groupName, new WeakReference<GroupedRadioButton>(clickedButton));
}
if (externalListener != null)
externalListener.onClick(view);
}
これは2つのことを行います。新しいボタンを選択する前に、古いグループボタンの選択を解除します(古いボタンと新しいボタンが異なると仮定します)。次に、クラスのユーザーが独自の「クリック時」機能を追加できるように、提供さonClick()
れているを呼び出します。externalListener
コンストラクターでのsetOnClickListener()
呼び出しは、次のように独自のメソッドを呼び出します。
private void setOnClickListener(OnClickListener listener, boolean internal) {
if (internal)
super.setOnClickListener(internalListener);
else
this.externalListener = listener;
}
これによりinternalListener
、が公式OnClickListener
に設定され、外部リスナーに適切なインスタンスデータが設定されます。その後、View.setOnClickListener()
メソッドは次のようにオーバーライドできます。
@Override
public void setOnClickListener(OnClickListener listener) {
setOnClickListener(listener, false);
}
この回答が長かったことをお詫びしますが、あなたや他の人が同じことをしようとしているのに役立つことを願っています。RadioGroup
もちろん、その子に再帰的に適用すれば、まったく必要ありません!
グリッドの要素を選択するときは、ラジオグループに含める他の要素が選択されていないこと、および選択が解除されていることを確認してください...