我正在开发一个应用程序,我需要有一个带有radiobuttons的列表视图,其中的值是从动态填充的数组中获取的。
我使用了here in this SO answer找到的示例来解决问题:
我也根据我的要求和使用我熟悉的代码来调整它以满足我的需求。
我的xml文件1:
<?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="match_parent">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:choiceMode="singleChoice"
android:id="@+id/myList" />
xml file2:
<com.blabla.CheckableLinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="@android:style/TextAppearance.Medium"
android:textStyle="bold"
android:ellipsize="end"
android:id="@+id/myTitle"
android:textColor="#000"
/>
</LinearLayout>
<CheckedTextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@android:id/text1" />
我的主要活动:
public class ListDemo extends Activity {
ArrayList<HashMap<String, String>> itemsList;
ListView listView;
public static final String TAG_ITEM = "item_name";
ArrayList< String>arrayList; // list of the strings that should appear in ListView
RadioAdapter arrayAdapter; // a middle man to bind ListView and array list
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.custom_view);
listView = (ListView) findViewById(R.id.myList);
itemsList = new ArrayList<HashMap<String, String>>();
// LIST OF STRINGS / DATA THAT SHOULD APPEAR IN LISTVIEW HERE WE HAVE HARD CODED IT WE CAN TAKE THIS INPUT FROM USER AS WELL
arrayList = new ArrayList();
arrayList.add("India");
arrayList.add("USA");
arrayList.add("England");
arrayList.add("Singapur");
arrayList.add("China");
arrayList.add("Canada");
arrayList.add("Srilanka");
arrayList.add("SouthAfrica");
Object[] items_2=arrayList.toArray();
for(int i=0;i<items_2.length;i++)
{
HashMap<String, String> map = new HashMap<String, String>();
map.put(TAG_ITEM,(String) items_2[i]);
itemsList.add(map);
}
arrayAdapter = new RadioAdapter(ListDemo.this,itemsList);
listView.setAdapter(arrayAdapter);
我的适配器:
public class RadioAdapter extends BaseAdapter {
private Activity activity;
private ArrayList<HashMap<String, String>> data;
private static LayoutInflater inflater=null;
public RadioAdapter(Activity a, ArrayList<HashMap<String, String>> d) {
activity = a;
data=d;
inflater = (LayoutInflater)activity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return data.size();
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
View vi=convertView;
if(convertView==null)
vi = inflater.inflate(R.layout.listitem, null);
TextView name = (TextView)vi.findViewById(R.id.myTitle); // title
HashMap<String, String> song = new HashMap<String, String>();
song = data.get(position);
// Setting all values in listview
// price2.setText(song.get(HistoryItems.TAG_PRICE2));
name.setText("Name: "+ song.get(ListDemo.TAG_ITEM));
return vi;
}
启动活动时出错,这是堆栈跟踪:
12-16 19:49:46.619: W/dalvikvm(8527): threadid=1: thread exiting with uncaught exception (group=0x400207d8)
12-16 19:49:46.749: E/AndroidRuntime(8527): FATAL EXCEPTION: main
12-16 19:49:46.749: E/AndroidRuntime(8527): android.view.InflateException: Binary XML file line #1: Error inflating class com.blabla.CheckableLinearLayout
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:576)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.LayoutInflater.inflate(LayoutInflater.java:385)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
12-16 19:49:46.749: E/AndroidRuntime(8527): at com.blabla.Dulux.RadioAdapter.getView(RadioAdapter.java:40)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.AbsListView.obtainView(AbsListView.java:1448)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.ListView.measureHeightOfChildren(ListView.java:1273)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.ListView.onMeasure(ListView.java:1184)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.View.measure(View.java:8171)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3132)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1012)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.LinearLayout.measureHorizontal(LinearLayout.java:696)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.LinearLayout.onMeasure(LinearLayout.java:306)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.View.measure(View.java:8171)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3132)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.View.measure(View.java:8171)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.LinearLayout.measureVertical(LinearLayout.java:526)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.LinearLayout.onMeasure(LinearLayout.java:304)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.View.measure(View.java:8171)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:3132)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.widget.FrameLayout.onMeasure(FrameLayout.java:245)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.View.measure(View.java:8171)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.ViewRoot.performTraversals(ViewRoot.java:801)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.ViewRoot.handleMessage(ViewRoot.java:1727)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.os.Handler.dispatchMessage(Handler.java:99)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.os.Looper.loop(Looper.java:123)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.app.ActivityThread.main(ActivityThread.java:4633)
12-16 19:49:46.749: E/AndroidRuntime(8527): at java.lang.reflect.Method.invokeNative(Native Method)
12-16 19:49:46.749: E/AndroidRuntime(8527): at java.lang.reflect.Method.invoke(Method.java:521)
12-16 19:49:46.749: E/AndroidRuntime(8527): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:858)
12-16 19:49:46.749: E/AndroidRuntime(8527): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616)
12-16 19:49:46.749: E/AndroidRuntime(8527): at dalvik.system.NativeStart.main(Native Method)
12-16 19:49:46.749: E/AndroidRuntime(8527): Caused by: java.lang.ClassNotFoundException: com.blabla.CheckableLinearLayout in loader dalvik.system.PathClassLoader[/data/app/com.blabla.Dulux-1.apk]
12-16 19:49:46.749: E/AndroidRuntime(8527): at dalvik.system.PathClassLoader.findClass(PathClassLoader.java:243)
12-16 19:49:46.749: E/AndroidRuntime(8527): at java.lang.ClassLoader.loadClass(ClassLoader.java:573)
12-16 19:49:46.749: E/AndroidRuntime(8527): at java.lang.ClassLoader.loadClass(ClassLoader.java:532)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.LayoutInflater.createView(LayoutInflater.java:466)
12-16 19:49:46.749: E/AndroidRuntime(8527): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:565)
12-16 19:49:46.749: E/AndroidRuntime(8527): ... 32 more
作为事后的想法,我还添加了实现可检查接口的类:
public class CheckableLinearLayout extends LinearLayout implements Checkable{
private CheckedTextView mCheckedTextView;
private final Drawable mCheckDrawable;
private final Drawable mRadioDrawable;
private boolean mIsChecked;
public CheckableLinearLayout(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray typedArray = null;
// Cache the check box drawable.
typedArray = context.getTheme().obtainStyledAttributes(new int[] {android.R.attr.listChoiceIndicatorMultiple});
if ((typedArray != null) && (typedArray.length() > 0)) {
mCheckDrawable = typedArray.getDrawable(0);
}
else {
// Fallback if the target theme doesn't define a check box drawable.
// Perhaps an application specific drawable should be used instead of null.
mCheckDrawable = null;
}
// Careful with resources like this, we don't need any memory leaks.
typedArray.recycle();
// Cache the radio button drawable.
typedArray = context.getTheme().obtainStyledAttributes(new int[] {android.R.attr.listChoiceIndicatorSingle});
if ((typedArray != null) && (typedArray.length() > 0)) {
mRadioDrawable = typedArray.getDrawable(0);
}
else {
// Fallback if the target theme doesn't define a radio button drawable.
// Perhaps an application specific drawable should be used instead of null
mRadioDrawable = null;
}
// Careful with resources like this, we don't need any memory leaks.
typedArray.recycle();
mIsChecked = false;
}
/*
* (non-Javadoc)
* @see android.widget.Checkable#isChecked()
*/
public boolean isChecked() {
return mIsChecked;
}
/*
* (non-Javadoc)
* @see android.view.View#onAttachedToWindow()
\
*/
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
mCheckedTextView = (CheckedTextView) findViewById(android.R.id.text1);
// Check if there is a valid GUI element that can visualize the current state.
if (mCheckedTextView != null) {
ViewParent p = getParent();
// Check if the parent of this list item is a ListView
if (p instanceof ListView) {
int choiceMode = ((ListView) p).getChoiceMode();
// Decide which check-state notation to visualize (check box, radio button
or none).
switch (choiceMode) {
case ListView.CHOICE_MODE_MULTIPLE:
mCheckedTextView.setCheckMarkDrawable(mCheckDrawable);
break;
case ListView.CHOICE_MODE_SINGLE:
mCheckedTextView.setCheckMarkDrawable(mRadioDrawable);
break;
default:
mCheckedTextView.setCheckMarkDrawable(null);
break;
}
}
}
}
/*
* (non-Javadoc)
* @see android.view.View#onFinishInflate()
*/
@Override
protected void onFinishInflate() {
super.onFinishInflate();
}
/*
* (non-Javadoc)
* @see android.widget.Checkable#setChecked(boolean)
*/
public void setChecked(boolean checked) {
mIsChecked = checked;
if (mCheckedTextView != null) {
mCheckedTextView.setChecked(mIsChecked);
}
}
/*
* (non-Javadoc)
* @see android.widget.Checkable#toggle()
*/
public void toggle() {
setChecked(!mIsChecked);
}
}