我创建了一个ViewPager,我使用bitmapArray在ViewPager中显示图像。一切工作正常,但当我添加一个新的数据和调用notifydatasetchange,应用程序崩溃。
在这个应用程序中,我正在下载歌曲,并从该文件中获取从下载的歌曲的位图,并在位图数组中添加。
给出如下exception:
java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
我无法找到导致此异常的原因
ViewPager的适配器类是:
public class CoverFlowPagerAdapter extends PagerAdapter {
ArrayList<Bitmap> mBitmapArray;
Context c;
interface CoverFlowClick {
public void coverClick(int coverFlowPosition);
}
CoverFlowClick mCoverFlowClick;
public CoverFlowPagerAdapter(Context c, ArrayList<Bitmap> mBitmapArray) {
this.c = c;
this.mBitmapArray = mBitmapArray;
mCoverFlowClick = (CoverFlowClick) c;
}
@Override
public int getCount() {
return mBitmapArray.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return (object == view);
}
@Override
public Object instantiateItem(ViewGroup container, final int position) {
ImageView imageView;
View v = null;
LayoutInflater inflater= (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v=inflater.inflate(R.layout.coverflow_item,null);
imageView= (ImageView) v.findViewById(R.id.coverFlowImage);
imageView.setImageBitmap(mBitmapArray.get(position));
container.addView(imageView);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(c, "Clicked::--" + position, Toast.LENGTH_SHORT).show();
mCoverFlowClick.coverClick(position);
}
});
return imageView;
}
@Override
public int getItemPosition(Object object) {
return POSITION_NONE;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((ImageView) object);
}
}
我将位图添加到数组中,并像这样调用notifydatasetchanged:
@Override
public void updateSongList(String songName) {
getBitmapArray(songName);
mCoverFlowAdapter.notifyDataSetChanged();
}
编辑:我的自定义布局文件是
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<ImageView
android:id="@+id/coverFlowImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
我的getBitmapArray函数是
public void getBitmapArray(String songName) {
Bitmap bitmap = null;
path = Environment.getExternalStorageDirectory() + "/AppDownloads/" + songName;
File file = new File(path);
FileInputStream inputStream = null;
try {
inputStream = new FileInputStream(file.getAbsolutePath());
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
metaRetriver.setDataSource(inputStream.getFD());
} catch (IOException e) {
e.printStackTrace();
}
art = metaRetriver.getEmbeddedPicture();
if (art != null) {
bitmap = BitmapFactory
.decodeByteArray(art, 0, art.length);
}
if (bitmap != null) {
mBitmapArray.add(bitmap);
} else {
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.unknown_album);
mBitmapArray.add(icon);
}
}
不要让LinearLayout作为ImageView的父元素,而是让ImageView作为Layout的ROOT元素,如下所示:-
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/coverFlowImage"
android:layout_width="match_parent"
android:layout_height="match_parent" />
在适配器中:-
@Override
public Object instantiateItem(ViewGroup container, final int position) {
LayoutInflater inflater= (LayoutInflater) c.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ImageView imageView = (ImageView) inflater.inflate(R.layout.coverflow_item, container, false);
imageView.setImageBitmap(mBitmapArray.get(position));
container.addView(imageView);
imageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(c, "Clicked::--" + position, Toast.LENGTH_SHORT).show();
mCoverFlowClick.coverClick(position);
}
});
return imageView;
}
如果你想使用一个LinearLayout作为ROOT然后而不是添加ImageView到容器,添加膨胀视图,并返回它在instantiateItem方法。
同时将destroyItem方法改为
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(object);
}
在您的自定义布局文件coverflow_item.xml
中已经包含了ImageView
。
再次尝试使用
在相同的容器中添加container.addView (imageView);
这就是它抛出异常的原因。
要克服它,您需要更改
container.addView(imageView);
container.addView(v);
和这个
return imageView;
return v;
编辑:也修改一下
container.removeView((ImageView) object);
container.removeView((LinearLayout)object)
看这里:
imageView.setImageBitmap(mBitmapArray.get(position));
container.addView(imageView);
每次你添加biotmap时,它都是添加到同一个容器中,现在一个容器怎么能在它上面添加另一个视图呢?所以你需要删除旧视图:像这样
@Override
public void updateSongList(String songName) {
getBitmapArray(songName);
container.removeView((ImageView) object)
mCoverFlowAdapter.notifyDataSetChanged();
}
PS:说明代码,请确保你传递正确的参数如果有帮助请告诉我:)
我最近实现了这个,这是我的instantiateItem方法(使其可读性最小)
@Override
public Object instantiateItem(View collection, int position) {
Evaluation evaluation = evaluations.get(position);
View layout = inflater.inflate(R.layout.layout_evaluation, null);
TextView evaluationSummary = (TextView) layout.findViewById(R.id.evaluation_summary);
evaluationSummary.setText(evaluation.getEvaluationSummary());
((ViewPager) collection).addView(layout);
return layout;
}
@Override
public void destroyItem(View collection, int position, Object view) {
((ViewPager) collection).removeView((View) view);
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
因此,对于显示的页面,我使用位置作为索引从评估列表中获取数据。然后膨胀有视图的布局,我也会添加我的数据。然后我得到TextView来设置评估摘要文本。然后整个布局被添加到ViewPager中。最后,Layout也被返回。
如果有帮助请告诉我