Android - 将 ProgressBar 设置为垂直条而不是水平条?
Posted
技术标签:
【中文标题】Android - 将 ProgressBar 设置为垂直条而不是水平条?【英文标题】:Android - set a ProgressBar to be a vertical bar instead of horizontal? 【发布时间】:2010-10-13 17:38:46 【问题描述】:我正在尝试将 ProgressBar 用作类似计量的显示器。我认为这将是一项简单的任务,并认为 ProgressBar 有一个属性可以设置为垂直,但我什么也没看到。
此外,我希望能够在条形图的一侧显示类似标尺的指示器,以清楚地指示当前级别。
感谢指点 - 谢谢!
【问题讨论】:
android-coding.blogspot.co.uk/2013/02/… 【参考方案1】:我最近遇到了对垂直进度条的需求,但无法使用现有的进度条小部件找到解决方案。我遇到的解决方案通常需要对当前进度条进行扩展或在其中添加一个全新的类。我不相信推出一个新类来实现简单的方向改变是必要的。
本文介绍了一种简单、优雅且最重要的是实现垂直进度条的无黑客解决方案。 我将跳过解释,简单地提供一个千篇一律的解决方案。如果您需要更多详细信息,请随时与我联系或在下面发表评论。
在你的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_
android:layout_
style="@style/Widget.ProgressBar.Vertical"
/>
这就是您在项目中使用垂直进度条所需要做的一切。或者,您可能有用于进度条的自定义可绘制九个补丁图像。您应该在 progress_bar_vertical.xml 文件中进行适当的更改。 我希望这对您的项目有所帮助!
【讨论】:
您博文中的示例不完整,有用户提出您没有回答的问题。 @jagsaund 给定链接上没有文件 @jagasund:链接已失效 抱歉死链接。我的博客已经关闭了一段时间,但我找到了一个旧副本。所以这只是一个副本。希望对您有所帮助! 对于 Lollipop 中使用的主题,恐怕这与水平进度条的默认行为不一致。使用它可能不是一个好主意:(【参考方案2】:您必须创建自己的自定义进度条。
在您的 xml 中添加此布局:
<com.example.component.VerticalProgressBar
style="?android:attr/progressBarStyleHorizontal"
android:id="@+id/verticalRatingBar1"
android:layout_
android:progress="50"
android:layout_ />
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 解决方案也在完善中。
【讨论】:
不幸的是,进度条在达到等于栏宽度的高度后没有正确更新(从顶部开始),我认为有些 x/y 混淆了,但我不能找到一个简单的修复,使用 jagsaund 解决方案 添加无效();在 onSizeChanged() 之后;以避免上述渲染问题。【参考方案3】:我知道这是一篇旧帖子,但我找到了一个非常简单的解决方案来解决这个问题,也许可以帮助别人。 首先像这样创建一个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_
android:layout_
android:max="100"
android:progress="33"
android:progressDrawable="@drawable/progress_drawable_vertical" />
我还创建了一个progress_drawable_horizontal.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>
与progress_drawable_vertical.xml中定义的风格保持一致
这里的关键是android:clipOrientation
和android:gravity
的正确使用。
我找到了here这个解决方案,这个解决方案的核心类似于jagsaund,但更简单一点。
【讨论】:
太棒了,使用它我还能够创建一个从下到上的圆形填充进度。【参考方案4】:我找到了可能是最好(最简单和最通用)的解决方案:)
这是一个旧帖子,但我很难找到这个如此简单的解决方案,所以我想我应该发布它..
只需使用scale-drawable
(如果需要,也可以使用 9-patch),无需任何其他代码。
示例:
<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_
android:layout_
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
【讨论】:
【参考方案5】: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_
android:layout_`enter code here`
android:progressDrawable="@drawable/progress_dialog"/>
【讨论】:
【参考方案6】:创建进度条(我将代码从 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>
使您的条形垂直的是vertical_progress_bar.xml
中的scaleHeight
和scaleGravity
属性。
它最终看起来像这样:
【讨论】:
你是天才老板【参考方案7】:将此添加到 xml 代码中 机器人:旋转=“90” 安卓:transformPivotX="0dp" 所以这就是您的进度条 xml 的外观
<ProgressBar
android:id="@+id/progressBar6"
style="?android:attr/progressBarStyleHorizontal"
android:layout_
android:layout_
android:rotation="90"
android:transformPivotX="0dp"
tools:layout_editor_absoluteX="101dp"
tools:layout_editor_absoluteY="187dp" />
【讨论】:
【参考方案8】:这是一个简单的解决方案,只需旋转你的进度条
android:rotation="270"
【讨论】:
经过一些实验,我能够让它工作。在 LinearLayout 中,android:layout_width 必须是“fill_parent”,我不得不稍微调整一下 layout_weight 以使其扩展到我想要的位置。但是,嘿 - 它的工作原理!而且比制作定制的东西要简单得多。谢谢! 它只适用于方形布局。【参考方案9】:要利用 ProgressBar 并使其垂直,您必须创建自己的自定义 View 扩展 ProgressBar 视图并覆盖 onDraw() 方法。这将允许您以相反的方向绘制它。查看ProgressBar.onDraw()
的source code(位于链接底部)以获取有关如何执行此操作的帮助。最佳情况下,您只需交换几个 x 和 y 变量。
【讨论】:
【参考方案10】:我有确切的问题。制作自定义类(扩展 ProgressBar)将创建难以维护的代码。使用自定义样式将导致与新操作系统的不同主题(例如棒棒糖)的兼容性问题
最后,我只是将旋转动画应用到水平进度条。灵感来自Pete。
-
像普通水平进度条一样在布局 xml 中创建标签。
确保 ProgressBar 的大小和位置在旋转后是您想要的。 (也许设置负边距会有所帮助)。在我的代码中,我从 0,0 旋转视图。
使用以下方法旋转并设置新进度。
代码:
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);
【讨论】:
【参考方案11】:简单易行的方法:
只需将视图添加到 LinearLayout
并对其进行缩放。
<LinearLayout
android:layout_
android:layout_
android:background="@color/md_green_50"
android:orientation="vertical">
<View
android:id="@+id/progressView"
android:layout_
android:layout_
android:layout_gravity="top"
android:layout_weight="1"
android:background="@color/md_green_500"
android:scaleY="0.0" />
</LinearLayout>
将 View 的 pivotY
设置为零:
progressView.pivotY = 0F
现在您可以在0F
和1F
之间使用scaleY
填写进度:
progressView.scaleY = 0.3F
奖励:
使用animate()
动画进度:
progressView.animate().scaleY(0.3F).start()
【讨论】:
【参考方案12】:简单的进度条图像视图
例子
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();
【讨论】:
【参考方案13】:<ProgressBar
android:id="@+id/battery_pb"
android:rotation="270"
android:progress="100"
...
/>
使用 android:rotation="270" 到 100% 是从下到上或 android:rotation="90" 到 100% 是从上到下
【讨论】:
不起作用,进度条旋转但高度仍然很小 进行了一些实验,但我能够完成这项工作。在 LinearLayout 中,android:layout_width 必须是“fill_parent”,我不得不稍微调整一下 layout_weight 以使其扩展到我想要的位置。但是,它确实有效。谢谢!这比编写自定义小部件要简单得多。【参考方案14】:enter link description here
**查看此链接,我正在尝试使用类似的东西,您也可以使用 stepper 来满足您的要求,Github 上很少有关于如何在 ANDROID STUDIO 中使用 STEPPER 的项目**
【讨论】:
欢迎来到 Stack Overflow!虽然链接是分享知识的好方法,但如果它们在未来被破坏,它们将无法真正回答问题。将回答问题的链接的基本内容添加到您的答案中。如果内容太复杂或太大而无法在此处放置,请描述所提出解决方案的总体思路。请记住始终保留对原始解决方案网站的链接引用。见:How do I write a good answer?【参考方案15】:默认不支持垂直进度条。
【讨论】:
@Romain Guy 您不是 Google 的 Android 开发人员吗?你拜托不能让各种进度条支持垂直放置吗?我认为这是 UI 开发人员的一个非常明显的期望。 这不是问题的答案。它只是在说“太难了”。 我认为您在 Android 方面还不够好,无法提供解决方案。实际上根本没有答案。这只是您的意见。 在下面查看我的答案,这很容易完成(显然) 我通过这个公认的答案知道了 google 中有哪些类型的开发人员!以上是关于Android - 将 ProgressBar 设置为垂直条而不是水平条?的主要内容,如果未能解决你的问题,请参考以下文章
Android:以编程方式将颜色设置为 ProgressBar
Android - 将 ProgressBar 设置为垂直条而不是水平条?
我用C#进行winform编程,关于progressBar的用法
如何在确定模式下使用 Android ProgressBar?