CursorWheelLayout 오픈소스 기여 가이드: Android 회전 선택기 라이브러리 개발 참여 방법

프로젝트 개요 및 기여 가치

CursorWheelLayout은 Android 환경에서 원형 휠 기반의 아이템 선택 UI를 구현하는 커스텀 뷰 라이브러리입니다. 기존 리니어 리스트와 차별화된 회전 인터랙션을 제공하며, 터치 이벤트 처리 및 Canvas 드로잉 최적화 등 Android 프레임워크의 핵심 기술을 다루고 있습니다. 본 문서는 저장소에 코드를 기여하거나 기능을 확장하려는 개발자를 위한 실무 가이드입니다.

개발 환경 구성 및 소스 구조

기여를 시작하기 전 로컬 개발 환경을 다음과 같이 설정합니다.

  • IDE: Android Studio Hedgehog 이상
  • 빌드 시스템: Gradle 8.0+, AGP 8.1+
  • 언어: Java 17 또는 Kotlin 1.9+

저장소를 클론한 후 주요 디렉토리 구조를 파악합니다.

git clone https://github.com/BCsl/CursorWheelLayout.git
cd CursorWheelLayout

핵심 소스는 library/src/main/java/ 경로에 위치하며, 샘플 구현체는 app/ 모듈에서 확인할 수 있습니다. 레이아웃 리소스는 res/layout/res/values/ 하위에 정의되어 있습니다.

기여 워크플로우 및 브랜치 정책

효율적인 협업을 위해 다음 브랜치 전략을 따릅니다.

  • main: 프로덕션 레벨의 안정화된 코드만 병합
  • dev: 신규 기능 통합 및 지속적 통합(CI) 검증용
  • feat/{기능명}: dev에서 분기하여 신규 로직 개발
  • fix/{이슈번호}: main에서 분기하여 긴급 결함 수정

Issue 트래커에서 help wanted 또는 good first issue 라벨이 부착된 작업을 우선적으로 검토합니다. 로드맵에 명시된 마일스톤과 일치하는 개선 사항을 제안할 경우 채택 확률이 높아집니다.

코딩 컨벤션 및 Pull Request 절차

Android 공식 스타일 가이드를 준수하며, 식별자 명명 규칙은 다음과 같습니다.

  • 클래스/인터페이스: PascalCase
  • 메서드/로컬 변수: camelCase
  • 정적 상수: UPPER_SNAKE_CASE

공개 API에는 반드시 KDoc 또는 Javadoc을 작성해야 합니다. 코드 품질 검증을 위해 커밋 전 ./gradlew lint check 명령을 실행하여 정적 분석 및 테스트 스위트가 통과하는지 확인합니다.

PR 제출 시 다음 템플릿 구조를 활용합니다.

## 변경 사항 요약
- 구현된 기능 또는 수정된 결함 기술

## 연관 이슈
- Fixes #123

## 기술적 접근
- 아키텍처 변경점, 알고리즘 개선 내용 서술

## 검증 방법
1. 에뮬레이터 API 34에서 샘플 앱 실행
2. 휠 드래그 시 콜백 정상 호출 확인
3. 단위 테스트 WheelAdapterTest 통과 검증

핵심 모듈 확장 가이드

1. 커스텀 속성 추가

새로운 XML 속성을 도입하려면 res/values/attrs.xml에 정의를 추가한 후, 커스텀 뷰 생성자에서 TypedArray를 통해 값을 추출합니다.

<declare-styleable name="CursorWheelLayout">
    <attr name="wheel_item_spacing" format="dimension" />
    <attr name="wheel_rotation_enabled" format="boolean" />
</declare-styleable>
public class CursorWheelLayout extends ViewGroup {
    private float itemSpacing;
    private boolean isRotationActive;

    public CursorWheelLayout(Context ctx, AttributeSet attrs) {
        super(ctx, attrs);
        TypedArray ta = ctx.obtainStyledAttributes(attrs, R.styleable.CursorWheelLayout);
        try {
            itemSpacing = ta.getDimension(R.styleable.CursorWheelLayout_wheel_item_spacing, 0f);
            isRotationActive = ta.getBoolean(R.styleable.CursorWheelLayout_wheel_rotation_enabled, true);
        } finally {
            ta.recycle();
        }
        initComponent();
    }
}

2. 어댑터 구현

데이터 바인딩을 위해 CycleWheelAdapter 인터페이스를 구현합니다. 기존 구현체를 참고하여 뷰 홀더 패턴을 적용할 수 있습니다.

public class CustomLabelAdapter implements CycleWheelAdapter {
    private final List<String> dataSource;
    private final LayoutInflater inflater;

    public CustomLabelAdapter(Context context, List<String> items) {
        this.dataSource = new ArrayList<>(items);
        this.inflater = LayoutInflater.from(context);
    }

    @Override
    public int getItemCount() {
        return dataSource.size();
    }

    @Override
    public View onCreateView(ViewGroup parent, int position) {
        return inflater.inflate(R.layout.item_wheel_label, parent, false);
    }

    @Override
    public void onBindView(View itemView, int position) {
        TextView label = itemView.findViewById(R.id.tv_wheel_item);
        label.setText(dataSource.get(position));
        label.setAlpha(position == getSelectedItem() ? 1.0f : 0.5f);
    }
}

3. 이벤트 콜백 확장

선택 상태 변경 및 클릭 이벤트를 처리하기 위해 리스너 인터페이스를 정의합니다. 기존 OnMenuSelectedListener 구조를 참고하여 콜백 시점을 onTouchEvent 또는 computeScroll 로직과 연동합니다.

기여자 FAQ

Q: 대규모 기능 개선은 어떻게 제출하나요?
A: 단일 PR의 범위를 최소화하세요. 핵심 로직, UI 리소스, 테스트 코드를 분리하여 순차적으로 머지 요청을 보내면 리뷰 부하가 줄어듭니다.

Q: CI 파이프라인에서 Lint 오류가 발생했습니다.
A: ./gradlew lintReport로 생성된 HTML 리포트를 확인하세요. 주로 import 순서, 자원 누수, 또는 하드코딩된 문자열에서 발생합니다.

Q: 비개발자도 기여할 수 있나요?
A: 네. API 레퍼런스 번역, 샘플 앱의 UX 개선 제안, 이슈 트래커의 버그 재현 단계 정리 등 문서화 및 QA 활동도 중요한 기여로 인정됩니다.

라이선스 고지

본 프로젝트는 Apache License 2.0을 따릅니다. 기여된 모든 커밋은 동일한 라이선스 하에 배포되는 것에 동의한 것으로 간주됩니다. 상세 조건은 저장소 최상단의 LICENSE 파일을 참조하십시오.

태그: Android CustomView OpenSourceContribution Gradle java

9월 13일 06:29에 게시됨