You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过代码获取LinearLayout中指定索引的ProgressBar并设置进度?

解决LinearLayout中指定索引ProgressBar的获取与进度设置问题

问题背景

要实现类似Instagram Stories的顶部进度条效果:动态向LinearLayout中添加多个ProgressBar,之后能获取指定索引的ProgressBar单独设置进度和最大值,但当前代码运行后页面空白,无法实现预期效果。

错误原因

  1. 执行时机错误:OnGlobalLayoutListener是异步回调,在它外部调用linearLayout.getChildCount()时,子控件还未被添加,直接获取索引1的控件会得到null,强转ProgressBar触发空指针异常,导致页面崩溃空白。
  2. 类型转换错误:linearLayout.getChildAt(index)拿到的是你inflate的stories_progress布局根节点LinearLayout,不是里面的ProgressBar,直接强转必然报错。
  3. 冗余循环逻辑:循环里重复获取同一个索引的控件,完全没必要。

修正方案

  1. 将设置ProgressBar进度的代码移到OnGlobalLayoutListener的onGlobalLayout方法内部,确保控件已经添加完成。
  2. 先获取目标索引对应的子LinearLayout,再通过findViewById拿到其中的ProgressBar。
  3. 移除无用的循环,直接定位到目标索引的控件。

修正后的代码

添加并设置ProgressBar的核心代码

linearLayout.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        linearLayout.getViewTreeObserver().removeOnGlobalLayoutListener(this);
        linearLayout.removeAllViews();

        int newWidth = linearLayout.getWidth() / 7;
        int newHeight = linearLayout.getHeight();
        int i = 0;
        while (i < 7) {
            LinearLayout child = (LinearLayout) getLayoutInflater()
                    .inflate(R.layout.stories_progress, linearLayout, false);
            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) child.getLayoutParams();
            lp.width = newWidth;
            lp.height = newHeight;
            linearLayout.addView(child);
            i++;
        }

        // 控件已添加完成,获取索引1的ProgressBar并设置进度
        if (linearLayout.getChildCount() > 1) {
            LinearLayout targetChildLayout = (LinearLayout) linearLayout.getChildAt(1);
            ProgressBar pg = targetChildLayout.findViewById(R.id.stories_progressBar_id);
            pg.setProgress(20);
            pg.setMax(100);
        }
    }
});

stories_progress布局(保持不变)

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:padding="5dp">
    
    <ProgressBar
        android:id="@+id/stories_progressBar_id"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    </ProgressBar>

</LinearLayout>

Activity布局(保持不变)

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/linear_layout_id"
    android:layout_width="match_parent"
    android:layout_height="30dp"
    android:orientation="horizontal"
    tools:context=".stories">

</LinearLayout>

额外优化建议

可以把添加的ProgressBar实例缓存到一个List<ProgressBar>中,后续直接通过列表索引获取,不用每次都从LinearLayout中查找,更高效:

// 定义成员变量
private List<ProgressBar> progressBarList = new ArrayList<>();

// 在onGlobalLayout中添加控件时缓存
LinearLayout child = (LinearLayout) getLayoutInflater()
        .inflate(R.layout.stories_progress, linearLayout, false);
// ...设置布局参数
linearLayout.addView(child);
ProgressBar pb = child.findViewById(R.id.stories_progressBar_id);
progressBarList.add(pb);
i++;

// 后续获取时直接用列表
if (progressBarList.size() > 1) {
    ProgressBar targetPb = progressBarList.get(1);
    targetPb.setProgress(20);
    targetPb.setMax(100);
}

内容的提问来源于stack exchange,提问作者Miguel Bets

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 02:36:18