kotlin 을 이용 하여 떡 그림 인 스 턴 스 코드 를 실현 합 니 다.

머리말
떡 그림 은 많은 사람들 이 가장 잘 아 는 도표 유형 이자 사용 빈도 가 가장 높 은 도표 유형 중 하나 입 니 다.본 고 는 주로 kotlin 을 이용 하여 떡 그림 을 실현 하 는 관련 내용 을 소개 하고 참고 학습 을 제공 하 며 코드 가 어렵 지 않 기 때문에 kotlin 으로 실현 하고 숙련 도 를 높이 려 고 합 니 다.다음은 함께 보 겠 습 니 다.
일단 뭐 하 는 지.

그림 을 보고 우리 생각 을 정리 합 시다.
4.567917.떡 그림 은 가운데 에 있 고 모든 구역 은 하나의 부채 형 이 므 로 canvas.draw Arc 는 각도 에 따라 그립 니 다4
  • path.arcTo 가 부채 형 라디에이터 의 절반 을 찾 아 접 는 선의 출발점 을 그 려 야 합 니 다
  • canvas.drawPath 를 통 해 접 는 선 을 그립 니 다.접 는 선의 길 이 는 떡 그림 의 크기 에 따라 비례 를 설정 합 니 다
  • canvas.drawText 를 통 해 문 자 를 그립 니 다.문자 의 크기 는 떡 그림 의 크기 에 따라 비례 를 설정 하고 문 자 를 그 리 는 위 치 는 문자 의 너 비 를 계산 해 야 합 니 다
  • 생각 이 분명 한 후 소 매 를 걷 어 올 리 고 힘 을 내 서 하 다.
    지식 점
    우리 가 먼저 하나의 개념 을 알 아 보 자.우리 가 paint 에서 부채 형 을 그 릴 때 대응 하 는 도 수 는 어느 위치 에 있 습 니까?

    그림 을 보시 면 아 시 겠 죠.
    떡 그림 그리 기
    먼저 그의 매개 변 수 를 살 펴 보 자.왼쪽,위,오른쪽,아래 매개 변 수 는 하나의 패 널 을 형성 하고 startAngle 은 시작 각도 이 며 sweepAngle 은 시작 각도 에서 몇 도 를 그립 니까?useCenter 는 원심 에 연결 되 었 는 지,paint 는 붓 입 니 다.
    
     public void drawArc(float left, float top, float right, float bottom, float startAngle,
     float sweepAngle, boolean useCenter, @NonNull Paint paint) {
     super.drawArc(left, top, right, bottom, startAngle, sweepAngle, useCenter, paint);
     }
    우 리 는 현재 컨트롤 의 width,height 를 패 널 로 하여 동 그 란 떡 그림 을 그립 니 다.
    
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     override fun onDraw(canvas: Canvas) {
     super.onDraw(canvas)
     canvas.drawArc(0f, 0f, width, height, 0f, 360f, true, paintRed)
     }
    아 싸,못 생 겼 다.결 과 는 타원 으로 나 타 났 다.동 그 란 떡 그림 을 그 리 려 면 left=top=right=bottom 을 확보 해 야 한다.

    그림%1 개의 캡 션 을 편 집 했 습 니 다.
    
     /**
     * view   
     */
     var width: Float = 0f
     /**
     * view   
     */
     var height: Float = 0f
     /**
     * drawArc       
     */
     var left: Float = 0f
     /**
     * drawArc       
     */
     var top: Float = 0f
     /**
     * drawArc       
     */
     var right: Float = 0f
     /**
     * drawArc       
     */
     var bottom: Float = 0f
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     override fun onDraw(canvas: Canvas) {
     super.onDraw(canvas)
     canvas.drawArc(left, top, right, bottom, 0f, 360f, true, paint)
     } 
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
     super.onSizeChanged(w, h, oldw, oldh)
     setBackgroundColor(resources.getColor(R.color.black))
     width = w.toFloat()
     height = h.toFloat()
     left = width / 4f
     top = width / 4f
     right = width - left
     bottom = width - top 
     }
    완벽 한 가운데

    다음 에 우 리 는 위 를 0 도 에서 360 도 까지 몇 단계 로 나 누 어 그 려 야 한다.
    
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     override fun onDraw(canvas: Canvas) {
     super.onDraw(canvas)
     ...
     canvas.drawArc(left, top, right, bottom, 0f, 20f, true, paintPuple)
     canvas.drawArc(left, top, right, bottom, 20f, 10f, true, paintGray)
     canvas.drawArc(left, top, right, bottom, 30f, 40f, true, paintGreen)
     canvas.drawArc(left, top, right, bottom, 70f, 110f, true, paintBlue)
     canvas.drawArc(left, top, right, bottom, 180f, 110f, true, paintRed)
     canvas.drawArc(left, top, right, bottom, 290f, 70f, true, paintYellow)
     }
    괜찮다
    위의 그림 의 도 수 는 죽은 것 이 라 고 쓰 여 있 으 니,지금 우리 가 그 를 살 려 보 자.
    예 를 들 어 농 명 아저씨 가 과일 을 팔 고 배 는 10 개,바 나 나 는 3 개,사 과 는 7 개 를 팔 았 다.그러면 이 수의 집합 은 pieList=(10,3,7)이다.
    떡 그림 은 각도 에 따라 그 려 지기 때문에 우 리 는 이 숫자 를 각도 로 집합 시 켜 야 한다.환산 하 는 과정 에서 우 리 는 모든 과일 이 전체 과일 에서 차지 하 는 비율 을 알 아야 한다.그리고 이 비율 을 통 해 360 도 를 곱 하면 모든 과일 이 차지 하 는 도 수 를 알 수 있다.
    배 는 10/(10+3+7)=1/2,배 는 떡 그림 에서 차지 하 는 도 수 는 1/2*360=180 도이 다.이런 식 으로 따 지면 바나나 와 사과 가 떡 그림 에서 차지 하 는 도 수 는 각각 54 도와 126 도이 다.그러면 떡 그림 의 분포 도 나온다.
    이제 우 리 는 하나의 수의 집합 을 정의 하고 비례 의 집합 과 도수 의 집합 을 계산한다.다음은 비례 의 집합 이다.도수 의 집합 은 우리 가 그 릴 때 다시 계산한다.
    
     /**
     *       
     */
     var pieList = arrayListOf(10f,3f,7f)
    
     /**
     *        
     */
     var scaleList = arrayListOf<Float>()
     /**
     *        
     */
     var total: Float = 0f 
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
     super.onSizeChanged(w, h, oldw, oldh)
     //       
     total = pieList.sum()
     //     
     for (a in pieList) {
      scaleList.add(a.div(total))
     }
     }
    비례 집합 을 얻 었 습 니 다.그 다음 에 우 리 는 이 비례 치 를 순환 한 다음 에 비례 치 를 360 도 에 곱 하여 각도 치 를 계산 하여 draw Arc 의 sweepAngle 에 사용 할 수 있 습 니 다.그러나 우 리 는 startAngle 의 시작 각도 가 부족 합 니 다.우 리 는 시작 각 도 를 0 도로 정의 할 수 있 습 니 다.그리고 매번 계 산 된 각도 치 sweepAngle 에 따라 시작 도 수 를 누적 할 수 있 습 니 다.코드 로 구현 해 주세요.
    
     /**
     *           
     */
     var currentDegree: Float = 0f
    
     /**
     *                    
     */
     var srctorDegree: Float = 0f 
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     override fun onDraw(canvas: Canvas) {
     super.onDraw(canvas) 
     for (scale in scaleList) {
      val paint = Paint()
      paint.strokeWidth = dip(10.0f).toFloat()
      paint.isAntiAlias = true
      //            ,          
      val hex = "#" + Integer.toHexString((-16777216 * Math.random()).toInt())
      paint.color = Color.parseColor(hex)
      //   
      srctorDegree = scale * 360
      canvas.drawArc(left, top, right, bottom, currentDegree, srctorDegree, true, paint)
      //    
      currentDegree += srctorDegree
     }
     }
    ok,이제 우 리 는 무 작위 로 숫자 를 정의 하여 비례 하 는 떡 그림 을 만 들 수 있 습 니 다.

    접 는 선 그리 기
    그 다음 에 우 리 는 접 는 선 을 그립 니 다.접 는 선의 출발점 은 모든 부채 형 아크 의 절반 입 니 다.path 의 arcTo 방법 도 원 을 그 릴 수 있 고 방법 적 인 매개 변수 도 마찬가지 입 니 다.우 리 는 arcto 가 canvas.draw Arc 를 따라 그림 을 그 릴 수 있 습 니 다.arcto 의 startAngle 시작 각 도 는 canvas.draw Arc 의 시작 각도 에 sweepAngle 도수 의 절반 을 더 하면 아크 변 의 절반 을 찾 을 수 있 습 니 다.arcto 의 sweepAngle 은 0 이면 됩 니 다.우 리 는 위치 만 정 하고 그리 지 않 습 니 다.
    
      ...
      canvas.drawArc(left, top, right, bottom, currentDegree, srctorDegree, true, paint)
      val path = Path()
      path.arcTo(left, top, right, bottom, currentDegree + srctorDegree / 2, 0f, false)
      ...
    이제 path 의 위 치 는 호 변 의 절반 으로 정 해 졌 습 니 다.그 다음 에 우 리 는 현재 path 의 좌 표를 알 고 좌표 에 따라 접 는 선 을 그 려 야 합 니 다.
    
      val bounds = RectF()
      // path        bounds
      path.computeBounds(bounds, true)
    지금 좌 표를 얻 었 습 니 다.우 리 는 효과 도 를 다시 보 겠 습 니 다.접 는 선과 문 자 는 네 가지 방향 입 니 다.우 리 는 떡 그림 을 네 개의 구역 으로 나 누 어 원심 을 좌표 축 원점 으로 하고 네 개의 상한 으로 나 누 는 것 이 좋 습 니 다.
    4.567917.제1 상한:접 는 선 은 오른쪽 위 이 고 문 자 는 접 는 선 오른쪽 에 있 습 니 다두 번 째 상한:접 는 선 은 왼쪽 위 이 고 문 자 는 접 는 선 왼쪽 에 있 습 니 다세 번 째 상한:접 는 선 은 왼쪽 아래 이 고 문 자 는 접 는 선 왼쪽 에 있 습 니 다제4 상한:접 는 선 은 오른쪽 아래 이 고 문 자 는 접 는 선 오른쪽 에 있 습 니 다그러면 그 다음 에 현재 의 시작 점 이 어느 상한 선 에 있 는 지 어떻게 판단 하 는 것 입 니까?먼저 첫 번 째 상한 선 을 예 로 들 면 현재 의 좌표 가 떡 그림 의 횡축 방향 절반 보다 크 고 떡 그림 의 종축 방향의 절반 보다 작 으 면 첫 번 째 상한 선 이 고 다른 순서 로 유추 하 는 것 입 니 다.
    
     /**
     *      
     */
     var lineae: Int = 30
    
     /**
     *      
     */
     var slantLine: Int = 30 
     override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
     super.onSizeChanged(w, h, oldw, oldh)
      //       
      lineae = (width / 30f).toInt()
      //       
      slantLine = (width / 40f).toInt()
     }
     
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     override fun onDraw(canvas: Canvas) {
     super.onDraw(canvas)
    
     for (scale in scaleList) {
      ...
      val path = Path()
      path.arcTo(left, top, right, bottom, currentDegree + srctorDegree / 2, 0f, false)
      val bounds = RectF()
      path.computeBounds(bounds, true) 
      //    
      if (bounds.left >= width / 2 && bounds.top <= width / 2) {
      path.lineTo(bounds.left + lineae, bounds.top)
      path.lineTo(bounds.left + lineae + slantLine, bounds.top - slantLine)
      canvas.drawPath(path, paintLine)
      //    
      } else if (bounds.left <= width / 2 && bounds.top <= width / 2) {
      path.lineTo(bounds.left - lineae, bounds.top)
      path.lineTo(bounds.left - lineae - slantLine, bounds.top - slantLine)
      canvas.drawPath(path, paintLine)
      //    
      } else if (bounds.left <= width / 2 && bounds.top >= width / 2) {
      path.lineTo(bounds.left - lineae, bounds.top)
      path.lineTo(bounds.left - lineae - slantLine, bounds.top + slantLine)
      canvas.drawPath(path, paintLine)
      //    
      } else {
      path.lineTo(bounds.left + lineae, bounds.top)
      path.lineTo(bounds.left + lineae + slantLine, bounds.top + slantLine)
      canvas.drawPath(path, paintLine)
      } 
      }
      ...
     } 
       
    아이고,나 왔 다.
    텍스트 그리 기
    다음은 문 자 를 그 리 는 것 입 니 다.첫 번 째,네 번 째 상한 선 은 괜 찮 습 니 다.문 자 는 접 는 선 뒤에서 그 릴 수 있 습 니 다.그러나 두 번 째,세 번 째 상한 의 문 자 는 허용 되 지 않 습 니 다.우 리 는 문자 너비 의 거 리 를 앞으로 이동 해 야 접 는 선 을 완벽 하 게 연결 할 수 있 습 니 다.그래서 우 리 는 문 자 를 계산 하 는 방법 을 정의 합 니 다.
    
     /**
     *        
     */
     private fun getStringWidth(str: String): Float = paintLine.measureText(str)
    문 자 는 떡 그림 의 크기 에 따라 달라 지기 때문에 문자 크기 의 비율 을 설정 합 니 다.
    
     paintLine.textSize = dip(width / 100).toFloat()
    이제 글 을 그 려 보도 록 하 겠 습 니 다.
    
     @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
     override fun onDraw(canvas: Canvas) {
     super.onDraw(canvas)
      ... 
      //          
      val textStr = String.format("%.2f%%", scale * 100)
      //       
      val textWidth = getStringWidth(textStr)   
      //    
      if (bounds.left >= width / 2 && bounds.top <= width / 2) {
      ...
      canvas.drawText(textStr, bounds.left + lineae + slantLine, bounds.top - slantLine, paintText)
      ...
      //    
      } else if (bounds.left <= width / 2 && bounds.top <= width / 2) {
      ...
      canvas.drawText(textStr, bounds.left - lineae - slantLine - textWidth, bounds.top - slantLine, paintText)
      ...
      //    
      } else if (bounds.left <= width / 2 && bounds.top >= width / 2) {
      ...
      canvas.drawText(textStr, bounds.left - lineae - slantLine - textWidth, bounds.top + lineae, paintText)
      ...
      //    
      } else {
      ...
      canvas.drawText(textStr, bounds.left + lineae + slantLine, bounds.top + slantLine, paintText)
      ...
      }  
     }
    응,괜찮아,

    그리고 효과 도 를 살 펴 보 겠 습 니 다.떡 그림 중간 에 배경 색 과 같은 검 은 원 이 있 습 니 다.이것 은 간단 하지 않 습 니까?
    
     //         
     paintCicle.color = resources.getColor(R.color.black)
     paintCicle.isAntiAlias = true
     paintCicle.style = Paint.Style.FILL 
      @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
      override fun onDraw(canvas: Canvas) {
      super.onDraw(canvas)  
      ...  
      //          ,            
      canvas.drawCircle(width / 2, width / 2, width / 8, paintCicle)
      }

    그리고 우 리 는 Activity 에 호출 하 는 방법 을 폭로 했다.
    
     /**
      *       
      */
     fun setPieData(a: ArrayList<Float>) {
      pieList.clear()
      pieList.addAll(a)
      invalidate()
     }
    그러면 Activity 는 이렇게 호출 할 수 있 습 니 다.
    
     override fun onCreate(savedInstanceState: Bundle?) {
      super.onCreate(savedInstanceState)
      setContentView(R.layout.activity_second)
      pie1.setPieData(arrayListOf(1f,10f,15f,9f,15f))
      pie2.setPieData(arrayListOf(3f,8f,15f,7f,9f))
      pie3.setPieData(arrayListOf(9f,3f,7f,3f,4f,2f,1f))
     }

    총결산
    이상 은 이 글 의 전체 내용 입 니 다.본 논문 의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가치 가 있 기 를 바 랍 니 다.궁금 한 점 이 있 으 시 면 댓 글 을 남 겨 주 셔 서 저희 에 대한 지지 에 감 사 드 립 니 다.

    좋은 웹페이지 즐겨찾기