Android 사용자 정의 View 접선 도 효과 구현

다음은 결과 그림 입 니 다.

1.홈 페이지 레이아웃 파일 은 다음 과 같 습 니 다.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
 xmlns:tools="http://schemas.android.com/tools" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 tools:context=".MainActivity" 
 xmlns:app="http://schemas.android.com/apk/res/ting.example.linecharview"> 
 <ting.example.linecharview.LineCharView 
 android:id="@+id/test" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 app:xytextcolor="@color/bg" 
 app:xytextsize="20sp" 
 app:interval="80dp" 
 /> 
</RelativeLayout> 
그 중에서linecharview는 사용자 정의View이 고app:xx는 바로 이View의 각종 속성 이다.
2.values의 attrs 파일 에 다음 과 같은 xml 를 추가 하여linecharview의 각종 속성 을 정의 합 니 다.

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
 <declare-styleable name="LineChar"> 
 <attr name="xylinecolor" format="color"/><!-- xy      --> 
 <attr name="xylinewidth" format="dimension"/><!-- xy      --> 
 <attr name="xytextcolor" format="color"/><!-- xy        --> 
 <attr name="xytextsize" format="dimension"/><!-- xy        --> 
 <attr name="linecolor" format="color"/><!--           --> 
 <attr name="interval" format="dimension"/><!-- x           --> 
 <attr name="bgcolor" format="color"/><!--      --> 
 </declare-styleable> 
</resources> 
3.다음 에 개 류LineCharView 계승View을 구축 하고 다음 과 같은 변 수 를 설명 한다.

<span style="white-space:pre"> </span>private int xori;//  x   
 private int yori;//  y   
 private int xinit;//    x   
 private int minXinit;//    ,         x   
 private int maxXinit;//    ,           x   
 private int xylinecolor;//xy      
 private int xylinewidth;//xy      
 private int xytextcolor;//xy        
 private int xytextsize;//xy        
 private int linecolor;//      
 private int interval;//       
 private int bgColor;//     
 private List<String> x_coords;//x      
 private List<String> x_coord_values;//       
 
 
 private int width;//     
 private int heigth;//     
 private int imageWidth;//      
 private float textwidth;//y       
 float startX=0;//    ,      x   
구조 함수 에서 각 속성 값 읽 기:

public LineCharView(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 TypedArray typedArray= context.obtainStyledAttributes(attrs, R.styleable.LineChar); 
 xylinecolor=typedArray.getColor(R.styleable.LineChar_xylinecolor, Color.GRAY); 
 xylinewidth=typedArray.getInt(R.styleable.LineChar_xylinewidth, 5); 
 xytextcolor=typedArray.getColor(R.styleable.LineChar_xytextcolor, Color.BLACK); 
 xytextsize=typedArray.getLayoutDimension(R.styleable.LineChar_xytextsize, 20); 
 linecolor=typedArray.getColor(R.styleable.LineChar_linecolor, Color.GRAY); 
 interval=typedArray.getLayoutDimension(R.styleable.LineChar_interval, 100); 
 bgColor=typedArray.getColor(R.styleable.LineChar_bgcolor, Color.WHITE); 
 typedArray.recycle(); 
 x_coords=new ArrayList<String>(); 
 x_coord_values=new ArrayList<String>(); 
} 
4.그 다음 에 다시 쓰기onLayout방법 으로 컨트롤 의 너비 와 좌표 축의 원점 좌 표를 계산 할 수 있 습 니 다.좌표 축 원점 의 x 좌 표 는 y 축 문자 의 너비,y 축 너비 와 거리 y 의 수평 거 리 를 통 해 계산 할 수 있 습 니 다.여기 서 y 축 문 자 는 4 가지 상태(A,B,C,D)만 있 고 아래 의 방법 으로 원점 의 x 좌 표를 계산 할 수 있 습 니 다.

Paint paint=new Paint(); 
paint.setTextSize(xytextsize); 
textwidth= paint.measureText("A"); 
xori=(int) (textwidth+6+2*xylinewidth);//6   y     
원점 의 y 좌표 도 비슷 한 방법 으로 계산 할 수 있다.

yori=heigth-xytextsize-2*xylinewidth-3; //3 x    ,heigth     。 
보 여 줘 야 할 데이터 양 이 많 을 때 모두 보 여줄 수 없 을 때 미끄럼 접선 도 를 통 해 보 여 줘 야 합 니 다.우 리 는 첫 번 째 x 좌표 만 제어 하면 interval 이라는 속성 을 통 해 뒤의 각 점 의 좌 표를 계산 할 수 있 습 니 다.그러나 모든 데 이 터 를 인터페이스 밖으로 미 끄 러 뜨리 는 것 을 방지 하기 위해 서 는 미 끄 러 질 때 제어 해 야 합 니 다.사실은 첫 번 째 점 x 좌표 의 범 위 를 제어 하 는 것 이다.첫 번 째 점 의 x 좌표 의 최소 치 는 컨트롤 의 폭 을 통 해 원점 x 좌 표를 빼 고 모든 접선 그림 의 수평 거 리 를 줄 일 수 있다.코드 는 다음 과 같다.

minXinit=width-xori-x_coords.size()*interval; 
컨트롤 은 기본적으로 첫 번 째 전시 에서 첫 번 째 점 과 y 축의 수평 거 리 는interval의 절반 과 같 습 니 다.미 끄 러 질 때 첫 번 째 점 이 이 위치 에 나타 나 면 더 이상 오른쪽으로 미 끄 러 지 는 것 을 허용 하지 않 기 때문에 첫 번 째 점 x 좌표 의 최대 치 는 이 시작 x 좌 표를 기다 리 고 있 습 니 다.

xinit=interval/2+xori; 
maxXinit=xinit; 
다시 쓰기onLayout방법의 코드 는 다음 과 같다.

@Override 
 protected void onLayout(boolean changed, int left, int top, int right, 
 int bottom) { 
 if(changed){ 
 width=getWidth(); 
 heigth=getHeight(); 
 Paint paint=new Paint(); 
 paint.setTextSize(xytextsize); 
 textwidth= paint.measureText("A"); 
 xori=(int) (textwidth+6+2*xylinewidth);//6   y     
 yori=heigth-xytextsize-2*xylinewidth-3;//3 x     
 xinit=interval/2+xori; 
 imageWidth= BitmapFactory.decodeResource(getResources(), R.drawable.facea).getWidth(); 
 minXinit=width-xori-x_coords.size()*interval; 
 maxXinit=xinit; 
 setBackgroundColor(bgColor); 
 } 
 super.onLayout(changed, left, top, right, bottom); 
 } 
5.그 다음 에 접 는 선,x 좌표 축 에 있 는 작은 원점 과 접 는 선 에 있 는 표정 을 그 릴 수 있 습 니 다.
코드 는 다음 과 같 습 니 다:

// X    ,  ,   
 @SuppressLint("ResourceAsColor") 
 private void drawX (Canvas canvas) { 
 Paint x_coordPaint =new Paint(); 
 x_coordPaint.setTextSize(xytextsize); 
 x_coordPaint.setStyle(Paint.Style.FILL); 
 Path path=new Path(); 
 //        ,      
 for(int i=0;i<x_coords.size();i++){ 
 int x=i*interval+xinit; 
 if(i==0){ 
 path.moveTo(x, getYValue(x_coord_values.get(i))); 
 }else{ 
 path.lineTo(x, getYValue(x_coord_values.get(i))); 
 } 
 x_coordPaint.setColor(xylinecolor); 
 canvas.drawCircle(x, yori, xylinewidth*2, x_coordPaint); 
 String text=x_coords.get(i); 
 x_coordPaint.setColor(xytextcolor); 
 canvas.drawText(text, x-x_coordPaint.measureText(text)/2, yori+xytextsize+xylinewidth*2, x_coordPaint); 
 } 
 
 x_coordPaint.setStyle(Paint.Style.STROKE); 
 x_coordPaint.setStrokeWidth(xylinewidth); 
 x_coordPaint.setColor(linecolor); 
 //    
 canvas.drawPath(path, x_coordPaint); 
 
 
 //    
 for(int i=0;i<x_coords.size();i++){ 
 int x=i*interval+xinit; 
 canvas.drawBitmap(getYBitmap(x_coord_values.get(i)), x-imageWidth/2, getYValue(x_coord_values.get(i))-imageWidth/2, x_coordPaint); 
 } 
 
 
 //     x          
 x_coordPaint.setStyle(Paint.Style.FILL); 
 x_coordPaint.setColor(bgColor); 
 x_coordPaint.setXfermode(new PorterDuffXfermode( PorterDuff.Mode.SRC_OVER)); 
 RectF rectF=new RectF(0, 0, xori, heigth); 
 canvas.drawRect(rectF, x_coordPaint); 
 
 } 
상기 코드 는 먼저x_coordsx_coord_values두 개의 List 집합 을 통 해 좌표 점,접 는 선,표정 을 그립 니 다.왼쪽으로 미 끄 러 질 때 좌표 점,접 는 선 을 Y 축의 왼쪽 에 그 릴 수 있 기 때문에 이 를 절단 해 야 합 니 다.그 중에서getYValue와 getYBitmap 방법 은x_coord_values의 값 으로 y 좌표 와 해당 하 는 표정 을 계산 할 수 있다.두 가지 방법 은 다음 과 같다.

//  y   
 private float getYValue(String value) 
 { 
 if(value.equalsIgnoreCase("A")){ 
 return yori-interval/2; 
 } 
 else if(value.equalsIgnoreCase("B")){ 
 return yori-interval; 
 } 
 else if(value.equalsIgnoreCase("C")){ 
 return (float) (yori-interval*1.5); 
 } 
 else if(value.equalsIgnoreCase("D")){ 
 return yori-interval*2; 
 }else{ 
 return yori; 
 } 
 } 
 
 
 //      
 private Bitmap getYBitmap(String value){ 
 Bitmap bitmap=null; 
 if(value.equalsIgnoreCase("A")){ 
 bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.facea); 
 } 
 else if(value.equalsIgnoreCase("B")){ 
 bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.faceb); 
 } 
 else if(value.equalsIgnoreCase("C")){ 
 bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.facec); 
 } 
 else if(value.equalsIgnoreCase("D")){ 
 bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.faced); 
 } 
 return bitmap; 
 } 
6.좌표 점,접 는 선,표정 을 그 렸 습 니 다.그 다음 에 간단 하면 x y 축 을 그 릴 수 있 습 니 다.x y 축 은 원점 좌표 만 확정 하면 매우 간단 합 니 다.코드 는 다음 과 같 습 니 다.

//     
private void drawXY(Canvas canvas){ 
 Paint paint=new Paint(); 
 paint.setColor(xylinecolor); 
 paint.setStrokeWidth(xylinewidth); 
 canvas.drawLine(xori, 0, xori, yori, paint); 
 canvas.drawLine(xori, yori, width, yori, paint); 
} 
7.마지막 으로 Y 축의 좌표 작은 원점 과 y 축의 문 자 를 그 릴 수 있 습 니 다.

// Y     
 private void drawY(Canvas canvas){ 
 Paint paint=new Paint(); 
 paint.setColor(xylinecolor); 
 paint.setStyle(Paint.Style.FILL); 
 for(int i=1;i<5 ;i++){ 
 canvas.drawCircle(xori, yori-(i*interval/2), xylinewidth*2, paint); 
 } 
 
 paint.setTextSize(xytextsize); 
 paint.setColor(xytextcolor); 
 canvas.drawText("D",xori-textwidth-6-xylinewidth , yori-(2*interval)+xytextsize/2, paint); 
 canvas.drawText("C",xori-textwidth-6-xylinewidth , (float) (yori-(1.5*interval)+xytextsize/2), paint); 
 canvas.drawText("B",xori-textwidth-6-xylinewidth , yori-interval+xytextsize/2, paint); 
 canvas.drawText("A",xori-textwidth-6-xylinewidth , (float) (yori-(0.5*interval)+xytextsize/2), paint); 
 } 
8.상기 세 가지 방법 을 다 썼 습 니 다.다시 쓰기onDraw방법 만 있 으 면 그 릴 수 있 습 니 다.

@Override 
 protected void onDraw(Canvas canvas) { 
 drawX(canvas); 
 drawXY(canvas); 
 drawY(canvas); 
 } 
9.수평 으로 미 끄 러 지기 위해 서 는 컨트롤 의 onTouchEvent 방법 을 다시 써 야 합 니 다.미 끄 러 질 때 손가락 이 미 끄 러 지 는 거 리 를 실시 간 으로 계산 하여 첫 번 째 점 의 x 좌 표를 바 꾼 다음 에 호출invalidate();하면 컨트롤 을 새로 고 쳐 서 미 끄 러 지 는 효 과 를 얻 을 수 있 습 니 다.

@Override 
 public boolean onTouchEvent(MotionEvent event) { 
 
 //               ,      
 if(interval*x_coord_values.size()<=width-xori){ 
 return false; 
 } 
 
 switch (event.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 startX=event.getX(); 
 break; 
 
 case MotionEvent.ACTION_MOVE: 
 float dis=event.getX()-startX; 
 startX=event.getX(); 
 if(xinit+dis>maxXinit){ 
 xinit=maxXinit; 
 }else if(xinit+dis<minXinit){ 
 xinit=minXinit; 
 }else{ 
 xinit=(int) (xinit+dis); 
 } 
 invalidate(); 
 
 break; 
 } 
 return true; 
 } 
10.마지막 으로 데이터 원본 을 설정 하 는 방법 을 추가 합 니 다.설정x_coords,x_coord_values이 두 개List를 집합 하고 설정 이 완 료 된 후에 호출invalidate() 하여 컨트롤 새로 고침 을 합 니 다.

/** 
 *          
 * @param x_coords        
 * @param x_coord_values       
 */ 
public void setValue( List<String> x_coords ,List<String> x_coord_values) { 
 if(x_coord_values.size()!=x_coords.size()){ 
 throw new IllegalArgumentException("                  !"); 
 } 
 this.x_coord_values=x_coord_values; 
 this.x_coords=x_coords; 
 invalidate(); 
} 
총결산
안 드 로 이 드 사용자 정의 뷰 가 접 힌 그림 효 과 를 실현 하 는 모든 내용 입 니 다.안 드 로 이 드 개발 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기