setHasOptionsMenu 가 onActivityCreated method 에서 호출되었는지 확인한다. 

ListView 의 addFooterView 를 호출한후에 setAdapter 를 호출해야한다.


XML을 파싱할 일이 생겨서,  이래저래 만져보다가 작업한 내용을 정리 합니다 :)

1. XML Parsing

Android 에서 제공하는 XmlResourceParser 를 사용하기로 했습니다.

XMLResourceParser는 다른 Java XML Parser들에 비해 성능이 좋은게 특징입니다.
이유인 즉은, 다른 Android XML 파일들 처럼, pre compiled 해서 birnary에 들어 가서 처리 하기 때문입니다.
아래는 간단하게 XML 을 읽어 들이는 코드 입니다. 
public Problem parseXML(XmlResourceParser xmlParser)
			throws Exception {

		Problem problem = new Problem();
		String name = null;

		while (xmlParser.getEventType() != XmlPullParser.END_DOCUMENT) {

			if (xmlParser.getEventType() == XmlPullParser.START_TAG) {
				name = xmlParser.getName();
			} else if (xmlParser.getEventType() == XmlPullParser.TEXT) {
				if (name == null) {
					Log.d("ProblemDAO-parseXML", "name is null ? error ??");

				}
			} else if (xmlParser.getEventType() == XmlPullParser.END_TAG) {
				name = null;
			}
			xmlParser.next();
		}

		return problem;
	}

2. XML to Pojo



a. 첫 번째 시도 - if 지옥

자 읽어 들인 XML을 Java Plaiin Object 로 매핑할 차리 인데요.

제일 처음 작업한게 아래와 같은 코드 입니다.
if(name.equalsIgnoreCase("title") == true) {
}
위와 같은 코드의 문제점은 if/elseif/elseif 지옥이 나타난다는것이죠. :(
그리고,  xml 형식등의 변경이 있을때, pojo/xml 이외에 추가로 관리할 곳이 늘어 난다는 점입니다.

b. 두 번째 시도 - Reflection

그래서 생각해낸것이 Java의 Reflection 입니다.

xml element 이름을 pojo 의 setter와 연결시키도록 아래와 같이 코드를 작성하였습니다..

               char[] stringArray = name.toCharArray();
		stringArray[0] = Character.toUpperCase(stringArray[0]);
		String methodName = "set"+ new String(stringArray);	
                try {
			Method m = Problem.class.getMethod(methodName, String.class);
			m.invoke(problem, text);
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
				Method m = Problem.class.getMethod(methodName,Integer.class);
				m.invoke(problem,Integer.valueOf(text));
		}

조금 신경 쓴부분이 바로 Setter의 자료형 부분입니다.
m.invoke 가 없는 메소드 인 경우에, NoSouchMethodException을 발생시키기 때문에 이를 캐치하여,
다른 형으로 시도 해보도록 코드를 작성하였습니다.

3. 더 해볼것

추후에, JacksonMapper 등에서 어떻게 json 을 pojo화 시키는지 좀 스터디해보고 좀 더  좋은 방법이 있나 생각해봐야겠습니다 :)
http://developers.facebook.com/docs/guides/mobile/#android

FaceBook사에서 Guide를 했는데도 불구하고,

07-29 10:11:50.140: DEBUG/Facebook-authorize(11292): Login failed: invalid_key


 위와 같은 error가 발생하며, Login Page로 가지 않는 문제가 있었다. 
 
이래저래 서치를 해본 결과
Android Hash Key를 생성하는데서 문제가 있었다. 
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore 
| openssl sha1 -binary
| openssl base64

http://developer.android.com/guide/publishing/app-signing.html#debugmode

Android 개발자 사이트를 보면, debugmode에서의 app-sigining에 대한 내용이 있다.

Eclipse에서 applicatoin을 debug로 signing할때, "android"란 password를 통해서 생성sign하기때문에, keytool에서도 동일 password를 써줘야 한다.




후아아, Android 개발하는데 이 그림정도는 환벽히 머리속에 넣고 있어야 하지,

onPause와 onStop의 의 혼동으로 잠깐 삽질.

GOAL 
  • ListActivity 에서 ContextMenu를 띄운다.
  • ContextMenuItem을 선택하여 특정 Position의 ListViewItem에 대한 작업을 수행한다.
Try 1.

ListView를 ContextMenu에 등록하여, LongClick Event발생시 ContextMenu를 띄우게 한다.registerForContextMenu(getListView());  

Result : Failed

이방법은 LongClick을 받은 Item Position을 알아낼 방법이 없다.
( 아시는 분 손좀? ^^ )

Try 2.


ListView setOnItemLongClickEventListener() 에서, 
openContextMenu(view) 를 통해서 ContextMenu를 Open 하고, 그 View를 이용해 Position을 가져 온다. 

Result : Failed

openContextMenu의 파라미터가 되기 위해서는 registerContextMenu를 통해서 registering을 해야 하는데,
Adapter에서 View를 만들때 register를 한다고 해도, unregister를 해야 하는 시점이 불분명하고,
비직관적이다. 

Try 3.
 

registerForContextMenu(getListViewI()) 를 통해 ListView의 ContextMenu를 Open
getListView().setOnItemLongClickListener를 등록하여, Last Long Clicked Position을 저장
ContextMenuItemSelected가 호출 될때 저장된 Position을 사용하여 Task 수행

Result : Success


그래도 뭔가 찜찜하다. 뭔가 좋은 방법이 있을것 같은데.. 아시는 분 없나요? ㅎㅎ



 
  1. isul 2011.04.06 22:55

    저도 Try3과 같은 방법을 사용합니다.
    onItemLongClick 이벤트 핸들러에서 첫 번째 파라미터인 AdapterView(ListView)의 Tag(adapterView.setTag())에 세번째 파라미터인 position을 저장하거나 그 position에 해당되는 값을 구하여 저장합니다.
    그리고, onContextItemSelected 이벤트 핸들러에서 그 ListView의 Tag를 구해서 처리합니다.
    뭐.. 변수 하나 선언하지 않고 사용한다는 것 뿐입니다.

  2. 2222 2011.04.07 13:31

    onContextItemSelected에서 (AdapterContextMenuInfo) item.getMenuInfo();와 같이 아답터 정보를 가져오면 될듯합니다.

  3. Funny 2011.05.13 05:35

    저도 context menu 의 header 에 리스트의 내용을 띄우려고 같은 고민을 했습니다.
    menuInfo 에 답이 있더군요.
    @Override
    public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    AdapterContextMenuInfo info = (AdapterContextMenuInfo)menuInfo;

    // 이제 info.position 로 현재 contextmenu 를 띄운 listview 의 list position 을 알 수 있습니다.
    .....
    }

    그럼 ^^

  4. Funny 2011.05.13 05:37

    onContextItemSelected(MenuItem item) 에서 하고 싶을 경우에는

    @Override
    public boolean onContextItemSelected(MenuItem item) {
    AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
    // info.position 을 이용합니다.
    ...
    }

    • taehoon.Koo 2011.06.21 12:04 신고

      오 감사합니다 ~ 나중에 한번 해봐야겠군요

      요새 Android 개발은 .... ....
      쩜쩜쩜이라 ㅎ

    • taehoon.Koo 2011.06.21 12:04 신고

      오 감사합니다 ~ 나중에 한번 해봐야겠군요

      요새 Android 개발은 .... ....
      쩜쩜쩜이라 ㅎ

CursorAdapter adapter = (CursorAdapter) getListAdapter();

adapter.getCursor().requery();

adapter.notifyDataSetChanged();


CursorAdapter를 가져와서
거기에서 다시 Cursor를 가지고 오고 requery();

그리고 adapter에 notifyDataSetChanged() 해주면 된다.  

난 또 순진했을 뿐이고 :(

 ClickListener 같은 경우 setOnClickListener를 사용하기 때문에, 당연히 난 setTextBlahBlah가 있을줄 알았는데, 
그런게 없어서,

setKeyListener를 사용해봤는데, SoftKey를 잡지 못하고, Hardware Key만 잡았다.

아 이런게 없을 수 있나 싶었는데.. :(

addTextChangedListener가 존재 했다.. 

public void addTextChangedListener (TextWatcher watcher)


mDialogEditText.addTextChangedListener(new TextWatcher() {

@Override

public void onTextChanged(CharSequence s, int start, int before, int count) {

Log.d(TAG,"Count = " + count);

}

@Override

public void beforeTextChanged(CharSequence s, int start, int count,

int after) {

}

@Override

public void afterTextChanged(Editable s) {

}

});

 

위와 같이, before, changed, after 등의 event를 detecting 할 수 있다. 


 

ListView Background  세팅하기.

이게 Blog에 포스팅 할 꺼리가 될까? android:background 세팅 해주면 끝이 아닌가?

나도 그러길 기대했지만, 이것 때문에 꽤나 고생했습니다 :(


위의 스크린샷은 ListView에 android:background="#777777" 로 회색으로 줬습니다.
잘 나옵니다. 그런데, Drag를 하면 아래와 같이 검은 색으로 바뀌어 버립니다. 



이것 참 난감한일이 아닐수가 없습니다. 실제로 Scrolling이 되지 않는 뷰임에도 불구 하고, 
Dragging을 하면 검은색으로 바뀌어 버립니다. 다시 터치를 해주면 원래대로 들어옵니다.

그 이유는 바로 여기 있습니다.


android:cacheColorHint가 black으로 되어 있기 때문인데요, 

Scrolling (혹은 Drag)가 일어 나면, 성능 최적화를 위해 저 ColorHint를 사용하는데, 
Drag시에 검은색으로 노출 되는것이 cacheColorHint값과 동일 한것이지요. 

해당 값을 background와 동일하게 세팅해주면, Drag에 색이 변하는 문제가 해결됩니다.

후.. 안드로이드 아직 수련이 많이 부족한가 봅니다 ㅎㅎ

  1. ghun 2011.07.20 13:56

    굿~!! Dialog 형태의 Activity를 구성하다가 문제가 생겼는데 덕분에 깔끔해 졌습니다 ^^ 감사


오늘 제가 해볼 것은 Preference Category를 Customizing 해보는것입니다. 
우선 결과 부터 보여드리면, 


이런식으로 Category Title을 변경해보는것이죠.

위와 같은 Layout의 Preference XML은 아래와 같습니다. 

<?xml version="1.0" encoding="utf-8"?>


<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"

        android:title="@string/app_name">

    <PreferenceCategory

    android:title="@string/category_name">

    <Preference android:key="app_name"

        android:persistent="false"

        android:title="@string/app_name"

    />

    </PreferenceCategory>  

</PreferenceScreen>


PreferenceScreen에 PreferenceCategory를 추가하고, 
PreferenceCategory에 Preference Item이 하나 있는 형태 이지요, 

여기서, PreferenceCategory의 Layout을 Customizing하는게 목적입니다.

Preference Item의 Layout을 변경할때 사용하는것은,  android:layout 속성을 정의 하는것입니다. 


android:layout="@layout/my_preference_category" 뭐 이런식으로 추가 해주는것지요 

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

  xmlns:android="http://schemas.android.com/apk/res/android"

  android:orientation="horizontal"

  android:layout_width="fill_parent"

  android:layout_height="25dip"

  android:gravity="center_vertical"

  android:paddingLeft="5dip"

  android:background="#323331">

  

  <ImageView 

  android:layout_width="wrap_content"

  android:layout_height="fill_parent"

  android:src="@android:drawable/ic_menu_info_details"/>

  <TextView

  android:textStyle="bold"

  android:id="@android:id/title"

  android:layout_width="wrap_content"

  android:layout_height="fill_parent" 

  android:text="test"

  android:gravity="center"

  android:textColor="#FF0000"

  />

  

</LinearLayout>


여기서 부터, 안드로이드 개발의 짜증나는 점이 나타나는데, 
PreferenceCategory에서 지정한 title 값과, 내가 만든 Layout의 TextView가 연결되어야 하는데, 
id값을 어떻게 지정해주어야 한다는 정보가, developer.android.com을 아무리 뒤져 봐도 없습니다.

결국 Android Source코드를 보고 나서야 
@android:id/title로 줘야 한다는걸 알게 되었고,  이렇게 해주고 나니 정상적으로  동작합니다.

android:layout은 PreferenceCategory의 XML Attribute가 아니라, Preference 아이템 클래스들의 최상위 클래스인 Preference Class의 
XML Attribute입니다. 

즉, PreferenceCategory뿐 아니라, CheckBoxPreference 등등 모든 Preference들을 이와 같은 원리로 Customizing할 수 있습니다. 

  1. 감사 2013.02.03 20:46

    포스팅 감사합니다 덕분에 도움 많이 되었습니다 ^^ 좋은 하루 되세요~!

+ Recent posts