android - 如何在圆角内画一条线?

标签 android xamarin.android

在 android 中,我创建了自定义 View 。我首先绘制了圆,现在我想在圆内绘制一条线角度。我想要这样的动画。 https://drive.google.com/file/d/1Qx0MBu-77JIlQTByqGTyD-KtGKOB8naG/view?usp=sharing

我用 Canvas 画了圆和线。我用了viewpager。如果我滑动viewpager,饼图就会旋转。

到目前为止我做了什么。动画时总是从零开始: https://drive.google.com/file/d/12mmAUOeY77jAlj_GmM3Ymcx5m34vli3X/view?usp=sharing

我已经完成了以下代码:

    public class PieView : View
    {
        int w, h, pl, pr, pt, pb, usableWidth, usableHeight, radius, cx, cy, lineLenght;
        Paint paint;
        public Canvas canvas;
        public float firstLineangle = 0;
        public float secondLineangle = 40;
        public float thirdLineangle = 120;
        float currentAngle,maxAngle;

        public override void Draw(Canvas canvas)
        {
            base.Draw(canvas);
            w = Width;
            h = Height;
            pl = PaddingLeft;
            pr = PaddingRight;
            pt = PaddingTop;
            pb = PaddingBottom;
            this.canvas = canvas;
            usableWidth = w - (pl + pr);
            usableHeight = h - (pt + pb);

            radius = Math.Min(usableWidth, usableHeight) / 2;
            cx = pl + (usableWidth / 2);
            cy = pt + (usableHeight / 2);

            lineLenght = radius - (pl * 2) - (pr * 2);
            paint = new Paint();
            paint.Color = Android.Graphics.Color.White;
            paint.SetStyle(Paint.Style.Stroke);
            paint.StrokeWidth = 5;
            canvas.DrawCircle(cx, cy, radius - 5, paint);

            Drawline(canvas, firstLineangle);
            Drawline(canvas, secondLineangle);
            Drawline(canvas, thirdLineangle);

            PostInvalidateDelayed(500);
            Invalidate();
        }

        public void Drawline(Canvas canvas, float angle)
        {
            float displacedAngle = angle - 90;
            float x = cx + ((float)Math.Cos(degreesToRadians(displacedAngle)) * (radius - 5)); //convert angle to radians for x and y coordinates
            float y = cy + ((float)Math.Sin(degreesToRadians(displacedAngle)) * (radius - 5));
            canvas.DrawLine(cx, cy, x, y, paint); //draw a line from center point back to the point
        }

        public double degreesToRadians(double degrees)
        {
            return (degrees * Math.PI) / 180;
        }
    }

    public class PieAnimation  : Android.Views.Animations.Animation
    {
        private PieView pieView;

        private float firstLineangle;
        private float secondLineangle;
        private float thirdLineangle;

        public PieAnimation(PieView pieView, float firstLineangle,float secondLineangle,float thirdLineangle)
        {
            this.pieView = pieView;
            this.firstLineangle = firstLineangle;
            this.secondLineangle = secondLineangle;
            this.thirdLineangle = thirdLineangle;
        }

        protected override void ApplyTransformation(float interpolatedTime, Transformation t)
        {
            pieView.firstLineangle = 0 + ((firstLineangle) * interpolatedTime);
            pieView.secondLineangle = 0 + ((secondLineangle) * interpolatedTime);
            pieView.thirdLineangle = 0 + ((thirdLineangle) * interpolatedTime);
            pieView.RequestLayout();
        }
    }

public class TourPager : Java.Lang.Object, ViewPager.IOnPageChangeListener, ViewPager.IPageTransformer
    {

        private ViewPager mViewPager;

        private float mLastOffset;
        public TourView _context;

        public TourPager(ViewPager viewpager, TourView context)
        {
            mViewPager = viewpager;
            viewpager.AddOnPageChangeListener(this);
            _context = context;
        }

        public void OnPageSelected(int position)
        {

            if (position == 0)
            {
                PieAnimation animation = new PieAnimation(_context._pieView, 0, 40, 120);
                animation.Duration = (1000);
                _context._pieView.StartAnimation(animation);
            }
            if (position==1)
            {
                PieAnimation animation = new PieAnimation(_context._pieView, 100, 140, 200);
                animation.Duration=(1000);
                _context._pieView.StartAnimation(animation);
            }
            if(position==2)
            {
                PieAnimation animation = new PieAnimation(_context._pieView, 180, 270, 10);
                animation.Duration = (1000);
                _context._pieView.StartAnimation(animation);
            }
    }

最佳答案

有正在运行的GIF。

enter image description here

PieView.cs

  public class PieView:View
   {

    int w, h, pl, pr, pt, pb, usableWidth, usableHeight, radius, cx, cy, lineLenght;
    int handTruncation, hourHandTruncation = 0;
    Paint paint;
     int[] numbers = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
    Rect rect = new Rect();
    public PieView(Context context) : base(context)
    {

    }

    public PieView(Context context, IAttributeSet attrs) : base(context, attrs)
    {
    }

    public PieView(Context context, IAttributeSet attrs, int defStyleAttr) : base(context, attrs, defStyleAttr)
    {
    }

    public PieView(Context context, IAttributeSet attrs, int defStyleAttr, int defStyleRes) : base(context, attrs, defStyleAttr, defStyleRes)
    {
    }

    public override  void Draw(Canvas canvas)
    {
        base.Draw(canvas);
        w = Width;
        h = Height;

        pl = PaddingLeft+10;
        pr = PaddingRight+10;
        pt = PaddingTop+10;
        pb = PaddingBottom+10;

        usableWidth = w - (pl + pr);
        usableHeight = h - (pt + pb);

        radius = Math.Min(usableWidth, usableHeight) / 2;
        cx = pl + (usableWidth / 2);
        cy = pt + (usableHeight / 2);

        int min = Math.Min(usableWidth, usableHeight);

        handTruncation = min / 20;
        hourHandTruncation = min / 7;


        lineLenght = radius - (pl * 2) - (pr * 2);
        paint = new Paint();
        paint.Color = Android.Graphics.Color.White;
        paint.SetStyle(Paint.Style.Stroke);
        paint.StrokeWidth = 5;

        canvas.DrawCircle(cx, cy, radius , paint);
        drawNumeral(canvas);
        drawHands(canvas);
        PostInvalidateDelayed(200);
        Invalidate();

    }



    private void drawHands(Canvas canvas)
    {

        Calendar c = Calendar.Instance;
        float hour = c.Get(CalendarField.HourOfDay);
        hour = hour > 12 ? hour - 12 : hour;
        drawHand1(canvas, (hour + c.Get(CalendarField.Minute) / 60) * 5f,true);
        drawHand1(canvas, c.Get(CalendarField.Minute),false);
        drawHand1(canvas, c.Get(CalendarField.Second),false);
    }
    private void drawNumeral(Canvas canvas)
    {
        paint.TextSize=50;
        foreach (var number in numbers)
        {
            string tmp = number.ToString();
            paint.GetTextBounds( tmp, 0, tmp.Length, rect); //getTextBounds(tmp, 0, tmp.length(), rect);
            double angle = Math.PI / 6 * (number - 3);
            int x = (int)(w / 2 + Math.Cos(angle) * radius - rect.Width() / 2);
            int y = (int)(h / 2 + Math.Sin(angle) * radius + rect.Height() / 2);
            canvas.DrawText(tmp, x, y, paint);
        }

    }

    private void drawHand1(Canvas canvas, double loc, bool isHour)
    {

       double angle = Math.PI * loc / 30 - Math.PI / 2;
        int handRadius = isHour ? radius - handTruncation - hourHandTruncation : radius - handTruncation;
        canvas.DrawLine(Width / 2, Height / 2,
          (float)(Width / 2 + Math.Cos(angle) * handRadius),
          (float)(Height / 2 + Math.Sin(angle) * handRadius),
          paint);

    }

}

您可以在 MainActivity.cs 中使用它

        RelativeLayout relativeLayout1 = FindViewById<RelativeLayout> 
        (Resource.Id.relativeLayout1);
        relativeLayout1.SetBackgroundColor(Color.Black);
        AddContentView(new PieView(this),new ViewGroup.LayoutParams(-1,-1));

关于android - 如何在圆角内画一条线?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56257409/

相关文章:

android - Sqlite高级搜索

java - ECDSA 签名生成 KeyPair Java 到 C# - JcaPEMKeyConverter()

java - 由于四处移动文件,Android Studio 项目搞砸了

Android O 抬头通知

android - 如何在 Xamarin 中获取 ActivityManager 的实例?

c# - Visual Studio 2015 Xamarin.Android - 将图像库中的 throw 限制为每次 throw 仅一项

android - canvas.DrawRect 导致应用程序自动退出

c# - (Xamarin,Android)此代码如何帮助减少引用实例?

Android:将搜索查询转发到一个处理搜索的 Activity

android - ios/android 应用的 Laravel 密码加密/解密机制