【问题标题】:ProgressBar under Action Bar操作栏下的进度条
【发布时间】:2012-12-05 17:17:39
【问题描述】:

问题摘要:我怎样才能将ProgressBar 集成到ActionBar 中,就像在Chrome 应用程序上一样?

详情:看看这个来自 Chrome 的截图:

我想创建一个像这样的操作栏。就在操作栏下方,有一个根据页面加载填充的进度栏。我从许多应用程序(例如 Feedly)中看到了这个示例,但我无法创建自己的实现。我尝试使用 Android 自己的 API 来创建它:

@Override
protected void onCreate(Bundle savedInstanceState) {
    //Request Permission to display the Progress Bar...
    this.requestWindowFeature(Window.FEATURE_PROGRESS);
            this.setWindowContentView(R.layout.activity_main)
    super.onCreate(savedInstanceState);

    this.setProgressBarIndeterminate(true);
}

但此代码仅导致 ProgressBar 操作栏上显示,如下所示:

那么,我怎样才能让我的 ProgressBar 出现在操作栏下方,就像在 Chrome 应用程序上一样?

【问题讨论】:

标签: android android-actionbar android-progressbar


【解决方案1】:

从以下类扩展活动,在每个类的顶部(在 ActionBar 下方)有一个 ProgressBar,以及一个 getProgressBar() 方法:

父类:

public abstract class ProgressActivity extends Activity {
    private ProgressBar mProgressBar;

    @Override
    public void setContentView(View view) {
        init().addView(view);
    }

    @Override
    public void setContentView(int layoutResID) {
        getLayoutInflater().inflate(layoutResID,init(),true);
    }

    @Override
    public void setContentView(View view, ViewGroup.LayoutParams params) {
        init().addView(view,params);
    }

    private ViewGroup init(){
        super.setContentView(R.layout.progress);
        mProgressBar = (ProgressBar) findViewById(R.id.activity_bar);
        return (ViewGroup) findViewById(R.id.activity_frame);
    }

    protected ProgressBar getProgressBar(){
        return mProgressBar;
    }
}

布局(progress.xml):

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical"
    android:layout_width="match_parent" android:layout_height="match_parent">
<ProgressBar android:id="@+id/activity_bar"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-8dp"
    style="@android:style/Widget.DeviceDefault.ProgressBar.Horizontal"
    />
  <FrameLayout android:id="@+id/activity_frame"
      android:layout_width="match_parent"
      android:layout_height="fill_parent"
      />
</LinearLayout>

【讨论】:

  • 它在大多数情况下都有效。 ProgressBar 看起来确实与操作栏分开。我必须将android:layout_marginTop="-8dp" 添加到 ProgressBar 以模拟“阴影”效果。但是对于这种方法,将其添加到主布局本身可能更有效。然而现在它按预期工作。感谢您的破解。
  • @zubietaroberto 是的,如果您只是将其用于一项活动,则可以将其添加到主布局中。如果您希望多个活动具有此功能,您可以扩展上面显示的类。
  • 它对我有用,但进度条出现在标签主机下方,我如何才能使其位于标签主机上方和操作栏下方?
【解决方案2】:

嗯,我为我的一个宠物应用程序做了类似的事情,但不确定这是唯一的方法还是最好的方法,但它确实有效。

首先,使用覆盖操作栏,然后将背景可绘制对象设置为“null”,以便覆盖操作栏是透明的。

现在在您的活动布局中,将根视图的上边距设置为“操作栏高度”您可以这样做。

<RelativeLayout
    ...
    android:layout_marginTop="?android:attr/actionBarSize" />

现在该操作不会隐藏您的任何活动内容。

您现在要做的下一件事是 - 在根视图的顶部添加一个标题视图,其高度与操作栏相同。为其设置背景颜色。现在这将是您的操作栏的颜色,并且由于操作栏在此标题视图的顶部完美对齐。

现在您可以轻松地在标题视图中放置一个进度条,并将其与标题视图的底部对齐。对用户来说,这看起来好像进度条在操作栏本身上,就像 chrome ..

【讨论】:

    【解决方案3】:

    请使用以下代码。只需在进度条中使用一种默认样式为style="?android:attr/progressBarStyleHorizontal"

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/hello_world" />
        <ProgressBar 
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            style="?android:attr/progressBarStyleHorizontal"
            android:indeterminate="true"
    
            />
    
    </RelativeLayout>
    

    【讨论】:

      【解决方案4】:

      我对上面接受的答案并不完全满意,所以我自己做了一些额外的研究。

      我相信他们使用的技巧是他们检索了名为DecorView 的视图层次结构中的顶视图,并在其中添加了进度条。这样,进度条会同时显示在操作栏和内容区域上。请注意,SD 的回答是将进度条放入内容区域并从实际内容中“窃取”空间,这可能会导致意外结果。

      此实现的示例屏幕截图

      代码

      只需将此代码放入某些活动的onCreate 方法中,它应该可以工作:

      // create new ProgressBar and style it
      final ProgressBar progressBar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);
      progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
      progressBar.setProgress(65);
      
      // retrieve the top view of our application
      final FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
      decorView.addView(progressBar);
      
      // Here we try to position the ProgressBar to the correct position by looking
      // at the position where content area starts. But during creating time, sizes 
      // of the components are not set yet, so we have to wait until the components
      // has been laid out
      // Also note that doing progressBar.setY(136) will not work, because of different
      // screen densities and different sizes of actionBar
      ViewTreeObserver observer = progressBar.getViewTreeObserver();
      observer.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
          @Override
          public void onGlobalLayout() {
              View contentView = decorView.findViewById(android.R.id.content);
              progressBar.setY(contentView.getY() - 10);
      
              ViewTreeObserver observer = progressBar.getViewTreeObserver();
              observer.removeOnGlobalLayoutListener(this);
          }
      });
      

      您可以使用 LayoutParams 的高度参数来设置progressBar 更宽或更窄,但您可能需要调整-10 偏移量。

      造型

      不幸的是,你可以看到进度条丑陋的灰色背景。要删除它,只需按 id 搜索背景并尝试隐藏它是行不通的。要删除背景,我必须创建与系统版本相同的 drawble 并删除背景项。

      TL;DR:创建文件 progress_horizontal_holo_no_background_light.xml 并粘贴此可绘制对象:

      <?xml version="1.0" encoding="utf-8"?>
      <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
      
          <item android:id="@android:id/secondaryProgress">
              <scale android:scaleWidth="100%"
                     android:drawable="@drawable/progress_secondary_holo_light" />
          </item>
      
          <item android:id="@android:id/progress">
              <scale android:scaleWidth="100%"
                     android:drawable="@drawable/progress_primary_holo_light" />
          </item>
      
      </layer-list>
      

      sdk/platforms/android-xx/data/res/drawable-xxx/复制适当的.png drawables到你的项目,然后在你可以添加的代码中:

      progressBar.setProgressDrawable(getResources().getDrawable(R.drawable.progress_horizontal_holo_no_background_light));
      

      额外:不确定的进度条

      不定进度条的 Pre-KitKat 版本非常丑陋和滞后。 您可以下载名为ButteryProgressBar 的新平滑进度条。只需在谷歌上搜索它(我不能发布更多链接,因为我是新来的:[),将类添加到您的项目中,您可以简单地用这段代码替换以前的 ProgressBar 并获得清晰的不确定进度条:

      final ButteryProgressBar progressBar = new ButteryProgressBar(this);
      progressBar.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, 24));
      

      您可能还需要简化此代码:

      final TypedArray ta = c.obtainStyledAttributes(attrs, R.styleable.ButteryProgressBar);
      try {
          mBarColor = ta.getColor(R.styleable.ButteryProgressBar_barColor,
                  c.getResources().getColor(android.R.color.holo_blue_light));
          mSolidBarHeight = ta.getDimensionPixelSize(
                  R.styleable.ButteryProgressBar_barHeight,
                  Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity));
          mSolidBarDetentWidth = ta.getDimensionPixelSize(
                  R.styleable.ButteryProgressBar_detentWidth,
                  Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity));
      } finally {
          ta.recycle();
      }
      

      到此代码:

      mBarColor = c.getResources().getColor(android.R.color.holo_blue_light);
      mSolidBarHeight = Math.round(DEFAULT_BAR_HEIGHT_DP * mDensity);
      mSolidBarDetentWidth = Math.round(DEFAULT_DETENT_WIDTH_DP * mDensity);
      

      希望我能帮上忙:)

      【讨论】:

      • ViewTreeObserver 类型的 removeGlobalOnLayoutListener(ViewTreeObserver.OnGlobalLayoutListener) 方法已弃用
      • @ArjunU。我们应该改用什么>
      • 我已经用ActionBarActivity 测试了不确定的进度条(ButteryProgressBar),但它不起作用。如何在ActionBar/Toolbar 下放置不确定的进度条?这是我正在使用的布局:stackoverflow.com/a/26440880/1480019
      • @GerritHoekstra:如果getSupportActionBar().getHeight() 函数有效,那么您就快到了。 progressBar.setY() 函数设置相对于屏幕顶部的位置,包括状态栏。所以你要做的就是setY(supportActionBarHeight + Math.ceil(25 * context.getResources().getDisplayMetrics().density))。状态栏高 25 像素 (mdpi) 并以更高的密度 (hdpi/xhdpi/...) 进行缩放。试一试并告诉我它是否有效。
      【解决方案5】:

      我已经从这个线程以及 StackOverflow 上的其他线程编译了代码,并创建了一个可用于实现 ButteryProgessbar 以及“下拉刷新”的项目。 https://github.com/pauldmps/Gmail-like-Pull-Down-to-Refresh

      请随意在您的应用程序中使用代码。

      非常感谢你们。

      【讨论】:

        【解决方案6】:

        现在这是可以使用SwipeRefreshLayout 获得的本机行为。

        您可以使用SwipeRefreshLayout 包裹您的可滚动视图,然后您只需要监听 onRefresh 事件:

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        
            swipeLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container);
            swipeLayout.setOnRefreshListener(this);
            swipeLayout.setColorScheme(android.R.color.holo_blue_bright, 
                    android.R.color.holo_green_light, 
                    android.R.color.holo_orange_light, 
                    android.R.color.holo_red_light);
        }
        
        
        @Override public void onRefresh() {
            new Handler().postDelayed(new Runnable() {
                @Override public void run() {
                    swipeLayout.setRefreshing(false);
                }
            }, 5000);
        }
        

        一个不错的简单教程可以在this blog找到。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-04-03
          • 2014-04-21
          • 1970-01-01
          • 1970-01-01
          • 2014-01-02
          • 1970-01-01
          • 2017-07-30
          • 1970-01-01
          相关资源
          最近更新 更多