求助:如何实现点击ListView Item时显示30秒平滑进度条
实现ListView Item点击后显示30秒平滑进度条的方案
针对你的需求,我整理了一套可行的实现思路,结合你现有代码一步步修改:
1. 给列表项布局添加进度条
首先打开你的Resource.Layout.List布局文件,添加一个水平进度条,默认隐藏:
<!-- 放在现有布局的合适位置,比如TextView下方 --> <ProgressBar android:id="@+id/itemProgressBar" android:layout_width="match_parent" android:layout_height="wrap_content" android:visibility="gone" style="@android:style/Widget.ProgressBar.Horizontal"/>
2. 在ListAdapter中维护进度状态
因为ListView会复用View,不能直接把进度存在View里,得给适配器加两个集合跟踪每个Item的状态:
public class ListAdapter : ArrayAdapter { // 记录每个位置的进度值,初始为0 private List<int> _progressList; // 记录哪个位置正在加载,防止重复点击 private HashSet<int> _loadingPositions = new HashSet<int>(); private List<GeraeteModel> Geraetelist; // 假设你的数据模型是这个类型 private Context _context; public ListAdapter(Context context, int resource, List<GeraeteModel> objects, string serverIp) : base(context, resource, objects) { Geraetelist = objects; _context = context; // 初始化进度列表,每个Item初始进度0 _progressList = new List<int>(Enumerable.Repeat(0, objects.Count)); } // 启动指定位置的进度加载 public async Task StartProgress(int position) { if (_loadingPositions.Contains(position)) return; _loadingPositions.Add(position); // 进度从0到100,耗时30秒,每100ms更新一次保证平滑 int totalSteps = 300; // 30秒 = 300*100ms int step = 100 / totalSteps; for (int i = 0; i <= totalSteps; i++) { int currentProgress = i * step; _progressList[position] = currentProgress; // 刷新列表更新进度 NotifyDataSetChanged(); await Task.Delay(100); } // 加载完成后重置状态,隐藏进度条 _progressList[position] = 0; _loadingPositions.Remove(position); NotifyDataSetChanged(); } public override View GetView(int position, View convertView, ViewGroup parent) { View v = convertView; if (v == null) { LayoutInflater inflater = (LayoutInflater)_context.GetSystemService(Context.LayoutInflaterService); v = inflater.Inflate(Resource.Layout.List, parent, false); } // 你的原有代码... v.FindViewById<ImageView>(Resource.Id.typeImageView).SetImageResource(Resource.Drawable.Icon); v.FindViewById<TextView>(Resource.Id.numberTextView).Text = Geraetelist[position].geraeteplatz; v.FindViewById<TextView>(Resource.Id.descriptionTextView).Text = Geraetelist[position].geraeteinformation; ImageView iv = v.FindViewById<ImageView>(Resource.Id.bspImageView); iv.SetImageResource(Geraetelist[position].bespielt == "N" ? Resource.Drawable.greenPoint : Resource.Drawable.redPoint); // 新增:处理进度条的显示和进度更新 ProgressBar progressBar = v.FindViewById<ProgressBar>(Resource.Id.itemProgressBar); if (_loadingPositions.Contains(position)) { progressBar.Visibility = ViewStates.Visible; progressBar.Progress = _progressList[position]; } else { progressBar.Visibility = ViewStates.Gone; progressBar.Progress = 0; } return v; } }
3. 修改Activity中的Item点击事件
在TableActivity的OnItemClick方法里,调用适配器的StartProgress方法启动对应位置的进度条:
private async void OnItemClick(object sender, AdapterView.ItemClickEventArgs e) { var geraete = geraeteliste.CurrentGeraeteliste[e.Position]; if (geraete.bespielt == "J") return; // 这里保留你的其他业务逻辑... // 启动对应位置的进度条 if (adapter is ListAdapter listAdapter) { await listAdapter.StartProgress(e.Position); } }
关键注意点
- ListView复用问题:必须用集合跟踪每个Item的进度和加载状态,不能直接依赖View的状态,否则滚动时进度条会错乱。
- 防止重复点击:用
HashSet记录正在加载的位置,避免同一个Item被多次点击触发多个进度任务。 - 平滑度控制:通过每100ms更新一次进度,保证进度条的平滑动画效果,你也可以根据需求调整更新间隔。
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

