안드로이드/고급

[PAAD] 4장 커스텀 뷰 만들기

success17 2011. 8. 14. 16:03


1. 기존 뷰 수정하기

// ** Listing 4-5: Extending TextView (Extended)
public class MyTextView extends TextView {

  public MyTextView (Context context, AttributeSet ats, int defStyle) {
    super(context, ats, defStyle);
  }
 
  public MyTextView (Context context) {
    super(context);
  }

  public MyTextView (Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  public void onDraw(Canvas canvas) {
    [ ... Draw things on the canvas under the text ... ]

    // Render the text as usual using the TextView base class.
    super.onDraw(canvas);

    [ ... Draw things on the canvas over the text ... ]
  }

  @Override
  public boolean onKeyDown(int keyCode, KeyEvent keyEvent) {
    [ ... Perform some special processing ... ]
    [ ... based on a particular key press ... ]

    // Use the existing functionality implemented by
    // the base class to respond to a key press event.
    return super.onKeyDown(keyCode, keyEvent);
  }
}

ⓐ 기존뷰를 상속한다
ⓑ 생성자와 OnDraw()를 구현한다
ⓒ 리소스 id를 사용하기위해 xml을 만든다"<com.paad.todolist.TodoListItemView>"와같이 풀패키지 이름으로




2. 복합 컨트롤 만들기
ⓐ xml로 레이아웃을 만들고
ⓑ 레이아웃을 상속하여 xml 컨포넌트들을 인플레이트 시켜 행동을 구현한다


3. 커스텀 뷰 만들기
ⓐ onMeasure 오버라이딩: 자신이 차지할 폭과 높이를 계산
ⓑ OnDraw: 캔버스에 그린다



// *******************************************************************
// ** Listing 4-10: Creating a new View class
public class MyView extends View {

  // Constructor required for in-code creation
  public MyView(Context context) {
    super(context);
  }
 
  // Constructor required for inflation from resource file
  public MyView (Context context, AttributeSet ats, int defaultStyle) {
    super(context, ats, defaultStyle );
  }

  //Constructor required for inflation from resource file
  public MyView (Context context, AttributeSet attrs) {
    super(context, attrs);
  }

  @Override
  protected void onMeasure(int wMeasureSpec, int hMeasureSpec) {
    int measuredHeight = measureHeight(hMeasureSpec);
    int measuredWidth = measureWidth(wMeasureSpec);

    // MUST make this call to setMeasuredDimension
    // or you will cause a runtime exception when
    // the control is laid out.
    setMeasuredDimension(measuredHeight, measuredWidth);
  }

  private int measureHeight(int measureSpec) {
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

     [ ... Calculate the view height ... ]

     return specSize;
  }

  private int measureWidth(int measureSpec) {
    int specMode = MeasureSpec.getMode(measureSpec);
    int specSize = MeasureSpec.getSize(measureSpec);

     [ ... Calculate the view width ... ]

     return specSize;
  }

  @Override
  protected void onDraw(Canvas canvas) {
    [ ... Draw your visual interface ... ]
  }
}


// ** Listing 4-13: A typical View measurement implementation
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  int measuredHeight = measureHeight(heightMeasureSpec);
  int measuredWidth = measureWidth(widthMeasureSpec);

  setMeasuredDimension(measuredHeight, measuredWidth);
}

private int measureHeight(int measureSpec) {
  int specMode = MeasureSpec.getMode(measureSpec);
  int specSize = MeasureSpec.getSize(measureSpec);

  //  Default size if no limits are specified.
  int result = 500;

  if (specMode == MeasureSpec.AT_MOST) {
    // Calculate the ideal size of your
    // control within this maximum size.
    // If your control fills the available
    // space return the outer bound.
    result = specSize;
  } else if (specMode == MeasureSpec.EXACTLY) {
    // If your control can fit within these bounds return that value.
    result = specSize;
  }
  return result;
}

private int measureWidth(int measureSpec) {
  int specMode = MeasureSpec.getMode(measureSpec);
  int specSize = MeasureSpec.getSize(measureSpec);

  //  Default size if no limits are specified.
  int result = 500;

  if (specMode == MeasureSpec.AT_MOST) {
    // Calculate the ideal size of your control
    // within this maximum size.
    // If your control fills the available space
    // return the outer bound.
    result = specSize;
  } else if (specMode == MeasureSpec.EXACTLY) {
    // If your control can fit within these bounds return that value.
    result = specSize;
  }
  return result;
}