Android 사용자 정의 View 그 라 데 이 션 진행 막대 구현

14206 단어 Android진도 표
인터넷 에서 진도 조 효과 도 를 보 았 는데 매우 아름 답 습 니 다.다음 과 같 습 니 다.

진행 효과 분해:
1.그 라 데 이 션 컬러 는 색상 변화 가 복잡 하지 않 아 보 이 므 로 리 니 어 그 라 데 이 션 을 사용 하면 가능 할 것 같 습 니 다.
2.둥 근 머리 는 두 개의 원 을 그 리 는 것 이 아니 라 겉 원 은 그 라 데 이 션 색 을 사용 하고 안쪽 원 은 흰색 으로 고정한다.
3.회색 바탕 에 아직 도착 하지 않 은 진도 부분 은 회색 이다.
4.진도 값,텍스트 로 표시 하기;
5.원호 형의 머리 는 직선 으로 연결 하거나 곡선 을 사용 하 는 것 을 고려한다.예 를 들 어 베 세 르 곡선 이다.
나 는 먼저 진도 조 의 모습 을 초보 적 으로 실현 하 였 는데,모양 은 있 지만 그다지 아름 답지 않다 는 것 을 발견 하 였 다.
돌 이 켜 보면 저 는 코드 를 쓰 는 사람 일 뿐 어떤 비율 이 아름 다운 지 에 대해 명확 한 인식 이 없 기 때문에 원 도 를 참고 하 세 요.
그리고 정밀 한 측량 을 진행 했다.
그림 을 4 배로 확대 하여 측정 한 다음 에 각 부분의 비례 관 계 를 얻 으 면 구체 적 인 과정 은 자세히 말 하지 않 고 측정 결과(비례 에 따라)를 말 합 니 다.
보기 의 총 길 이 는 300 이 고 그 중에서 앞 에 5 를 비 운 다음 에 5 를 비 운 다음 에 텍스트 가 26 을 차지 하고 뒤에 6 을 비 웁 니 다.
높이 는 4 개 로 나 뉜 다.
바깥
글자 높이:9
내원:6
굵기
상하 각 10 을 비 우 는 것 을 고려 하면 보기 의 높이 는 30 이다.
보기 의 전체적인 효 과 를 고려 하여 사용자 가 길이 와 높이 를 설정 하고 비례 에 따라 최소 값 을 취하 여 그림 을 그 릴 수 있 습 니 다.
먼저 한 단위 의 실제 픽 셀 수 를 계산 하고 각 부분 은 비례 에 따라 표시 하면 된다.
원호 형의 머리 가 하나 더 있 는데 어떻게 이 루어 졌 을까요?
확대 한 후에 도형 이 비교적 간단 하고 라디안 이 보이 지 않 으 면 작은 직선 으로 연결 하면 된다.
이 작은 직선 을 추산 한다.선 은 굵 은 것 이 2 이 고 30 도 각 을 나타 내 며 길 이 는 8-10 이면 된다.직선 과 아크 지붕 을 연결 하고 출발점 은 아크 지붕 의 왼쪽 아래 에 있다.
주의:진도 의 출발점 에서 그 릴 수 없습니다.매우 튀 어 나 온 작은 꼬리 가 나타 나 는 것 을 피하 다.2%진도 후에 야 그림 을 그리 기 시작 했다.
텍스트 를 그 리 는 과정 에서 작은 문제 에 부 딪 혔 습 니 다.바로 문자 가 가운데 에 있 지 않 고 약간 비 뚤 어 졌 기 때 문 입 니 다.인터넷 에서 찾 아 보 았 습 니 다.그 이 유 는 다음 과 같 습 니 다.우리 가 텍스트 를 그 릴 때 사용 하 는 이 함수:canvas.draw Text('30%',x,y,paint)입 니 다.
그 중의 매개 변수 y 는 문자열 baseline 의 위 치 를 가리 키 며 텍스트 의 중심 이 아니다.계산 을 통 해 가운데 로 조정 할 수 있 습 니 다.다음 과 같 습 니 다.

//         
FontMetrics fontMetrics = mPaint.getFontMetrics(); 
float fontHeight = fontMetrics.bottom - fontMetrics.top;
float baseY = height/2 + fontHeight/2 - fontMetrics.bottom;
비율 에 따라 그 려 보 니 그 길 고 우아 한 느낌 이 었 다.
실제 운행 한 결과 글씨체 가 작 아서 세로 로 보기 에는 적합 하지 않 고 크게 조절 한 것 으로 나 타 났 다.
또한 매개 변수 에 대해 다음 과 같은 몇 가지 사용자 정의 속성 을 만 들 었 습 니 다.
전경 색:색상 시작,색상 종료;
진행 항목 이 도착 하지 않 은 기본 색상,
글꼴 색상.
속성 xml 는 다음 과 같 습 니 다:

<?xml version="1.0" encoding="utf-8"?>
<resources>

 <attr name="startColor" format="color" />
 <attr name="endColor" format="color" />
 <attr name="backgroundColor" format="color" />
 <attr name="textColor" format="color" />

 <declare-styleable name="GoodProgressView">
 <attr name="startColor" />
 <attr name="endColor" />
 <attr name="backgroundColor" />
 <attr name="textColor" /> 
 </declare-styleable>

</resources>
사용자 정의 보기 파일:

package com.customview.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.graphics.Paint.Cap;
import android.graphics.Paint.FontMetrics;
import android.graphics.Paint.Style;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import com.customview.R;

public class GoodProgressView extends View
{
 private int[] mColors = { Color.RED, Color.MAGENTA};//     (    2  )
 private int backgroundColor = Color.GRAY;//       
 private int textColor = Color.GRAY;//    

 private Paint mPaint;//  
 private int progressValue=0;//   
// private RectF rect;//    

 public GoodProgressView(Context context, AttributeSet attrs)
 { 
 this(context, attrs, 0);
 }

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

 //             
 public GoodProgressView(Context context, AttributeSet attrs, int defStyle)
 {
 super(context, attrs, defStyle);

 //                 
 TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.GoodProgressView, defStyle, 0);
 int n = a.getIndexCount();
 for (int i = 0; i < n; i++)
 {
  int attr = a.getIndex(i);
  switch (attr)
  {
  case R.styleable.GoodProgressView_startColor:
  //         ,       
  mColors[0] = a.getColor(attr, Color.RED);
  break; 
  case R.styleable.GoodProgressView_endColor:
  //         ,       
  mColors[1] = a.getColor(attr, Color.MAGENTA);
  break; 
  case R.styleable.GoodProgressView_backgroundColor:
  //        ,       
  backgroundColor = a.getColor(attr, Color.GRAY);
  break; 
  case R.styleable.GoodProgressView_textColor:
  //     ,       
  textColor = a.getColor(attr, Color.GRAY);
  break; 
  }
 }
 a.recycle();

 mPaint = new Paint();
 progressValue=0;
 }

 public void setProgressValue(int progressValue){

 if(progressValue>100){
  progressValue = 100;
 }
 this.progressValue = progressValue;
 Log.i("customView","log: progressValue="+progressValue);
 }

 public void setColors(int[] colors){
 mColors = colors; 
 }

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
 {

 int width = 0;
 int height = 0;
 /**
  *     
  */
 int specMode = MeasureSpec.getMode(widthMeasureSpec);
 int specSize = MeasureSpec.getSize(widthMeasureSpec);
 switch (specMode)
 {
 case MeasureSpec.EXACTLY://      
  width = specSize;
  break;
 case MeasureSpec.AT_MOST://    WARP_CONTENT
  width = getPaddingLeft() + getPaddingRight() ;
  break;
 }

 /**
  *     
  */
 specMode = MeasureSpec.getMode(heightMeasureSpec);
 specSize = MeasureSpec.getSize(heightMeasureSpec);
 switch (specMode)
 {
 case MeasureSpec.EXACTLY://      
  height = specSize;
  break;
 case MeasureSpec.AT_MOST://    WARP_CONTENT
  height = width/10;
  break;
 }

 Log.i("customView","log: w="+width+" h="+height);
 setMeasuredDimension(width, height);

 }

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

 int mWidth = getMeasuredWidth();
 int mHeight = getMeasuredHeight();

 //             
 float unit = Math.min(((float)mWidth)/300, ((float)mHeight)/30);
 float lineWidth = 5*unit;//  
 float innerCircleDiameter = 6*unit;//    
 float outerCircleDiameter = 10*unit;//    
 float wordHeight = 12*unit;//  //9*unit
// float wordWidth = 26*unit;//  
 float offsetLength = 5*unit;//  
// float width = 300*unit;//       
 float height = 30*unit;//       
 float progressWidth = 258*unit;//       

 mPaint.setAntiAlias(true);
 mPaint.setStrokeWidth((float) lineWidth );
 mPaint.setStyle(Style.STROKE);
 mPaint.setStrokeCap(Cap.ROUND);

 mPaint.setColor(Color.TRANSPARENT);

 float offsetHeight=height/2;
 float offsetWidth=offsetLength;

 float section = ((float)progressValue) / 100;
 if(section>1)
  section=1;

 int count = mColors.length;
 int[] colors = new int[count];
 System.arraycopy(mColors, 0, colors, 0, count); 

 //      ,        
 mPaint.setShader(null);
 mPaint.setColor(backgroundColor); 
 canvas.drawLine(offsetWidth+section * progressWidth, offsetHeight, offsetWidth+progressWidth, offsetHeight, mPaint);

 //       
 LinearGradient shader = new LinearGradient(0, 0, offsetWidth*2+progressWidth , 0, colors, null,
  Shader.TileMode.CLAMP);
 mPaint.setShader(shader);

 //        
 canvas.drawLine(offsetWidth, offsetHeight, offsetWidth+section*progressWidth, offsetHeight, mPaint);

 //     
 mPaint.setStrokeWidth(1);
 mPaint.setStyle(Paint.Style.FILL);
 canvas.drawCircle(offsetWidth+section * progressWidth, offsetHeight, outerCircleDiameter/2, mPaint);

 //      ,             
 if(section*100>1.8){

  mPaint.setStrokeWidth(2*unit);
  canvas.drawLine(offsetWidth+section * progressWidth-6*unit, offsetHeight-(float)1.5*unit, 
   offsetWidth+section * progressWidth-1*unit,offsetHeight-(float)3.8*unit, mPaint);

  canvas.drawLine(offsetWidth+section * progressWidth-6*unit, offsetHeight+(float)1.5*unit, 
   offsetWidth+section * progressWidth-1*unit,offsetHeight+(float)3.8*unit, mPaint);
 }

 //    
 mPaint.setShader(null);
 mPaint.setColor(Color.WHITE);
 canvas.drawCircle(offsetWidth+section * progressWidth, offsetHeight, innerCircleDiameter/2, mPaint);//    


 //    --   
 mPaint.setStrokeWidth(2*unit);
 mPaint.setColor(textColor);
 mPaint.setTextSize(wordHeight);
 //         
 FontMetrics fontMetrics = mPaint.getFontMetrics(); 
 float fontHeight = fontMetrics.bottom - fontMetrics.top;
 float baseY = height/2 + fontHeight/2 - fontMetrics.bottom;
 canvas.drawText(""+progressValue+"%", progressWidth+2*offsetWidth, baseY, mPaint);//    ,baseline

 }

}
주 xml:
두 개의 진행 바 를 놓 았 습 니 다.하 나 는 기본 값 을 사용 하고 하 나 는 진행 바 의 기본 색상 과 글꼴 색상 을 설정 합 니 다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 xmlns:custom="http://schemas.android.com/apk/res/com.customview"
 android:layout_width="match_parent"
 android:layout_height="match_parent" >

 <com.customview.view.GoodProgressView
 android:id="@+id/good_progress_view1"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:padding="10dp"  
 /> 

 <com.customview.view.GoodProgressView
 android:id="@+id/good_progress_view2"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:layout_centerInParent="true" 
 custom:backgroundColor="#ffcccccc"
 custom:textColor="#ff000000"
 android:padding="10dp"  
 /> 

</RelativeLayout>
액 티 비 티 파일:
하 나 는 기본 그 라 데 이 션 효 과 를 사용 하고 하 나 는 그 라 데 이 션 색 을 무 작위 로 사용 합 니 다.그러면 매번 실행 효과 가 다 르 고 재 미 있 습 니 다.또한 우 리 는 무 작위 효과 에서 비교적 좋 은 색상 조합 을 찾 을 수 있 습 니 다.진도 의 변 화 는 타 이 머 를 사용 하여 추진 하 는 것 이다.

package com.customview;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.WindowManager;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;
import com.customview.view.GoodProgressView;
import android.app.Activity;
import android.graphics.Color;

public class MainActivity extends Activity
{

 GoodProgressView good_progress_view1;
 GoodProgressView good_progress_view2;

 int progressValue=0; 

 @Override
 protected void onCreate(Bundle savedInstanceState)
 {
 super.onCreate(savedInstanceState);
 this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);//     

 setContentView(R.layout.activity_main);
 good_progress_view1 = (GoodProgressView)findViewById(R.id.good_progress_view1);
 good_progress_view2 = (GoodProgressView)findViewById(R.id.good_progress_view2);

 //              ,       (    )
 good_progress_view2.setColors(randomColors());

 timer.schedule(task, 1000, 1000); // 1s   task,  1s      
 }

 Handler handler = new Handler() { 
 public void handleMessage(Message msg) { 
  if (msg.what == 1) { 
  Log.i("log","handler : progressValue="+progressValue);

  //  view,      
  good_progress_view1.setProgressValue(progressValue*2);
  good_progress_view1.postInvalidate();

  good_progress_view2.setProgressValue(progressValue);
  good_progress_view2.postInvalidate();

  progressValue+=1;
  if(progressValue>100){
   timer.cancel();
  }
  } 
  super.handleMessage(msg);  
 }; 
 }; 

 private int[] randomColors() {
 int[] colors=new int[2];

 Random random = new Random();
 int r,g,b;
 for(int i=0;i<2;i++){
  r=random.nextInt(256);
  g=random.nextInt(256);
  b=random.nextInt(256);
  colors[i]=Color.argb(255, r, g, b);
  Log.i("customView","log: colors["+i+"]="+Integer.toHexString(colors[i]));
 }

 return colors;
 }

 Timer timer = new Timer(); 
 TimerTask task = new TimerTask() { 

 @Override 
 public void run() { 
  //      :     
  Message message = new Message(); 
  message.what = 1; 
  handler.sendMessage(message); 
 } 
 }; 

}
최종 효 과 는 다음 과 같다.
세로 화면 시:

가로 화면 시:

원본 다운로드:Android 그 라 데 이 션 색상 진행 막대
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기