Android 개발 의 날씨 트 렌 드 접선 도

먼저 효과 보기:

컨트롤 내용 이 비교적 간단 합 니 다.바로 일반적인 접 는 선 그림 입 니 다.상하 에 각각 숫자 가 있 고 클릭 할 때 당일 온도 의 차 이 를 표시 합 니 다. 
클래스 계승 뷰 를 만 들 고 두 가지 구조 방법 을 추가 합 니 다.

public class TrendGraph extends View {
  public TrendGraph(Context context) { //  java       
    super(context);
  }

  public TrendGraph(Context context, AttributeSet attrs) { //  xml     
    super(context, attrs);
  }
} 
여 기 는 wrap 을 고려 할 필요 가 없 으 니까 요.content 의 경우 onMeasure 방법 은 다시 쓸 필요 가 없습니다.관건 적 인 것 은 onDraw 입 니 다.onDraw 방법 도 어렵 지 않 습 니 다.각 점 의 구체 적 인 위 치 를 잘 정 하면 됩 니 다.연결선 도 점 의 좌표 가 필요 하기 때문에 코드 가 비교적 부 드 럽 고 생략 할 수 있 습 니 다.

   @Override
   protected void onDraw(Canvas canvas) {
     super.onDraw(canvas);
     if (mElements == null || mElements.size() == 0) {
       return;
     }
     double max_up = getMaxUp();
     double min_down = getMinDown();
     canvas.setDrawFilter(mDrawFilter);
     mPaint.setStrokeWidth(lineWeith);
     float width = getWidth();
     float grap = width / mElements.size();
     float textSize = mTextPaint.getTextSize();
     int textMargin = circleRadius * 2;
     float margin_top = textSize + 2 * textMargin;
     Log.d(TAG, "onDraw: " + margin_top + "|" + textSize);
     float height = getHeight() - 2 * margin_top;
 
     for (int i = 0; i < mElements.size() - 1; i++) {
       float startX = i * grap + grap / 2;
       float stopX = (i + 1) * grap + grap / 2;
       float startY = (float) (max_up - mElements.get(i).getUp()) / (float) (max_up -
           min_down) * height + margin_top;
       float stopY = (float) (max_up - mElements.get(i + 1).getUp()) / (float) (max_up -
           min_down) * height + margin_top;
 
       canvas.drawText((int) mElements.get(i).getUp() + "℃", startX - textSize, startY -
           textMargin, mTextPaint);
       canvas.drawCircle(startX, startY, circleRadius, mPaint);
       canvas.drawLine(startX, startY, stopX, stopY, mPaint);
       if (i == mElements.size() - 2) {
         canvas.drawText((int) mElements.get(i + 1).getUp() + "℃", stopX - textSize, stopY
             - textMargin, mTextPaint);
         canvas.drawCircle(stopX, stopY, circleRadius, mPaint);
       }
 
       startY = (float) (max_up - mElements.get(i).getDown()) / (float) (max_up - min_down) *
           height + margin_top;
       stopY = (float) (max_up - mElements.get(i + 1).getDown()) / (float) (max_up -
           min_down) * height + margin_top;
       canvas.drawText((int) mElements.get(i).getDown() + "℃", startX - textSize, startY +
           textSize + textMargin, mTextPaint);
       canvas.drawCircle(startX, startY, circleRadius, mPaint);
       canvas.drawLine(startX, startY, stopX, stopY, mPaint);
       if (i == mElements.size() - 2) {
         canvas.drawText((int) mElements.get(i + 1).getDown() + "℃", stopX - textSize,
             stopY + textSize + textMargin, mTextPaint);
         canvas.drawCircle(stopX, stopY, circleRadius, mPaint);
       }
     }
   }
사용자 가 간단 한 설정 을 할 수 있 도록 해 야 합 니 다.예 를 들 어 점 의 크기,문자 크기 등 을 고려 하여 사용자 정의 속성(res/values/attr.xml)을 정의 합 니 다.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="TrendGraph">
    <attr name="lineWidth" format="dimension"/>
    <attr name="circleRadius" format="dimension" />
    <attr name="textSize" format="dimension" />
    <attr name="textColor" format="reference" />
  </declare-styleable>
</resources>
format 는 이 속성의 형식 을 말 합 니 다.dimension 으로 지정 하면 사이즈 이 고,값 을 추출 하 는 단 위 는 dp,sp 또는 px 등 이 며,reference 는 참조 입 니 다.즉,일반적으로 xml 에서 다른 자원 의 쓰기,예 를 들 어@string/app 을 참조 합 니 다.name。다른 유형 도 있어 서 스스로 문 서 를 찾 을 수 있 습 니 다. 
사용자 정의 속성 을 분석 할 수 있 습 니 다.이 분석 은 위 에서 정의 한 두 번 째 구조 방법 에서 이 루어 져 야 합 니 다.코드 는 다음 과 같 습 니 다.

  public TrendGraph(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.TrendGraph);
    circleRadius = array.getDimensionPixelSize(R.styleable.TrendGraph_circleRadius, 5);
    lineWeith = array.getDimensionPixelSize(R.styleable.TrendGraph_lineWidth, 3);
    mTextPaint.setTextSize(array.getDimensionPixelSize(R.styleable.TrendGraph_textSize, 35));
    mTextPaint.setColor(array.getColor(R.styleable.TrendGraph_textColor, Color.BLACK));
    array.recycle();
  }
getDimension PixelSize 방법 은 들 어 오 는 값 을 통 해 구체 적 인 픽 셀(px)값 으로 전환 하면 수 동 으로 전환 하 는 번 거 로 움 을 피 할 수 있 습 니 다.그러나 그 중의 defaultValue 는 여전히 px 임 을 주의해 야 한다.
이 어 xml 를 통 해 이 속성 을 지정 하고 레이아웃 에 네 임 스페이스 를 추가 할 수 있 습 니 다.

xmlns:app=http://schemas.android.com/apk/res-auto
Android Studio 가 자동 으로 도입 되 고 보완 할 수 있 으 며 구체 적 으로 사용 할 수 있 습 니 다.

  <com.fndroid.byweather.views.TrendGraph
    android:id="@+id/tg"
    android:layout_width="match_parent"
    app:textColor="@color/colorAccent"
    app:textSize="22sp"
    app:circleRadius="2dp"
    android:layout_height="200dp"/>
마지막 으로 이벤트 감청 을 추가 하고 View 를 클릭 할 때 리 셋 합 니 다.
① 정의 인터페이스:

  public interface onItemClickListener{
    void onItemClick(View view, Element element);
  }
② View 에 인터페이스 대상 을 추가 하고 setter 방법 을 설정 합 니 다.

public class TrendGraph extends View {

  private onItemClickListener mOnItemClickListener;

  //     

  public void setOnItemClickListener(onItemClickListener onItemClickListener) {
    mOnItemClickListener = onItemClickListener;
  }

} 
③ onTouchEvent 를 처리 하고 이 방법 을 다시 작성 합 니 다.코드 는 다음 과 같 습 니 다.

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    int viewWidth = getWidth();
    int itemWidth = viewWidth / mElements.size();
    int viewHeight = getHeight();
    boolean isMove = false; //          NestedScrollView,            ,      

    switch (event.getAction()) {
      case MotionEvent.ACTION_MOVE:
        isMove = true;
        break;
      case MotionEvent.ACTION_UP:
        if (!isMove){ //            
          int position = (int) (event.getX() / itemWidth); //        
          mOnItemClickListener.onItemClick(this, mElements.get(position)); //   
        }
        break;
    }

    return true;
  }
④ Activity 에서 감청 설정 을 하고 처리 합 니 다.

  historyGraph.setOnItemClickListener(this);
  @Override
  public void onItemClick(View view, TrendGraph.Element element) {
    int dt = (int) (element.getUp() - element.getDown());
    Snackbar.make(root, "     :" + dt + "℃", Snackbar.LENGTH_SHORT).show();
  }
총결산
효과 완성!질문 이 있 으 시 면 토론 을 환영 합 니 다.본 고 는 안 드 로 이 드 개발 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기