안드로이드 원리를 이해하거나 앱에 새로운 기능 (커스텀뷰) 등을 추가할 때 쓸모가 많다.
네이티브를 포함한 안드로이드 전체 소스 주요 디렉토리
- frameworks : 안드로이드 프레임워크, android로 시작하는 자바 패키지 포함
- libcore : 자바 코어 패키지 포함
- system : 안드로이드 init 프로세스
- packages : 안드로이드 기본 애플리케이션
- bionic : 안드로이드 표준 C 라이브러리
- dalvik : 달빅 가상 머신
- cts : 안드로이드 호환성 테스트 관련
- build : 빌드시 사용
* 안드로이드 버전별 기반되는 자바 버전
- 프로요 : 자바5
- 젤리빈 : 자바6
- 마시멜로 : 자바7
- 누가 : 자바8
프레임워크 소스 레벨 검증
ListView의 아이템 레이아웃에 CheckBox가 있으면 아이템 클릭이 정상적으로 동작하지 않는다.
이때 해결방법은?
1. ListView fw 소스 검증
2. setOnItemClickListener() 메서드는 ListView 상위 클래스인 AdapterView에 있음
- ListView > AbsListView > AdapterView<ListAdapter>
3. OnItemClickListener를 사용하는 위치는 performItemClick() 메서드
public boolean performItemClick(View view, int position, long id) {
final boolean result;
if (mOnItemClickListener != null) {
playSoundEffect(SoundEffectConstants.CLICK);
mOnItemClickListener.onItemClick(this, view, position, id);
result = true;
} else {
result = false;
}
if (view != null) {
view.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
}
return result;
}
http://androidxref.com/7.1.2_r36/xref/frameworks/base/core/java/android/widget/AdapterView.java#306
4. 호출 위치를 따라가보면, AbsListView의 onTouchUp()메서드에서 자식 View의 hasFocusable() 값이 true일 때 클릭이 동작하지 않도록 설정
private void onTouchUp(MotionEvent ev) {
switch (mTouchMode) {
...
case TOUCH_MODE_DONE_WAITING:
final int motionPosition = mMotionPosition;
final View child = getChildAt(motionPosition - mFirstPosition);
if (child != null) {
if (mTouchMode != TOUCH_MODE_DOWN) {
child.setPressed(false);
}
if (inList && !child.hasFocusable()) {
if (mPerformClick == null) {
mPerformClick = new PerformClick();
}
......
return;
} else if (!mDataChanged && mAdapter.isEnabled(motionPosition)) {
performClick.run();
}
}
// nothing!!
}
.......
break;
http://androidxref.com/7.1.2_r36/xref/frameworks/base/core/java/android/widget/AbsListView.java#3993
5. CheckBox의 focusable의 기본 값 확인
<style name="Widget.CompoundButton">
<item name="focusable">true</item>
<item name="clickable">true</item>
<item name="textAppearance">?attr/textAppearance</item>
<item name="textColor">?attr/textColorPrimaryDisableOnly</item>
<item name="gravity">center_vertical|start</item>
</style>
<style name="Widget.CompoundButton.CheckBox">
<item name="button">?attr/listChoiceIndicatorMultiple</item>
</style>
http://androidxref.com/7.1.2_r36/xref/frameworks/base/core/res/res/values/styles.xml#362
- Widget.CopoundButton.CheckBox 스타일을 이용하는데 암묵적 상속으로 Widget.CompoundButton 스타일을 상속한다
- 부모 스타일에서 focusable이 true로 되어있다. 따라서 레이아웃에서 ChexkBox의 android: focusable 속성을 false로 하면 스타일이 다시 오버라이드되어 ListView에서 정상적으로 아이템 클릭이 동작한다
6. 번외로 ListView에 ImageButton을 똑같이 넣고 focusable false로 속성을 오버라이드했는데 아이템 클릭 액션 문제가 해결되지 않는다. 왜일까?
public ImageButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setFocusable(true);
}
http://192.168.2.253:38080/source/xref/AndroidN_S5P6818_R2_FullSource/frameworks/base/core/java/android/widget/ImageButton.java?r=45ea3ee6#85
ImageButton는 생성자에서 setFocusable(true)를 실행해서 레이아웃의 속성을 다시 오버라이드 하기 때문이다.
따라서 ListAdapter의 getView() 메서드에서 ImageButton에 setFocusable(false)를 실행해서 또다시 오버라이드하면 아이템 클릭이 문제없이 작동한다.
'Android > 안드로이드 프로그래밍 Next Step' 카테고리의 다른 글
[Next Step] 4. Context 클래스 (0) | 2023.08.25 |
---|---|
[Next Step] 3. AsyncTask (0) | 2023.08.13 |
[Next Step] 3. 스레드 풀 사용 (0) | 2023.08.12 |
[Next Step] 3. HandlerThread 클래스 (0) | 2023.08.09 |
[Next Step] 1장 안드로이드 프래임워크 - 안드로이드 버전 (0) | 2023.06.17 |