7

我必须画一条 3dp 线来表示智力竞赛游戏中的关卡完成情况。

这条线必须有 2 种颜色。例如,如果用户已经完成了 40% 的关卡,那么前 40% 的线将是红色的,其他 60% 的线是灰色的。

我已经设法用 drawable 做到了:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="line" >
            <size android:height="3dp" android:width="40dp"/>
            <stroke
                android:width="1dp"
                android:color="#FFFC10" />
        </shape>
    </item>
    <item android:left="40dp">
        <shape android:shape="line" >
            <size android:height="3dp" android:width="60dp" />
            <stroke
                android:width="1dp"
                android:color="#DDDDDD" />
        </shape>
    </item>
</layer-list>

然后我用 ImageView 显示它:

<ImageView
                android:id="@+id/row_completion_bar"
                android:src="@drawable/completion_bar"
                android:layout_width="100dp"
                android:layout_height="3dp" />

...但是现在,我当然必须能够根据实际用户的完成情况来更改这 40%/60% 的比例。

第一个问题:最好最有效的方法是什么?在运行时更改可绘制对象?或在 Java 运行时创建一个新的可绘制对象?

第二个问题:怎么做?我尝试了两种方法(在java代码中重新创建这个drawable/在运行时改变xml drawable)并且没有成功:-(

任何帮助将不胜感激。

4

4 回答 4

15

所以这是一个你可以使用的自定义 Drawable:

class LineDrawable extends Drawable {
    private Paint mPaint;

    public LineDrawable() {
        mPaint = new Paint();
        mPaint.setStrokeWidth(3);
    }

    @Override
    public void draw(Canvas canvas) {
        int lvl = getLevel();
        Rect b = getBounds();
        float x = b.width() * lvl / 10000.0f;
        float y = (b.height() - mPaint.getStrokeWidth()) / 2;
        mPaint.setColor(0xffff0000);
        canvas.drawLine(0, y, x, y, mPaint);
        mPaint.setColor(0xff00ff00);
        canvas.drawLine(x, y, b.width(), y, mPaint);
    }

    @Override
    protected boolean onLevelChange(int level) {
        invalidateSelf();
        return true;
    }

    @Override
    public void setAlpha(int alpha) {
    }

    @Override
    public void setColorFilter(ColorFilter cf) {
    }

    @Override
    public int getOpacity() {
        return PixelFormat.TRANSLUCENT;
    }
}

和测试代码:

View v = new View(this);
final LineDrawable d = new LineDrawable();
d.setLevel(4000);
v.setBackgroundDrawable(d);
setContentView(v);
OnTouchListener l = new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        int lvl = (int) (10000 * event.getX() / v.getWidth());
        d.setLevel(lvl);
        return true;
    }
};
v.setOnTouchListener(l);
于 2013-07-30T16:53:46.873 回答
3

使用进度条怎么样?可以通过编程方式或通过 xml 文件设置已完成和待办事项标记的样式。您的代码也将更具可读性/可维护性,因为您将使用正确的小部件来完成这项工作。您的布局将包含:

<ProgressBar
    android:id="@+id/progressBar"
    android:layout_height="3dip"
    android:layout_width="match_parent"
    android:progressDrawable="@drawable/progress_bar" />

您可以使用例如从您的代码更新栏:

ProgressBar bar = (ProgressBar)findViewById(R.id.progressBar);
bar.setProgress(40);

此示例使用 res/drawable/progress_bar.xml 文件覆盖栏的样式(由 progressDrawable 属性指示) - 内容如下。这个有额外的好处,比如渐变阴影和圆角;调整你认为合适的:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
  <item android:id="@android:id/background">
    <shape>
      <corners android:radius="5dip" />
      <gradient
        android:angle="270"
        android:centerColor="#ff5a5d5a"
        android:centerY="0.5"
        android:endColor="#ff747674"
        android:startColor="#ff9d9e9d" />
    </shape>
  </item>
  <item android:id="@android:id/progress">
    <clip>
      <shape>
        <corners android:radius="5dip" />
          <gradient
            android:angle="0"
            android:endColor="#ff009900"
            android:startColor="#ff000099" />
      </shape>
    </clip>
  </item>
</layer-list>

感谢http://www.tiemenschut.com/how-to-customize-android-progress-bars/,它提供了有关如何自定义进度条的更多详细信息。

于 2014-04-08T02:53:38.543 回答
0

我找到了一种方法来做到这一点。不知道这是否是最有效的方法,但这里是:

我使用 RelativeLayout 将 ImageViews 与背景颜色叠加。

在 layout.xml 中:

<RelativeLayout style="@style/CompletionBar">

<ImageView
    android:id="@+id/row_completion_bar_0"
    style="@style/CompletionBar0" />

<ImageView
    android:id="@+id/row_completion_bar_1"
    style="@style/CompletionBar1" />       

</RelativeLayout>

在样式.xml 中:

<!-- Completion Bar (Relative Layout) -->
<style name="CompletionBar">
    <item name="android:layout_width">wrap_content</item>
    <item name="android:layout_height">wrap_content</item>
</style>

<!-- Completion Bar 0 (ImageView) -->
<style name="CompletionBar0">
    <item name="android:layout_width">100dp</item>
    <item name="android:layout_height">2dp</item>
    <item name="android:background">#CCCCCC</item>
</style>

<!-- Completion Bar 1 (ImageView) -->
<style name="CompletionBar1">
    <item name="android:layout_width">40dp</item>
    <item name="android:layout_height">2dp</item>
    <item name="android:background">#555555</item>
</style>

在java文件中:

ImageView cb1 = (ImageView)row.findViewById(R.id.row_completion_bar_1);
cb1.getLayoutParams().width = 40; /* Value in pixels, must convert to dp */
于 2013-07-31T07:11:52.450 回答
0

此代码段适用于所有 api

用这个:

Drawable drawable = editText.getBackground();
drawable.setColorFilter(editTextColor, PorterDuff.Mode.SRC_ATOP);
if(Build.VERSION.SDK_INT > 16) {
    editText.setBackground(drawable);
}else{
    editText.setBackgroundDrawable(drawable);
}
于 2016-09-14T07:47:05.223 回答