마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

커스텀 켈린더 뷰 그리기에서 날자가 들어가는 뷰 그리기

0 추천

안녕하세요. 

커스텀 달력 그리기 공부중에 궁한 점이 있어서 질문을 올립니다.

아래 소스 코드를 보면 onMeasure 메소드 내부에 각 날자가 들어가는 view의 크기를 계산하는 부분이 있는데

이 부분이 어떤걸 의미하는지는 알겠는데 작동 Logic이 이해가 되지 않아서 도움을 요청하려고 합니다.

1. for 문에서 if(child.getVisibility() == INVISIBLE) continue;가 뜻하는게 무엇인가요?

2.   maxWidth += Math.max(maxWidth, child.getMeasuredWidth());
            mLeftWidth += child.getMeasuredWidth();

이 코드가 이해가 되질 않습니다. 

만약 첫번째 view의 크기를 계산한다고 가정했을때 maxWidth의 초기 값은 0이고 child.getMeasuredWidth()도 아직 계산된 값이 없기 때문에 0이고 그렇게 되면 view의 크기가 없는게 아닌가요?

 

public class CalendarView extends ViewGroup {

    private final int mScreenWidth;
    private final int mWidthDate;

    private long mMillis;
    /**
     * 1일의 요일
     */
    private int mDateOfWeek;
    /**
     * 해당월의 마지막 날짜
     */
    private int mMaxtDateOfMonth;

    private int mDefaultTextSize = 40;

    //  private int mTextColor = Color.BLUE;

    // private Paint mPaint = makePaint(mTextColor);
    //  private Paint mTestPaint = makePaint(mTextColor);

   // public CalendarItemView mCurrentSelectedView = null;

    public static String[] DAY_OF_WEEK = null;

    public CalendarView(Context context, AttributeSet attrs) {
        super(context, attrs);

        mScreenWidth = getResources().getDisplayMetrics().widthPixels;
        mWidthDate = mScreenWidth / 7;
        DAY_OF_WEEK = getResources().getStringArray(R.array.day_of_week);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int count = getChildCount();
        // Measurement will ultimately be computing these values.
        int maxHeight = 0;
        int maxWidth = 0;
        int childState = 0;
        int mLeftWidth = 0;
        int rowCount = 0;

        for (int i = 0; i < count; i++) {
            final View child = getChildAt(i);

            if (child.getVisibility() == INVISIBLE)
                continue;

            // Measure the child.
            measureChild(child, widthMeasureSpec, heightMeasureSpec);
            maxWidth += Math.max(maxWidth, child.getMeasuredWidth());
            mLeftWidth += child.getMeasuredWidth();

            if ((mLeftWidth / mScreenWidth) > rowCount) {
                maxHeight += child.getMeasuredHeight();
                rowCount++;
            } else {
                maxHeight = Math.max(maxHeight, child.getMeasuredHeight());
            }
            childState = combineMeasuredStates(childState, child.getMeasuredState());
        }

        maxHeight = (int) (Math.ceil((count + mDateOfWeek - 1) / 7d) * (mWidthDate * 0.75));// 요일중 일요일이 1부터 시작하므로 1을 빼줌
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth());
        int expandSpec = MeasureSpec.makeMeasureSpec(MEASURED_SIZE_MASK, MeasureSpec.AT_MOST);

        setMeasuredDimension(resolveSizeAndState(maxWidth, widthMeasureSpec, childState),
                resolveSizeAndState(maxHeight, expandSpec, childState << MEASURED_HEIGHT_STATE_SHIFT));

        LayoutParams params = getLayoutParams();
        params.height = getMeasuredHeight();
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {


        final int count = getChildCount();
        int curWidth, curHeight, curLeft, curTop, maxHeight;

        final int childLeft = this.getPaddingLeft();
        final int childTop = this.getPaddingTop();
        final int childRight = this.getMeasuredWidth() - this.getPaddingRight();
        final int childBottom = this.getMeasuredHeight() - this.getPaddingBottom();
        final int childWidth = childRight - childLeft;
        final int childHeight = childBottom - childTop;

        maxHeight = 0;
        curLeft = childLeft;
        curTop = childTop;

        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);

            if (child.getVisibility() == GONE)
                return;

            child.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
            curWidth = mWidthDate;
            curHeight = (int) (mWidthDate * 0.75);

            if (curLeft + curWidth >= childRight) {
                curLeft = childLeft;
                curTop += maxHeight;
                maxHeight = 0;
            }
            if (i == 7) {
                curLeft = (mDateOfWeek - 1) * curWidth;
            }
            child.layout(curLeft, curTop, curLeft + curWidth, curTop + curHeight);

            if (maxHeight < curHeight) {
                maxHeight = curHeight;
            }
            curLeft += curWidth;
        }
    }

    public void setDate(long millis) {
        mMillis = millis;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(millis);
        calendar.set(Calendar.DATE, 1);

        mDateOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        mMaxtDateOfMonth = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);

        invalidate();
    }

    // TODO : touch로 scale in/out 기능 추가
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                break;
            case MotionEvent.ACTION_UP:
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }

    private Paint makePaint(int color) {
        Paint p = new Paint(Paint.ANTI_ALIAS_FLAG);
        p.setColor(color);
        p.setTextSize(mDefaultTextSize);
        return p;
    }

    public void initCalendar(int dayOfWeek, int maxDateOfMonth) {
        mDateOfWeek = dayOfWeek;
        mMaxtDateOfMonth = maxDateOfMonth;
    }

    public void setCurrentSelectedView(View view) {
        if (getParent() instanceof ViewPager) {
            ViewPager pager = (ViewPager) getParent();
            View tagView = (View) pager.getTag();
            if (tagView != null) {
                long time = (long) tagView.getTag();
                Calendar c = Calendar.getInstance();
                c.setTimeInMillis(time);
                for (int i = 0; i < pager.getChildCount(); i++) {
                    for (int j = 0; j < getChildCount(); j++) {
                        CalendarItemView child = (CalendarItemView) ((CalendarView) pager.getChildAt(i)).getChildAt(j);
                        if (child == null) {
                            continue;
                        }
                        if (child.isStaticText()) {
                            continue;
                        }
                        if (child.isSameDay((Long) child.getTag(), (Long) tagView.getTag())) {
                            child.invalidate();
                            break;
                        }
                    }
                }
            }
            if (tagView == view) {
                pager.setTag(null);
                return;
            }
            long time = (long) view.getTag();
            Calendar cal = Calendar.getInstance();
            cal.setTimeInMillis(time);
            pager.setTag(view);
            view.invalidate();
        }
    }
}

 

존크레쉬 (160 포인트) 님이 2019년 9월 22일 질문

1개의 답변

+1 추천
1. visible/invisible/gone 에 대해 찾아보세요... continue/break 도 찾아보시고요.

2. 둘 다 없으면 0이 되겠고, 아니면 큰 값이 오겠죠. 브레이크 포인트 찍어서 디버그 모드로 돌려보세요. 그럼 무슨 값이 오는지 다 알 수 있습니다.
쎄미 (162,410 포인트) 님이 2019년 9월 23일 답변
...