간단한 Custom View 작성
간단하게 Custom View 를 작성해 보자. 사실 View 는 기능을 주려면 작성할 것이 많아진다. 하지만 그런것들은 덧붙여지는 것에 지나지 않는다. Custom View 의 핵심은 내가 원하는 View 를 만드는 것이다. 즉 내가 원하는 그림을 그리는 것이다.이런 관점에서 간단하게 'ㅗ' 를 그려주는 View 를 만들어보기로 하자. 소스는 ref. 1 의 소스를 참고해서 만들었다.
만드는 것은 아래에 적혀있는 것만 작성하면 된다.
- attr.xml
- .java
- constructor(생성자)
- onDraw()
- onMeasure()
source codes
values/attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DividerView">
<attr name="dvColor" format="color" />
<attr name="dvHeight" format="dimension" />
<attr name="dvThickness" format="dimension" />
</declare-styleable>
</resources>
DividerView.java
import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; import com.hbwhale.seedmoney.R; /** * Created by namh on 2016-03-26. */ public class DividerView extends View { private Paint _paint; private int _lineHeight; public DividerView(Context context, AttributeSet attrs) { super(context, attrs); int dashGap, lineHeight; int color; TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DividerView, 0, 0); try { lineThickness = a.getDimensionPixelSize(R.styleable.DividerView_dvThickness, 1); _lineHeight = a.getDimensionPixelSize(R.styleable.DividerView_dvHeight, getSuggestedMinimumHeight()); color = a.getColor(R.styleable.DividerView_dvColor, 0xff000000); } finally { a.recycle(); } _paint = new Paint(); _paint.setAntiAlias(true); _paint.setColor(color); _paint.setStyle(Paint.Style.STROKE); _paint.setStrokeWidth(lineThickness); // _paint.setPathEffect(new DashPathEffect(new float[] { lineLength, dashGap, }, 0)); } public DividerView(Context context) { this(context, null); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int height = getSuggestedMinimumHeight(); if(_lineHeight != height){ height = _lineHeight; } setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec), getDefaultSize(height, heightMeasureSpec)); } @Override protected void onDraw(Canvas canvas) { float bottom = getHeight(); float hcenter = getWidth() * 0.5f; canvas.drawLine(hcenter, 0, hcenter, _lineHeight, _paint); // v-line canvas.drawLine(0, bottom, getWidth(), bottom, _paint); // h-line } }
사용법
activity_main.xml
<com.mytest.DividerView android:layout_width="match_parent" android:layout_height="wrap_content" app:dvHeight="15dp" />
onMeasure() 를 override 한 이유
사실 여기서는 'ㅗ' 만 그리면 되기 때문에 onDraw() 만 필요하다. 그런데 왜 onMeasure() 를 작성했느냐 하면, 기본적으로 wrap_content 로 layout_height 를 설정해 놨는데, 실제적으로 content 가 없기 때문에 실제 height 는 0 이 된다.(말이 복잡하니 그냥 넘어가자.)여하튼 중요한 것은 DividerView 가 공간을 차지해야 보여진다. 그래서 실제로 height 가 필요하다. width 는 match_parent 이기에 0 이상의 값을 가지고 있다.
그래서 높이만 갖고 있으면 된다. 그러기 위해선 아래처럼 minHeight 를 설정해줘도 된다.
<com.mytest.DividerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="5dp"
/>
그런데 minHeight 는 좋은 design 이 아니다. 이것은 layout 의 size 이지 DividerView 의 size 가 아니기 때문이다. 그래서 이것을 app:dvHeight 로 대체했다. 그로인해 dvHeight 에서 설정한 값이 DividerView 의 height 에 반영이 되어야 했다.
그래서 onMeasure() 가 필요한 것이다. View 의 size 를 정하는 곳이 onMeasure() 이기 때문이다.(참고: Android 의 View 에서 onMeasure 와 onLayout 의 의미)
댓글 없음:
댓글 쓰기