我有一个名为AddZoneDialog的类,它扩展了DialogFragment。在这个类中,我正在尝试使用存储在名为arrays.xml的xml文件中的图像填充GridView。
我使用TypedArray检索xml文件中的条目。我将该数组传递给自定义ImageAdapter(称为ZoneIconAdapter)以填充GridView。问题是,我一直在行
上获得NullPointerExceptionsholder.iv.setImageResource(imgs.getResourceId(position, -1));
为了使用getResourceId(...)测试TypedArray的用法,我将ImageView放在GridView外部的DialogFragment中,并使用以下方法手动填充图像:
(ImageView) iv = (ImageView) view.findViewById(R.id.ivIcon);
然后我使用了与ZoneIconAdapter中使用的相同语法向其添加图像:
iv.setImageResource(imgs.getResourceId(0, -1));
显示正确的图像。 图像适配器位于名为com.my.project.model的包中,所以我输入了com.my.project.R 在适配器中,如果我尝试对资源进行硬编码,它仍然会出现Null错误:
holder.iv.setImageResource(R.drawable.bed1);
我的代码如下: Class - ZoneIconAdapter:
public class ZoneIconAdapter extends BaseAdapter {
private static final String LOGTAG = "HOMECONTROL";
Context context;
TypedArray imgs;
public ZoneIconAdapter(Context c, TypedArray a){
this.context = c;
imgs = a;
}
@Override
public int getCount() {
//return imgIds.length;
return imgs.length();
}
@Override
public Object getItem(int index) {
return imgs.getResourceId(index, -1);
}
@Override
public long getItemId(int index) {
return index;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
if(convertView == null){
LayoutInflater inflater = ((Activity) context).getLayoutInflater();
convertView = inflater.inflate(R.layout.zone_icon_list, parent, false);
holder = new ViewHolder();
holder.iv = (ImageView) convertView.findViewById(R.id.ivIcon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
Log.w(LOGTAG, "(ZoneIconAdapter) pos: "+ position + " drawable : " + imgs.getDrawable(position) + " res: " +
imgs.getResourceId(position, -1));
holder.iv.setImageResource(imgs.getResourceId(position, -1)); // ***NULL ERROR ***
return convertView;
}
private class ViewHolder {
ImageView iv;
}
}
类 - AddZoneDialog.java
public class AddZoneDialog extends DialogFragment {
private static final String LOGTAG = "HOMECONTROL";
public static final String EXTRA_ZONE_NAME = "homecontrol.zonename";
public static final String EXTRA_NAME_LIST = "homecontrol.namelist";
public static final String EXTRA_IMG_LIST = "homecontrol.imglist";
private ZoneList zoneList;
private EditText etZoneName;
private GridView gvIcons;
TypedArray ids;
public AddZoneDialog newInstance(ZoneList zones){
Bundle args = new Bundle();
args.putSerializable(EXTRA_NAME_LIST, zones);
AddZoneDialog newDialog = new AddZoneDialog();
newDialog.setArguments(args);
return newDialog;
}
@Override
public Dialog onCreateDialog(Bundle savedState) {
View v = getActivity().getLayoutInflater()
.inflate(R.layout.frag_add_zone_dialog, null);
zoneList = (ZoneList) getArguments().getSerializable(EXTRA_NAME_LIST);
gvIcons = (GridView) v.findViewById(R.id.gvZonesIcons);
etZoneName = (EditText) v.findViewById(R.id.etZonesPopupName);
etZoneName.requestFocus();
ImageView iv = (ImageView) v.findViewById(R.id.ivIcon);
ZoneIconAdapter iconAdapter = new ZoneIconAdapter(getActivity(), ids);
gvIcons.setAdapter(iconAdapter);
ids = getActivity().getResources().obtainTypedArray(R.array.zone_icons);
iconAdapter.notifyDataSetChanged();
Log.w(LOGTAG, "SIZE OF IDS: " + ids.length());
iv.setImageResource(ids.getResourceId(0, -1)); // *****THIS WORKS*****
return new AlertDialog.Builder(getActivity())
.setView(v)
.setTitle(R.string.zones_add_dialog_title)
.setPositiveButton(R.string.ok, new AlertDialog.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
sendResult(Activity.RESULT_OK);
}
})
.setNegativeButton(R.string.cancel, null)
.create();
}
@Override
public void onActivityCreated(Bundle bundle) {
getDialog().getWindow().setSoftInputMode(LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
super.onActivityCreated(bundle);
}
public void sendResult(int resultCode){
String newName = etZoneName.getText().toString();
if ((newName.length() < 1) || (newName == null) || (newName == "")){
Toast.makeText(getActivity(), "You must enter a name.", Toast.LENGTH_SHORT).show();
return;
}
else{
if (nameOnList(newName)){
Toast.makeText(getActivity(), "That name is already in use. Please enter another name.",
Toast.LENGTH_LONG).show();
return;
}
}
if(getTargetFragment() == null)
return;
Intent i = new Intent();
i.putExtra(EXTRA_ZONE_NAME, newName);
getTargetFragment().onActivityResult(getTargetRequestCode(), resultCode, i);
}
boolean nameOnList(String name){
for (int i = 0; i < zoneList.size(); i++){
if (zoneList.get(i).getName().equals(name))
return true;
}
return false;
}
@Override
public void onStop() {
ids.recycle();
super.onStop();
}
}
XML - zone_icon_list.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="match_parent"
android:orientation="vertical" >
<!-- <com.example.homecontrol.views.DynamicImageView -->
<ImageView
android:name="@+id/ivIcon"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="centerCrop" />
</LinearLayout>
XML - frag_add_zone_dialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="10dp" >
<TextView
android:id="@+id/tvZonesEnterName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/zones_enter_name"/>
<EditText
android:id="@+id/etZonesPopupName"
android:layout_width="fill_parent"
android:layout_height="match_parent"
android:inputType="text"
android:hint="@string/zones_name_hint"
android:singleLine="true" />
<TextView
android:id="@+id/tvZonesSelectIcon"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/zones_select_icon" />
<ImageView
android:id="@+id/ivIcon"
android:layout_width="30dp"
android:layout_height="30dp"
android:scaleType="centerCrop" />
<GridView
android:id="@+id/gvZonesIcons"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:numColumns="auto_fit"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_gravity="center_horizontal" />
</LinearLayout>
最后一件事:为了测试GridView和ZoneIconAdapter,我用zoneView替换了zone_icon_list.xml中的ImageView,在Adapter类中,我将ViewHolder改为使用TextView而不是ImageView并使用:
...
holder.tv = (TextView) convertView.findViewById(R.id.tvTest);
...
holder.tv.setText("image " + position);
看看GridView是否只使用TextView填充,它运行得很好。 我整天都在研究这个问题并且已经完成了我能找到的所有stackoverflow条目并且我被烧毁了。我觉得它必须是一种我忽略的愚蠢,但不确定。
答案 0 :(得分:1)
<ImageView
android:name="@+id/..."
而不是
<ImageView
android:id="@+id/..."
所以我使用我请求的ID为视图获取空值。