从下到上逐渐填充一个圆圈android [英] filling a circle gradually from bottom to top android

查看:31
本文介绍了从下到上逐渐填充一个圆圈android的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 xml 创建了一个带有笔划和白色背景的圆圈.如何在用户操作(例如连续按下按钮时)从下到上逐渐填充?

I have created a circle with a stroke and white background using xml. How can this be filled gradually from bottom to top on user actions(e.g. on successive button press)?

有没有免费的库可以用来实现类似的事情?

Is there any free library which can be used to achieve similar thing?

推荐答案

我创建了一个自定义视图类,它可以执行您想要的操作.可以在您的布局 xml 中设置四个自定义属性:

I created a Custom View class that will do what you want. There are four custom attributes that can be set in your layout xml:

  • fillColor, color - 设置填充区域的颜色.默认为 Color.WHITE.
  • strokeColor, color - 设置边界圆的颜色.默认为 Color.BLACK.
  • strokeWidth, float - 设置边界圆的粗细.默认为 1.0.
  • value, integer: 0-100 - 设置填充区域的值.默认为 0.
  • fillColor, color - Sets the color of the fill area. Default is Color.WHITE.
  • strokeColor, color - Sets the color of the bounding circle. Default is Color.BLACK.
  • strokeWidth, float - Sets the thickness of the bounding circle. Default is 1.0.
  • value, integer: 0-100 - Sets the value for the fill area. Default is 0.

请注意,这些属性必须使用 custom 前缀代替布局 xml 中的 android 前缀.根 View 还应该包含 custom xml 命名空间.(参见下面的示例.) 其他标准的 View 属性 - 例如 layout_widthbackground 等 -可用.

Please note that these attributes must have the custom prefix in lieu of the android prefix in your layout xml. The root View should also contain the custom xml namespace. (See the example below.) The other standard View attributes - such as layout_width, background, etc. - are available.

首先是CircleFillView类:

public class CircleFillView extends View
{
    public static final int MIN_VALUE = 0;
    public static final int MAX_VALUE = 100;

    private PointF center = new PointF();
    private RectF circleRect = new RectF();
    private Path segment = new Path();  
    private Paint strokePaint = new Paint();
    private Paint fillPaint = new Paint();

    private int radius;

    private int fillColor;
    private int strokeColor;
    private float strokeWidth;
    private int value;

    public CircleFillView(Context context)
    {
        this(context, null);
    }

    public CircleFillView(Context context, AttributeSet attrs)
    {
        super(context, attrs);

        TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.CircleFillView,
            0, 0);

        try
        {
            fillColor = a.getColor(R.styleable.CircleFillView_fillColor, Color.WHITE);
            strokeColor = a.getColor(R.styleable.CircleFillView_strokeColor, Color.BLACK);
            strokeWidth = a.getFloat(R.styleable.CircleFillView_strokeWidth, 1f);
            value = a.getInteger(R.styleable.CircleFillView_value, 0);
            adjustValue(value);
        }
        finally
        {
            a.recycle();
        }   

        fillPaint.setColor(fillColor);
        strokePaint.setColor(strokeColor);
        strokePaint.setStrokeWidth(strokeWidth);
        strokePaint.setStyle(Paint.Style.STROKE);
    }

    public void setFillColor(int fillColor)
    {
        this.fillColor = fillColor;
        fillPaint.setColor(fillColor);
        invalidate();
    }

    public int getFillColor()
    {
        return fillColor;
    }

    public void setStrokeColor(int strokeColor)
    {
        this.strokeColor = strokeColor;
        strokePaint.setColor(strokeColor);
        invalidate();
    }

    public int getStrokeColor()
    {
        return strokeColor;
    }

    public void setStrokeWidth(float strokeWidth)
    {
        this.strokeWidth = strokeWidth;
        strokePaint.setStrokeWidth(strokeWidth);
        invalidate();
    }

    public float getStrokeWidth()
    {
        return strokeWidth;
    }

    public void setValue(int value)
    {
        adjustValue(value);
        setPaths();

        invalidate();
    }

    public int getValue()
    {
        return value;
    }

    private void adjustValue(int value)
    {
        this.value = Math.min(MAX_VALUE, Math.max(MIN_VALUE, value));
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh)
    {
        super.onSizeChanged(w, h, oldw, oldh);

        center.x = getWidth() / 2;
        center.y = getHeight() / 2;
        radius = Math.min(getWidth(), getHeight()) / 2 - (int) strokeWidth;
        circleRect.set(center.x - radius, center.y - radius, center.x + radius, center.y + radius);

        setPaths();
    }

    private void setPaths()
    {
        float y = center.y + radius - (2 * radius * value / 100 - 1);
        float x = center.x - (float) Math.sqrt(Math.pow(radius, 2) - Math.pow(y - center.y, 2));

        float angle = (float) Math.toDegrees(Math.atan((center.y - y) / (x - center.x)));
        float startAngle = 180 - angle;
        float sweepAngle = 2 * angle - 180;

        segment.rewind();
        segment.addArc(circleRect, startAngle, sweepAngle);
        segment.close();
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        canvas.drawPath(segment, fillPaint);
        canvas.drawCircle(center.x, center.y, radius, strokePaint);
    }
}

现在,要使自定义 xml 属性起作用,您需要将以下文件放在项目的 /res/values 文件夹中.

Now, for the custom xml attributes to work, you will need to put the following file in the /res/values folder of your project.

attrs.xml:

<resources>
    <declare-styleable name="CircleFillView" >
        <attr name="fillColor" format="color" />
        <attr name="strokeColor" format="color" />
        <attr name="strokeWidth" format="float" />
        <attr name="value" format="integer" />
    </declare-styleable>
</resources>

以下是一个简单演示应用程序的文件,其中 CircleFillView 的值由 SeekBar 控制.

Following are the files for a simple demonstration app, where the CircleFillView's value is controlled with a SeekBar.

我们Activity的布局文件,main.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.circlefill"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical" >

    <com.example.circlefill.CircleFillView
        android:id="@+id/circleFillView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:background="#ffffff"
        custom:fillColor="#6bcae2"
        custom:strokeColor="#75b0d0"
        custom:strokeWidth="20"
        custom:value="65" />

    <SeekBar android:id="@+id/seekBar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

还有,MainActivity 类:

public class MainActivity extends Activity
{
    CircleFillView circleFill;
    SeekBar seekBar;

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        circleFill = (CircleFillView) findViewById(R.id.circleFillView);

        seekBar = (SeekBar) findViewById(R.id.seekBar);
        seekBar.setProgress(circleFill.getValue());
        seekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener()
            {
                @Override
                public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser)
                {
                    if (fromUser)
                        circleFill.setValue(progress);
                }

                @Override
                public void onStartTrackingTouch(SeekBar seekBar) {}

                @Override
                public void onStopTrackingTouch(SeekBar seekBar) {}
            }
        );
    }   
}

以及演示应用程序的屏幕截图:

And a screenshot of the demo app:

这篇关于从下到上逐渐填充一个圆圈android的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆