Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 在圆弧上画圆形空心拇指_Android_Draw_Shapes_Android Graphics - Fatal编程技术网

Android 在圆弧上画圆形空心拇指

Android 在圆弧上画圆形空心拇指,android,draw,shapes,android-graphics,Android,Draw,Shapes,Android Graphics,我想创建一个圆形图,显示我的应用程序中的一系列值。这些值可分为3类:低、中、高-由3种颜色表示:蓝色、绿色和红色(分别) 在这个范围之上,我想以“拇指”的形式在相关范围部分显示实际测量值: 根据测量值,白色拇指在范围弧上的位置可能会改变 目前,在视图的onDraw方法中,我可以通过在同一中心上绘制3个圆弧来绘制3色范围: width = (float) getWidth(); height = (float) getHeight(); float radius; if (width >

我想创建一个圆形图,显示我的应用程序中的一系列值。这些值可分为3类:低、中、高-由3种颜色表示:蓝色、绿色和红色(分别)

在这个范围之上,我想以“拇指”的形式在相关范围部分显示实际测量值:

根据测量值,白色拇指在范围弧上的位置可能会改变

目前,在视图的onDraw方法中,我可以通过在同一中心上绘制3个圆弧来绘制3色范围:

width = (float) getWidth();
height = (float) getHeight();

float radius;

if (width > height) {
    radius = height / 3;
} else {
    radius = width / 3;
}

paint.setAntiAlias(true);
paint.setStrokeWidth(arcLineWidth);
paint.setStrokeCap(Paint.Cap.ROUND);
paint.setStyle(Paint.Style.STROKE);

center_x = width / 2;
center_y = height / 1.6f;

left = center_x - radius;
float top = center_y - radius;
right = center_x + radius;
float bottom = center_y + radius;

oval.set(left, top, right, bottom);

//blue arc
paint.setColor(colorLow);
canvas.drawArc(oval, 135, 55, false, paint);

//red arc
paint.setColor(colorHigh);
canvas.drawArc(oval, 350, 55, false, paint);

//green arc
paint.setColor(colorNormal);

canvas.drawArc(oval, 190, 160, false, paint);
这是结果弧:

我的问题是,我如何:

  • 在这三种颜色之间创建平滑的渐变(我尝试使用
    SweepGradient
    但它没有给我正确的结果)
  • 如图所示,创建覆盖白色拇指的,以便我能够控制在何处显示

  • 在我的射程弧上设置这个白色拇指的动画

  • 注意:3色范围是静态的-因此,另一种解决方案可以是只需在可绘制对象上绘制白色拇指(并设置动画),因此我也愿意听到这样的解决方案:)

  • 我会改变一点绘制视图的方式,通过查看原始设计,而不是绘制3个封口,我只绘制一条线,这样,
    SweepGradient
    就可以工作了

  • 这可能有点棘手,您有两个选择:

    • 创建带有4个圆弧的
      路径
    • 画两个圆弧-一个是大白色(用白色填充,因此您仍然希望使用
      Paint.Style.STROKE
      ),另一个在其上使其填充透明,您可以使用PorterDuff xfermode实现它,可能需要几次尝试,直到您在不清除绿色圆圈的情况下获得它
  • 我想你想要设置拇指位置的动画,所以只需使用简单的
    动画
    即可使视图无效,并相应地绘制拇指视图位置


  • 希望这有帮助

    我会为你的前两个问题使用口罩

    1.创建平滑的渐变 第一步是画两个线性渐变的矩形。第一 矩形包含蓝色和绿色,而第二个矩形包含绿色 和红色,如下图所示。我在两个矩形互相接触的地方画了线 黑色以澄清它们实际上是两个不同的矩形

    这可以使用以下代码(摘录)实现:

    因为你的目标是有一个带圆形帽的彩色弧,我们接下来需要定义弧的面积 两个应该对用户可见的矩形。这意味着两个矩形中的大多数 将被遮住,因此不可见。相反,唯一剩下的是弧区域

    结果应该如下所示:

    为了实现所需的行为,我们定义了一个遮罩,仅显示其中的弧区域 矩形。为此,我们大量使用
    setXfermode
    Paint
    方法。作为论据 我们使用不同的
    PorterDuffXfermode
    实例

    private Paint maskPaint;
    private Paint imagePaint;
    
    // ...
    
    // To be called within all constructors
    private void init() {
        // I encourage you to research what this does in detail for a better understanding
    
        maskPaint = new Paint();
        maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
    
        imagePaint = new Paint();
        imagePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OVER));
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        // @step1
    
        // Mask
    
        Bitmap mMask = Bitmap.createBitmap(800, 800, conf);
        Canvas maskCanvas = new Canvas(mMask);
    
        paint.setColor(Color.WHITE);
        paint.setShader(null);
        paint.setStrokeWidth(70);
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeCap(Paint.Cap.ROUND);
        paint.setAntiAlias(true);
        final RectF oval = new RectF();
        center_x = 400;
        center_y = 400;
        oval.set(center_x - radius,
                center_y - radius,
                center_x + radius,
                center_y + radius);
    
        maskCanvas.drawArc(oval, 135, 270, false, paint);
    
        // /Mask
    
        canvas.save();
        // This is new compared to step 1
        canvas.drawBitmap(mMask, 0, 0, maskPaint);
        canvas.drawBitmap(mImage, 0, 0, imagePaint); // Notice the imagePaint instead of null
        canvas.restore();
    }
    
    2.创建覆盖白色拇指 这解决了您的第一个问题。第二种方法可以通过再次使用遮罩来实现,不过 是时候我们想要实现一些不同的东西了。之前,我们只想显示一个特定区域(弧) 背景图像(两个矩形)。这一次我们想做相反的事情: 我们定义了一个背景图像(拇指)并遮掩了它的内部内容,因此 中风似乎仍然存在。应用于圆弧图像时,拇指将彩色圆弧与 一个透明的内容区域

    所以第一步是画拇指。我们使用一个半径与 背景弧线,但角度不同,导致弧线小得多。但是因为 拇指应该“环绕”背景弧,其笔划宽度必须大于背景弧 背景弧

    @Override
    protected void onDraw(Canvas canvas) {
        // @step1
    
        // @step2
    
        // Thumb Image
    
        mImage = Bitmap.createBitmap(800, 800, conf);
        imageCanvas = new Canvas(mImage);
    
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(120);
        final RectF oval2 = new RectF();
        center_x = 400;
        center_y = 400;
        oval2.set(center_x - radius,
                center_y - radius,
                center_x + radius,
                center_y + radius);
    
        imageCanvas.drawArc(oval2, 270, 45, false, paint);
    
        // /Thumb Image
    
        canvas.save();
        canvas.drawBitmap(RotateBitmap(mImage, 90f), 0, 0, null);
        canvas.restore();
    }
    
    public static Bitmap RotateBitmap(Bitmap source, float angle)
    {
        Matrix matrix = new Matrix();
        matrix.postRotate(angle);
        return Bitmap.createBitmap(source, 0, 0, source.getWidth(), source.getHeight(), matrix, true);
    }
    
    代码的结果如下所示

    现在我们有了一个覆盖背景弧的拇指,我们需要定义遮罩 这将移除拇指的内部,以便背景弧再次可见

    为了实现这一点,我们基本上使用与之前相同的参数来创建另一个圆弧,但是 这一次,笔划宽度必须与背景弧的宽度相同 这标记了我们要在拇指内部移除的区域

    使用以下代码,生成的图像如图4所示

    3.设置白色拇指的动画 问题的最后一部分是设置圆弧运动的动画。我没有固体 这方面的解决方案,但也许可以为您提供一个有用的方向。我会尝试以下方法:

    首先将拇指定义为
    ImageView
    ,它是整个圆弧图的一部分。换衣服的时候 在图形的选定值周围,围绕背景中心旋转拇指图像 弧。因为我们想要为移动设置动画,所以只需设置拇指图像的旋转即可 这是不够的。相反,我们使用了一种类似这样的
    RotateAnimation

    final RotateAnimation animRotate = new RotateAnimation(0.0f, -90.0f, // You have to replace these values with your calculated angles
            RotateAnimation.RELATIVE_TO_SELF, // This may be a tricky part. You probably have to change this to RELATIVE_TO_PARENT
            0.5f, // x pivot
            RotateAnimation.RELATIVE_TO_SELF,
            0.5f); // y pivot
    
    animRotate.setDuration(1500);
    animRotate.setFillAfter(true);
    animSet.addAnimation(animRotate);
    
    thumbView.startAnimation(animSet);
    
    我想这还远远不是最终结果,但它很可能会帮助你寻找所需的信息 解决方案非常重要的一点是,轴心值必须指向轴的中心 背景弧,因为这是拇指图像应该旋转的点

    我已经用API级别16和22、23测试了我的(完整的)代码,所以我希望这个答案至少是正确的 为您提供解决问题的新思路

    请注意,
    onDraw
    方法中的分配操作不是一个好主意,应该 必须避免。为了简单起见,我没有遵循这个建议。此外,该代码还将用作 一个方向正确的指南,而不是简单地复制粘贴,因为它使沉重 使用幻数,一般不遵循
    @Override
    protected void onDraw(Canvas canvas) {
        // @step1
    
        // @step2
    
        // Thumb Image
        // ...
        // /Thumb Image
    
        // Thumb Mask
    
        mMask = Bitmap.createBitmap(800, 800, conf);
        maskCanvas = new Canvas(mMask);
    
        paint.setColor(Color.WHITE);
        paint.setStrokeWidth(70);
        paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
        final RectF oval3 = new RectF();
        center_x = 400;
        center_y = 400;
        oval3.set(center_x - radius,
                center_y - radius,
                center_x + radius,
                center_y + radius);
    
        maskCanvas.drawBitmap(mImage, 0, 0, null);
        maskCanvas.drawArc(oval3, 270, 45, false, paint);
    
        // /Thumb Mask
    
        canvas.save();
        canvas.drawBitmap(RotateBitmap(mMask, 90f), 0, 0, null); // Notice mImage changed to mMask
        canvas.restore();
    }
    
    final RotateAnimation animRotate = new RotateAnimation(0.0f, -90.0f, // You have to replace these values with your calculated angles
            RotateAnimation.RELATIVE_TO_SELF, // This may be a tricky part. You probably have to change this to RELATIVE_TO_PARENT
            0.5f, // x pivot
            RotateAnimation.RELATIVE_TO_SELF,
            0.5f); // y pivot
    
    animRotate.setDuration(1500);
    animRotate.setFillAfter(true);
    animSet.addAnimation(animRotate);
    
    thumbView.startAnimation(animSet);
    
    dependencies {
        ...
        compile 'com.github.paroca72:sc-gauges:3.0.7'
    }
    
    <com.sccomponents.gauges.library.ScArcGauge
                android:id="@+id/gauge"
                android:layout_width="300dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal" />
    
    ScArcGauge gauge = this.findViewById(R.id.gauge);
    gauge.setAngleSweep(270);
    gauge.setAngleStart(135);
    gauge.setHighValue(90);
    
    int lineWidth = 50;
    ScCopier baseLine = gauge.getBase();
    baseLine.setWidths(lineWidth);
    baseLine.setColors(Color.parseColor("#dddddd"));
    baseLine.getPainter().setStrokeCap(Paint.Cap.ROUND);
    
    ScCopier progressLine = gauge.getProgress();
    progressLine.setWidths(lineWidth);
    progressLine.setColors(
         Color.parseColor("#65AAF2"),
         Color.parseColor("#3EF2AD"),
         Color.parseColor("#FF2465")
    );
    progressLine.getPainter().setStrokeCap(Paint.Cap.ROUND);