[컴][안드로이드] 간단한 Custom View 작성

커스텀뷰 작성 / how to draw custom view

간단한 Custom View 작성

간단하게 Custom View 를 작성해 보자. 사실 View 는 기능을 주려면 작성할 것이 많아진다. 하지만 그런것들은 덧붙여지는 것에 지나지 않는다. Custom View 의 핵심은 내가 원하는 View 를 만드는 것이다. 즉 내가 원하는 그림을 그리는 것이다.

이런 관점에서 간단하게 'ㅗ' 를 그려주는 View 를 만들어보기로 하자. 소스는 ref. 1 의 소스를 참고해서 만들었다.

만드는 것은 아래에 적혀있는 것만 작성하면 된다.

  1. attr.xml
  2. .java
    1. constructor(생성자)
    2. onDraw()
    3. 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 의 의미)



Reference


  1. xml - Creating horizontal and vertical dotted lines in android - Stack Overflow




댓글 없음:

댓글 쓰기