我有一个ListView,其中包含使用特定布局创建的行。每行都有ProgressBar默认为View.GONE。单击此元素时,我需要在ListView项中显示ProgressBar。问题是,当我单击元素时,ProgressBars不仅在我单击的行中变得可见,而且在其他随机行中也变得可见。这是代码:
创建ListView并设置OnItemClickListener:
private void buildTracklist(ArrayList<Audio> differences, ArrayList<Audio> vkAudioList) {
ArrayList<Map<String, Object>> data = new ArrayList<Map<String, Object>>(vkAudioList.size());
Map<String, Object> m;
int i;
for (i=0;i<vkAudioList.size();i++) {
m = new HashMap<String, Object>();
m.put(AUDIO_ARTIST, vkAudioList.get(i).artist);
m.put(AUDIO_TITLE, vkAudioList.get(i).title);
if (arrayListContainsAudio(differences, vkAudioList.get(i))) {
m.put(AUDIO_DOWNLOADED, R.drawable.image_blank);
} else {
m.put(AUDIO_DOWNLOADED, R.drawable.image_downloaded);
}
data.add(m);
}
String[] from = {AUDIO_TITLE,AUDIO_ARTIST,AUDIO_DOWNLOADED};
int[] to = {R.id.audioTitleTextView,R.id.audioArtistTextView,R.id.isDownloadedImageView};
sAdapter = new SimpleAdapter(this, data, R.layout.tracklist_item, from, to);
audioListView = (ListView) findViewById(R.id.audioListView);
audioListView.setAdapter(sAdapter);
audioListView.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Log.i(TAG,"position="+position+" id="+id);
view.findViewById(R.id.audioItemProgressBar).setVisibility(View.VISIBLE);
//Here I'm passing progressBar further
}
});
}
tracklistItem布局:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/audioTitleTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="2dp"
android:gravity="top|left"
android:text="Title"
android:textSize="24dp" />
<TextView
android:id="@+id/audioArtistTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/audioTitleTextView"
android:layout_marginLeft="5dp"
android:layout_marginTop="2dp"
android:text="Artist"
android:textSize="16sp" />
<ProgressBar
android:id="@+id/audioItemProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_below="@+id/audioArtistTextView"
android:visibility="gone" />
</RelativeLayout>
<ImageView
android:id="@+id/isDownloadedImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|right"
android:src="@drawable/downloaded_backgroundv10"
android:visibility="visible" />
</FrameLayout>
我尝试使用getView()的getChildAt()获取listview项目视图,但发生了同样的问题。感谢您的帮助,抱歉我的英语不好。
更新:我发现progressBar我在滚动ListView时使用更改父项但我需要它在一行中,无论ListView当前在屏幕上的哪个部分。
答案 0 :(得分:0)
你的代码看起来很不错,但我想你应该使用 baseAdapter 而不是 SimpleAdapter 。如果要在每一行上显示或隐藏视图,建议您使用baseAdapter。
这是baseAdapter的示例。首先,创建一个名为MyBaseAdapter的新类。
public class MyBaseAdapter extends BaseAdapter{
private Activity mContext;
private ArrayList<Map<String, Object>> mList;
MyBaseAdapter(Activity context, ArrayList<Map<String, Object>> list){
this.mContext = context;
mList = list;
}
@Override
public int getCount() {
return mList.size();
}
@Override
public Map<String, Object> getItem(int position) {
return mList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
private static class ViewHolder {
public final TextView audioTitleTextView, autioArtistTextView;
public final ImageView isDownloadedImageView;
public final FrameLayout fl;
public ViewHolder(TextView audioArtist, TextView audioTitle,ImageView isDownloaded, FrameLayout fl){
this.autioArtistTextView = audioArtist;
this.audioTitleTextView = audioTitle;
this.isDownloadedImageView = isDownloaded;
this.fl = fl;
}
}
@Override
public View getView(int position, View convertView, ViewGroup parent){
TextView audioTitleTextView,autioArtistTextView;
FrameLayout fl;
ImageView isDownloadedImageView;
/*
* If convertView is not null, tried reuse it
* else create LayoutInflater to pack up the row view
*/
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.tracklistItem , parent,false);
audioTitleTextView = (TextView)convertView.findViewById(R.id.audioTitleTextView);
autioArtistTextView = (TextView)convertView.findViewById(R.id.audioArtistTextView);
isDownloadedImageView = (ImageView)convertView.findViewById(R.id.isDownloadedImageView);
fl = (FrameLayout)convertView.findViewById(R.id.parentFrameLayout);
convertView.setTag(new ViewHolder(autioArtistTextView,audioTitleTextView,isDownloadedImageView));
} else{
ViewHolder holder = (ViewHolder)convertView.getTag();
audioTitleTextView = holder.audioTitleTextView;
autioArtistTextView = holder.autioArtistTextView;
isDownloadedImageView = holder.isDownloadedImageView;
fl = holder.fl;
}
@SuppressWarnings("unchecked")
Map<String, Object> rowItem = getItem(position);
audioTitleTextView.setText(rowItem.get(AUDIO_TITLE));
autioArtistTextView.setText(rowItem.get(AUDIO_ARTIST));
// Change setImageResource to your own image resources
isDownloadedImageView.setImageResource(rowItem.get(AUDIO_DOWNLOADED));
fl.setOnClickListener( new View.OnClickListener(){
@Override
public void onClick(View view){
// hide your progress bar here
}
});
return convertView;
}
然后,将SimpleAdapter更改为以下
MyBaseAdapter sAdapter = new MyBaseAdapter(this, data);
audioListView = (ListView) findViewById(R.id.audioListView);
audioListView.setAdapter(sAdapter);
编辑:将FrameLayout添加到viewHolder并设置FrameLayout OnClickListener
答案 1 :(得分:0)
ListView
使用视图回收。
问题在于,当我点击元素时,ProgressBars不仅在我点击的行中变得可见,而且在其他随机行中也变得可见。
我敢打赌当你滚动视图时会发生这种情况。它的工作方式如下:显示进度条,然后滚动列表。带有进度条的项目滚动到屏幕的可见区域之外。 这是视图被回收的时刻。系统将其与列表视图分离,并再次附加以显示列表的另一行。这就是你再次看到进度条的原因。
怎么办?
您应该在自定义适配器的getView()方法中转换进度条的可见性(可以基于BaseAdapter
)。它是否开启应取决于某些旗帜。
阅读this以了解有关适配器视图中的回收视图的更多信息。
我需要更改进度条的可见性及其进度 点击元素,而不是在我创建listview时。
只需在适配器中定义一个方法,该方法将更改标志的值。然后你可以调用notifyDataSetChanged。
在处理适配器视图时要记住的重要一点是,您更改了基础数据,而不是视图,因为您的列表中可能有几千个项目,但只有少数视图可以处理可见行。
答案 2 :(得分:0)
要了解为什么会出现此问题,您必须先了解ListView
的工作原理。互联网上有很多可用的内容,所以我会在这里简要介绍一下。如果您的适配器中有50个项目,那么这并不意味着ListView
将为您创建50行。相反,它将创建5可能是10可能更多取决于您的屏幕的大小,但不是50!然后当你滚动ListView
时,就会发生这种情况。滚动出屏幕的行将被重用。 getView()
将被调用,您必须再次设置每个属性,否则将重新使用旧属性。在您的情况下,重新使用该行的可见性值。
以下是解决方法:
将可见性数据存储在数据ArrayList
中并覆盖适配器的getView()
方法,然后处理这两种情况:
if(data.isProressVisible){
audioItemProgressBarView.setVisibility(View.VISIBLE);
}else{
audioItemProgressBarView.setVisibility(View.INVISIBLE);
}