Android - 将ProgressBar设置为垂直条而不是水平条?

时间:2010-10-13 17:38:47

标签: android

我正在尝试将ProgressBar用作计量显示器。我认为这将是一个简单的任务,并认为ProgressBar有一个属性设置为垂直,但我没有看到任何东西。

此外,我希望能够在条形侧面显示标尺,如清楚地指示当前水平。

指针赞赏 - 谢谢!

15 个答案:

答案 0 :(得分:53)

我最近遇到了对垂直进度条的需求,但无法使用现有的Progress Bar小部件找到解决方案。我遇到的解决方案通常需要扩展当前的Progress Bar或者一个全新的类。我不相信推出一个新课程来实现简单的方向改变是必要的。

本文介绍了一个简单,优雅,最重要的是,实现垂直进度条的无懈可击的解决方案。 我将跳过解释并简单地提供一个千篇一律的解决方案。如果您需要更多详细信息,请随时与我联系或在下面发表评论。

在drawable文件夹中创建一个xml(不是drawable-hdpi或drawable-mdpi - 将它放在drawable中)。在本例中,我调用了我的xml vertical_progress_bar.xml

以下是xml文件中的内容:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:id="@android:id/background">
    <shape>
      <corners android:radius="5dip" />
      <gradient
        android:startColor="#ff9d9e9d"
        android:centerColor="#ff5a5d5a"
        android:centerY="0.75"
        android:endColor="#ff747674"
        android:angle="180"
      />
    </shape>
  </item>
  <item android:id="@android:id/secondaryProgress">
    <clip android:clipOrientation="vertical" android:gravity="bottom">
      <shape>
        <corners android:radius="5dip" />
        <gradient
          android:startColor="#80ffd300"
          android:centerColor="#80ffb600"
          android:centerY="0.75"
          android:endColor="#a0ffcb00"
          android:angle="180"
        />
      </shape>
    </clip>
  </item>
  <item android:id="@android:id/progress">
    <clip android:clipOrientation="vertical" android:gravity="bottom">
      <shape>
        <corners android:radius="5dip" />
        <gradient
          android:startColor="#ffffd300"
          android:centerColor="#ffffb600"
          android:centerY="0.75"
          android:endColor="#ffffcb00"
          android:angle="180"
        />
      </shape>
    </clip>
</item>
</layer-list>

创建一个名为styles.xml的xml文件,并将其放在res / values中。如果您的项目已在res / values中包含styles.xml,则跳过此步骤。

修改styles.xml文件并将以下代码附加到文件末尾:

<style name="Widget">
</style>
<style name="Widget.ProgressBar">
  <item name="android:indeterminateOnly">true</item>
  <item name="android:indeterminateBehavior">repeat</item>
  <item name="android:indeterminateDuration">3500</item>
  <item name="android:minWidth">48dip</item>
  <item name="android:maxWidth">48dip</item>
  <item name="android:minHeight">48dip</item>
  <item name="android:maxHeight">48dip</item>
</style>
<style name="Widget.ProgressBar.Vertical">
  <item name="android:indeterminateOnly">false</item>
  <item name="android:progressDrawable">@drawable/progress_bar_vertical</item>
  <item name="android:indeterminateDrawable">@android:drawable/progress_indeterminate_horizontal</item>
  <item name="android:minWidth">1dip</item>
  <item name="android:maxWidth">12dip</item>
</style>

将新的垂直进度条添加到布局中。这是一个例子:

<ProgressBar
  android:id="@+id/vertical_progressbar"
  android:layout_width="12dip"
  android:layout_height="300dip"
  style="@style/Widget.ProgressBar.Vertical"
/>

您应该只需要在项目中使用垂直进度条。 (可选)您可能具有用于进度条的自定义可绘制九补丁图像。您应该在progress_bar_vertical.xml文件中进行适当的更改。 我希望这可以帮助你完成你的项目!

答案 1 :(得分:29)

您必须创建自己的自定义进度条。

在你的xml中添加这个布局:

 <com.example.component.VerticalProgressBar 
        style="?android:attr/progressBarStyleHorizontal"
        android:id="@+id/verticalRatingBar1"
        android:layout_width="wrap_content"
        android:progress="50"
        android:layout_height="fill_parent" />

<强> VerticalProgressBar.java

public class VerticalProgressBar extends ProgressBar{
    private int x, y, z, w;

    @Override
    protected void drawableStateChanged() {
        // TODO Auto-generated method stub
        super.drawableStateChanged();
    }

    public VerticalProgressBar(Context context) {
        super(context);
    }

    public VerticalProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public VerticalProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(h, w, oldh, oldw);
        this.x = w;
        this.y = h;
        this.z = oldw;
        this.w = oldh;
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec,
            int heightMeasureSpec) {
        super.onMeasure(heightMeasureSpec, widthMeasureSpec);
        setMeasuredDimension(getMeasuredHeight(), getMeasuredWidth());
    }

    protected void onDraw(Canvas c) {
        c.rotate(-90);
        c.translate(-getHeight(), 0);
        super.onDraw(c);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (!isEnabled()) {
            return false;
        }

        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:

            setSelected(true);
            setPressed(true);
            break;
        case MotionEvent.ACTION_MOVE:
            setProgress(getMax()
                    - (int) (getMax() * event.getY() / getHeight()));
            onSizeChanged(getWidth(), getHeight(), 0, 0);

            break;
        case MotionEvent.ACTION_UP:
            setSelected(false);
            setPressed(false);
            break;

        case MotionEvent.ACTION_CANCEL:
            break;
        }
        return true;
    }

    @Override
    public synchronized void setProgress(int progress) {

        if (progress >= 0)
            super.setProgress(progress);

        else
            super.setProgress(0);
        onSizeChanged(x, y, z, w);

    }
}

或:            Jagsaund解决方案也很完美。

答案 2 :(得分:16)

我知道这是一个老帖子,但我发现这个问题的一个非常简单的解决方案可能对某些人有所帮助。 首先,创建一个progress_drawable_vertical.xml,如下所示:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
    <color android:color="#777" />
</item>
<item android:id="@android:id/progress">
    <clip
        android:clipOrientation="vertical"
        android:gravity="bottom">
        <shape>
            <gradient
                android:startColor="#00FF00"
                android:centerColor="#FFFF00"
                android:endColor="#FF0000"
                android:angle="90" />
        </shape>
    </clip>
</item>
</layer-list>

然后在progressBar中使用它:

<ProgressBar
    android:id="@+id/progress_bar"
    style="@android:style/Widget.ProgressBar.Horizontal"
    android:layout_centerInParent="true"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:max="100"
    android:progress="33"
    android:progressDrawable="@drawable/progress_drawable_vertical" />

我还创建了progress_drawable_horizo​​ntal.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@android:id/background">
    <color android:color="#777" />
</item>
<item android:id="@android:id/progress">
    <clip
        android:clipOrientation="horizontal"
        android:gravity="left">
        <shape>
            <gradient
                android:startColor="#00FF00"
                android:centerColor="#FFFF00"
                android:endColor="#FF0000" />
        </shape>
    </clip>
</item>
</layer-list>

以mantain为目标,在progress_drawable_vertical.xml中定义了相同的样式

这里的关键是正确使用android:clipOrientationandroid:gravity

我找到了这个解决方案jagsaund,解决方案的核心与docs here类似,但更简单一点。

答案 3 :(得分:4)

我找到了最好的(最简单和最通用的)解决方案:)

这是一篇很老的帖子,但是我很难找到这么简单的解决方案,所以我想我应该发布它。

只需使用scale-drawable(或9个补丁,如果需要),不需要任何其他代码。

示例:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">  

    <item android:id="@android:id/background" android:drawable="@color/transparent"/>  

    <item android:id="@android:id/progress">
        <scale android:scaleGravity="bottom" android:scaleWidth="0%" android:scaleHeight="100%">
            <shape >
                <solid android:color="@color/blue"/>
                <corners android:topRightRadius="1dp" android:topLeftRadius="1dp"/>
            </shape>
        </scale>
    </item>
</layer-list>  

当然还有普通代码:

<ProgressBar
    android:id="@+id/progress_bar"
    style="@android:style/Widget.ProgressBar.Horizontal"
    android:layout_width="24dp"
    android:layout_height="match_parent"
    android:max="1000"
    android:progress="200"
    android:progressDrawable="@drawable/progress_scale_drawable" />  

注意scale-drawable的xml行(魔术行):

android:scaleGravity="bottom"  //scale from 0 in y axis (default scales from center Y)  
android:scaleWidth="0%"        //don't scale width (according to 'progress')
android:scaleHeight="100%"     //do scale the height of the drawable

答案 4 :(得分:2)

This perfectly works

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@android:id/background">
        <shape>
            <gradient
                android:startColor="#DDDDDD"
                android:centerColor="#DDDDDD"
                android:centerY="0.75"
                android:endColor="#DDDDDD"
                android:angle="270"
                />
        </shape>
    </item>

    <item
        android:id="@android:id/progress">
        <clip
            android:clipOrientation="vertical"
            android:gravity="top">
            <shape>
                <gradient
                    android:angle="0"
                    android:startColor="#302367"
                    android:centerColor="#7A5667"
                    android:endColor="#C86D67"/>
            </shape>
        </clip>
    </item>
</layer-list>

    <ProgressBar
            android:id="@+id/progress_bar"
            style="?android:attr/progressBarStyleHorizontal"
            android:layout_width="5dp"
            android:layout_height="match_parent"`enter code here`
            android:progressDrawable="@drawable/progress_dialog"/>

答案 5 :(得分:1)

要利用ProgressBar并使其垂直,您必须创建自己的自定义View,扩展ProgressBar视图并覆盖onDraw()方法。这将允许您以反方向绘制它。请查看ProgressBar.onDraw()的{​​{3}}(位于链接底部),以获取有关如何执行此操作的帮助。最好的情况是,您只需交换一些x和y变量。

答案 6 :(得分:1)

创建进度条(我将代码从c#转换为java,因此可能不是100%正确)

ProgressBar progBar = new ProgressBar(Context, null, Android.resource.attribute.progressDrawable);
progBar.progressDrawable = ContextCompat.getDrawable(Context, resource.drawable.vertical_progress_bar);
progBar.indeterminate = false;

vertical_progress_bar.xml

<?xml version="1.0" encoding="utf-8"?>
    <layer-list xmlns:android="http://schemas.android.com/apk/res/android" >

      <item android:id="@android:id/background">
        <shape>
          <solid android:color="@color/grey" />

          <corners android:radius="20dip" />
        </shape>
      </item>
      <item android:id="@android:id/progress">
        <scale
            android:drawable="@drawable/vertical_progress_bar_blue_progress"
            android:scaleHeight="100%"
            android:scaleGravity="bottom"/>
      </item>
    </layer-list>

<强> vertical_progress_bar_blue_progress.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

  <corners
      android:radius="20dip" />

  <solid android:color="@color/ProgressBarFourth" />

</shape>

使您的栏垂直的是scaleHeight中的scaleGravityvertical_progress_bar.xml属性。

最终看起来像这样:

enter image description here

答案 7 :(得分:1)

简单易行的方法:

只需将视图添加到 LinearLayout 并对其进行缩放。

enter image description here

<LinearLayout
        android:layout_width="4dp"
        android:layout_height="300dp"
        android:background="@color/md_green_50"
        android:orientation="vertical">
    <View
            android:id="@+id/progressView"
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_gravity="top"
            android:layout_weight="1"
            android:background="@color/md_green_500"
            android:scaleY="0.0" />
</LinearLayout>

将视图的 pivotY 设置为零:

progressView.pivotY = 0F

现在您可以在 scaleY0F 之间使用 1F 填充进度:

progressView.scaleY = 0.3F

奖励: 使用 animate() 动画进度:

progressView.animate().scaleY(0.3F).start()

答案 8 :(得分:0)

我有确切的问题。创建自定义类(扩展ProgressBar)将创建难以维护的代码。使用自定义样式将导致与新操作系统(例如棒棒糖)不同主题的兼容性问题

最后,我只是将旋转动画应用于水平进度条。灵感来自Pete

  1. 在布局xml中创建标记,如普通水平进度条。
  2. 确保旋转后ProgressBar的大小和位置是您想要的。 (也许设置负边际会有所帮助)。在我的代码中,我从0,0。
  3. 旋转视图
  4. 使用以下方法旋转并设置新进度。
  5. 代码:

    private void setProgress(final ProgressBar progressBar, int progress) {
        progressBar.setWillNotDraw(true);
        progressBar.setProgress(progress);
        progressBar.setWillNotDraw(false);
        progressBar.invalidate();
    }
    
    private void rotateView(final View v, float degree) {
        Animation an = new RotateAnimation(0.0f, degree);
        an.setDuration(0);
        an.setRepeatCount(0);
        an.setFillAfter(true);               // keep rotation after animation
        v.setAnimation(an);
    }
    

答案 9 :(得分:0)

简单的progrebar图片视图

示例

viewHolder.proBarTrueImage.setMaximalValue(147);
viewHolder.proBarTrueImage.setLevel(45);
viewHolder.proBarTrueImage.setColorResource(R.color.corner_blue);

简单的课程

public class ProgressImageView extends ImageView {

private Context mContext;
private Paint paint;
private RectF rectf;

private int maximalValue = 1;
private int level = 0;
private int width;
private int height;

public ProgressImageView(Context context) {
    super(context);
    init(context, null, 0);
}

public ProgressImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
    init(context, attrs, 0);
}

public ProgressImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init(context, attrs, defStyleAttr);
}

private  void init(Context context, AttributeSet attrs, int defStyleAttr){

    mContext = context;
    paint = new Paint();
    rectf = new RectF();
    paint.setColor(Color.GRAY);
    paint.setStyle(Paint.Style.FILL);
};

@Override
protected void onDraw(Canvas canvas) {

    float dif = (float) height / (float) maximalValue;
    int newHeight = height - (int) (dif * level);

    rectf.set(0,newHeight, width, height);
    canvas.drawRect(rectf, paint);

    super.onDraw(canvas);
}

@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
    super.onSizeChanged(w, h, oldw, oldh);
    this.width = w;
    this.height = h;
}

public void setMaximalValue(int maximalValue) {
    this.maximalValue = maximalValue;
    invalidate();
}

public void setLevel(int level) {
    this.level = level;
    invalidate();
}

public void setColorResource(int color) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        color = mContext.getResources().getColor(color,mContext.getTheme());
    }else {
        color = mContext.getResources().getColor(R.color.corner_blue);
    }

    setColor(color);
}

public void setColor(int color){
    if (paint != null){
        paint.setColor(color);
        invalidate();
    }
}

}

答案 10 :(得分:0)

enter link description here

**请检查此链接,我尝试使用类似的东西,您也可以使用stepper来满足需求,Github上很少有关于如何在ANDROID STUDIO中使用STEPPER的项目**

答案 11 :(得分:0)

将此添加到xml代码         android:rotation =“ 90”         android:transformPivotX =“ 0dp” 这就是进度栏xml的外观

<ProgressBar
    android:id="@+id/progressBar6"
    style="?android:attr/progressBarStyleHorizontal"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:rotation="90"
    android:transformPivotX="0dp"
    tools:layout_editor_absoluteX="101dp"
    tools:layout_editor_absoluteY="187dp" />

答案 12 :(得分:0)

这是一个简单的解决方案,只需旋转进度条

android:rotation="270"

答案 13 :(得分:-1)

默认情况下不支持垂直进度条。

答案 14 :(得分:-1)

<ProgressBar
        android:id="@+id/battery_pb"
        android:rotation="270"
        android:progress="100"
...
/>

使用android:rotation =“270”到100%就像从下到上或者android:rotation =“90”到100%就像从上到下