使用画布清除特定圆圈外的区域

时间:2017-01-19 15:15:11

标签: android canvas view porter-duff

我有一个自定义视图,通过填充一个圆圈显示进度,但现在我正在寻找一种方法来删除我的视图区域这个白色圆圈

enter image description here

在这里,我的代码:

public class CircleGauge extends View {
    private int value = 75;
    private Paint backgroundPaint, gaugePaint, textPaint, circlePaint;

    ... constructors 

    private void init() {
        DisplayMetrics metrics = getResources().getDisplayMetrics();

        backgroundPaint = new Paint();
        backgroundPaint.setColor(ResourcesCompat.getColor(getResources(), R.color.favorite_position_gauge_background, null));
        backgroundPaint.setStyle(Paint.Style.FILL);
        backgroundPaint.setAntiAlias(true);

        gaugePaint = new Paint();
        gaugePaint.setColor(ResourcesCompat.getColor(getResources(), R.color.favorite_position_gauge, null));
        gaugePaint.setAntiAlias(true);

        circlePaint = new Paint();
        circlePaint.setColor(Color.WHITE);
        circlePaint.setStyle(Paint.Style.STROKE);
        circlePaint.setStrokeWidth(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, metrics));
        circlePaint.setAntiAlias(true);

        textPaint = new Paint();
        textPaint.setTextAlign(Paint.Align.CENTER);
        textPaint.setColor(Color.WHITE);
        textPaint.setFakeBoldText(true);
        textPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 23, metrics));
        textPaint.setAntiAlias(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), backgroundPaint);
        canvas.drawRect(0, ((float) (100 - value) / 100F) * canvas.getHeight(), canvas.getWidth(), canvas.getHeight(), gaugePaint);
        canvas.drawText(getContext().getString(R.string.percent_value, value), getWidth() / 2, getHeight() * .6F, textPaint);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, (getHeight() / 2) - circlePaint.getStrokeWidth() / 2, circlePaint);
    }

    public void setValue(int value) {
        this.value = value;
        invalidate();
    }
}

我非常确定我可以使用PorterDuff执行此操作,但我不知道如何使用。

1 个答案:

答案 0 :(得分:1)

Android drawable resources已经为您提供了完成此操作所需的一切,而无需借助子类化View并覆盖onDraw

首先让我们从drawable资源开始。我们希望有一个圆圈,其中一种颜色覆盖另一种颜色的圆圈。为此,我们使用LayerDrawable,它在XML中使用<layer-list>指定。

每个Drawable都有级别值。您可以通过调用setLevel上的Drawable来调整级别(0-10000)。我们想用水平来控制较亮圆圈的外观。为此,我们将使用ClipDrawable,该<clip>在XML中使用ShapeDrawable定义。

对于圈子本身,我们可以使用<shape> s(<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/field" android:gravity="fill"> <shape android:shape="oval"> <stroke android:width="2dp" android:color="@android:color/white"/> <solid android:color="#FF78606D"/> </shape> </item> <item android:id="@+id/progress" android:gravity="fill"> <clip android:gravity="bottom" android:clipOrientation="vertical"> <shape android:shape="oval" > <stroke android:width="2dp" android:color="@android:color/white"/> <solid android:color="#FFAB9BA6"/> </shape> </clip> </item> </layer-list> )。这就是我们把它们放在一起时的样子:

    <TextView
        android:id="@+id/text"
        android:layout_height="64dp"
        android:layout_width="64dp"
        android:layout_gravity="center"
        android:background="@drawable/circle_progress"
        android:gravity="center"
        android:textAppearance="?android:textAppearanceLarge"
        android:text="0%"/>

现在我们可以使用`TextView并将此drawable作为背景。

Theme.AppCompat

根据你的颜色,我使用了public class MainActivity extends AppCompatActivity { private TextView mTextView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.text); setLevel(0); new AsyncTask<Void, Integer, Void>() { @Override protected Void doInBackground(Void... params) { try { for (int i = 0; i <= 100; i++) { publishProgress(i); Thread.sleep(100); } } catch (InterruptedException e) { // just leave } return null; }; @Override protected void onProgressUpdate(Integer... values) { setLevel(values[0]); } }.execute(); } private void setLevel(int level) { mTextView.setText(Integer.toString(level) + "%"); LayerDrawable layerDrawable = (LayerDrawable) mTextView.getBackground(); Drawable progress = layerDrawable.findDrawableByLayerId(R.id.progress); progress.setLevel(level * 100); // drawable levels go 0-10000 } } ,这是一个黑暗的主题。

这是一个快速而又肮脏的演示,展示了它们如何协同工作:

function calculate() {
  var input = document.getElementById('sumRange');
  var val = input.value;
  
  var newStep;
  if (val < 100000) {
    newStep = 10;
  } else if (val < 150000) {
    newStep = 20;
  } else if (val < 200000) {
    newStep = 30;
  } else if (val < 250000) {
    newStep = 40;
  } else {
    newStep = 50;
  }
  
  input.step = newStep;
}