listView의 'itemclick' 이벤트에서 질문입니다.

안녕하세요?

listView에서 ‘itemclick’ 이벤트를 사용하고 있는데,

IOS에서는 정상적으로 작동하는데 안드로이드에서는 좀 이상해서 질문 올립니다.


ListView를 터치하여 실행되는 ‘itemclick’ 이벤트 핸들러에서 e.source.apiName을 보면

  1. IOS에서는 'Ti.UI.ListView’로 정상적인데

  2. 안드로이드의 경우 e.source가 'Ti.UI.ListItem’이 넘어옵니다.
    ListItem에 추가한 이벤트 핸들러는 없는 상태이고,
    ‘itemclick’ 이벤트 핸들러 내에서 사용하려고 ListItem에 추가한 프로퍼티들은 하나도 세팅되어 있지 않은 상태로 넘어와서 이벤트 핸들러에서 처리하기가 쉽지 않네요.

이런 경우 어떻게 처리를 하시는지 조언 부탁드립니다.

좋은 하루 되세요~

정확히 무엇을 하시려는지 잘 이해를 못했는데요.
예를들면 아래처럼 저는 listview event를 사용하고 property 를 바꿉니다.
원하시는 답이 맞는지 모르겠네요.



//controller 

var data = [];
var items = [{'title': 'a'}, {'title':'b'}];

for (var i in items){

   data.push({
		template : 'template',
		properties : {
			height : Ti.UI.SIZE
		},
		title : {
			text : items[i].title,
                        left : 10, //<-- 타이틀의 left value를 바꾸고 싶다고 가정하면 아래의 이벤트에서 property를 바꿀수 있습니다.
		}
		});
	}

$.section.setItems(data);
}



//listView click event
function clickItem(e){
    //item 은 클릭한 리스트 아이템의 정보를 가지고 있게 됩니다.
    var item = $.section.getItemAt(e.itemIndex);

    //value 를 바꿔준후
    item.left = 50;

    //리스트를 업데이트 합니다.
    $.section.updateItemAt(e.itemIndex, item);

});

//xml
<ListView id="listView" onItemclick="clickItem" >
            <Templates>
                <ItemTemplate name="template">
                    <Label bindId="title" class="title" />
                </ItemTemplate>
            </Templates>
            <ListSection id="section" />
</ListView>

제 코드는 아래와 같이 구현되어 있습니다.

listView.addEventListener('itemclick', function(e) {
	// 안드로이드에서 e.source가 정상적으로 Ti.UI.ListView가 넘어오면
	// 아래 조건문은 필요가 없습니다.
	if(e.source.apiName != 'Ti.UI.ListView')
		return;

	// e.source가 listView이므로
	// 전달받은 e.sectionIndex와 e.itemIndex로
	// 터치된 listItem을 찾아서 사용합니다.
	var listItem = e.source.sections[e.sectionIndex].items[e.itemIndex];
	if(listItem == null
	|| listItem.myProperty == undefined
	|| listItem.myProperty == null)
		return;
	
	// 여기에서부터 실제 처리 코드가 들어가 있습니다.
	// ~~
});

위 코드는 IOS에서 정상적으로 동작하는 코드인데
안드로이드의 경우에는 itemclick 이벤트를 발생시키는 e.source가 ListView가 아닌 ListItem이더군요.

만약 지금처럼 ListItem이 itemclick 이벤트를 발생시키더라도 listItem.myProperty에 제가 저장해놓은 값이 정상적으로 들어가 있으면 무난하게 처리가 가능한데 undefined가 들어있어서 정상적으로 동작하지 않습니다.

제가 궁금한 사항을 다시 정리해보면

  1. ListView에 ‘itemclick’ 이벤트를 추가했는데,
    안드로이드에서는 ListItem이 ‘itemclick’ 이벤트를 발생시키는 것이 이상하다는 점.
    (매뉴얼에는 ListItem은 아무 이벤트가 지원되지 않습니다.)

  2. 지금처럼 안드로이드에서 ListItem이 이벤트를 발생시키는 경우
    e.source로 전달되는 ListItem 오브젝트에 제가 설정한 myProperty 값이 undefined로 넘어오는 점입니다.

안드로이드에서 계속 오동작하면 e.source 대신 listView를 직접 사용해야 될 것 같네요. ^^

가끔 메뉴얼과 다른 부분이 있더라구요. ^^

만약 list item으로 이벤트를 만들 경우 저는 XML에 이벤트를 주어 사용합니다.

//js

//list item click event
function clickItem(e){
    //item 은 클릭한 리스트 아이템의 정보를 가지고 있게 됩니다.
    var item = $.section.getItemAt(e.itemIndex);

    //value 를 바꿔준후
    item.left = 50;

    //리스트를 업데이트 합니다.
    $.section.updateItemAt(e.itemIndex, item);

});

//xml
<ListView id="listView">
            <Templates>
                <ItemTemplate name="template">
                    <Label bindId="title" class="title" onClick="clickItem" />
                </ItemTemplate>
            </Templates>
            <ListSection id="section" />
</ListView>

도움 말씀 감사드립니다.
저는 XML은 사용하고 있지 않아서 다른 방법을 찾아봐야겠네요.

오늘도 좋은 하루 되세요~

itemclick에서 확실하게 보장되는 제공되는 properties는
section, sectionIndex, itemIndex, itemId 등등이죠…
e.source는 ios와 android가 다릅니다.
아시다시피 두 O/S가 view를 다루는 방식 이벤트 버블링 등등 많은 것이 다르죠.
http://docs.appcelerator.com/platform/latest/#!/api/Titanium.UI.ListView-event-itemclick

코드를 보니 listItem을 받으시면 되는거 같은데 그러면, 확실한 properties만을 가지고 코딩하시면 됩니다.

listView.addEventListener('itemclick', function(e) {
    var item = e.section.getItemAt(e.itemIndex);
    var itemId = e.itemId;

    ....
});

이렇게 말이죠.

2개의 좋아요

도움 말씀 감사드립니다.

제가 뭘 잘못 코딩했는지 모르겠지만,
저는 올려주신 코드를 실행해봐도 listItem을 정상적으로 가져오지 못하네요.

itemclick() called. e.section: [object ListSection], sectionIndex: 0, itemIndex: 59
listItem.apiName: undefined, listItem.myProperty: undefined

이것저것 디버깅해보면서 원인을 찾아봐야겠습니다.
그럼 좋은 밤 되세요~

저도 itemId 사용을 추천합니다.
item을 만들 때 데이터의 고유값을 나타내는 key(예. db의 primary key)를 itemId로 넣어놓고 itemClick 이벤트로 넘어온 itemId로 해당하는 data를 찾아쓰는 형태로 말이죠.

(단, button을 list에 넣을 경우에는 @heedoo 님의 방식을 씁니다. 그냥 label등을 button 처럼 쓸때는 itemId로)

아래는 두 파일은 예전 강의할 때 만들었던 관련 파일 입니다.

1개의 좋아요

도움 감사드립니다.

테스트해보니 제가 저장한 커스텀 프로퍼티는 유실되는데, 알려주신 것과 같이 itemId에 넣은 값은 이벤트 핸들러로 정상적으로 넘어오네요.
그래서 아래와 같이 제가 필요한 데이터들을 오브젝트로 만들어서 itemId에 저장하여 이벤트 핸들러에서 사용하도록 했습니다.

잘 되네요.

listItem = {
	myTemplate:		{},
	
	properties: {
		itemId:		{
			'myProperty1':	myProperty1,
			'myProperty2':	myProperty2,
			'myProperty3':	myProperty3,
		},
	}
};


listView.addEventListener('itemclick', function(e) {
	var myProperty1 = e.itemId.myProperty1;
	var myProperty2 = e.itemId.myProperty2;
	var myProperty3 = e.itemId.myProperty3;

	// 여기에서부터 실제 처리 코드가 들어가 있습니다.
	// ~~
});

제가 필요한 데이터들을 itemId를 통해서 모두 받을 수 있으므로 ListItem은 찾지 않아도 되었습니다.

그럼 좋은 밤 되세요~

1개의 좋아요