1

我正在使用鈦合金版本3.2。我有一個列表視圖中的帖子的集合。我的數據是這樣的:鈦合金ListView嵌套模型數組標籤

[ 
    { username: 'dude', imageUrl: 'url', tags: ['tag1','tag2','tag3']  }, 
    { username: 'wheres', imageUrl: 'url', tags: ['tag1']      }, 
    { username: 'my',  imageUrl: 'url', tags: ['tag1','tag2','tag3','tag4'] }, 
    { username: 'car', imageUrl: 'url', tags: ['tag1','tag2']    } 
    ] 

這裏是xml。這僅適用於用戶名和圖像。我無法弄清楚如何將標籤添加到每個帖子。

<ListView id="streamListview"> 

     <Templates> 
      <ItemTemplate name="template" id="template"> 
       <View class="item-container">    
        <ImageView bindId="pic" class="pic"/> 
        <Label bindId="username" class="username"/> 
       </View> 
      </ItemTemplate> 
     </Templates> 

     <ListSection id="section"> 
      <ListItem template="template" class="list-item"/> 
     </ListSection>     

    </ListView> 

我的控制器代碼(無標籤)

var posts = []; 
    for (var i=0; i<data.length; i++){ 
     var post = { 
      template : "template", 
      pic  : { image : data[i].get("imageUrl") }, 
      username : { text : data[i].get("username") } 
     }; 
     posts.push(post);    
    } 
    $.section.setItems(posts); 

我如何可以添加標籤(可點擊的)的帖子,如果我應該聲明在手前的模板每個視圖?根據數組的長度,我的示例中的每個標籤數組都需要不同數量的視圖。每個標籤最好是它自己的UI.Label元素。我相信這可以使用TableView完成,但我更喜歡使用ListView出於性能原因。

回答

0

如果您在控制器中動態創建模板,則應該可以使用ListView。您還需要遍歷每個「標記」對象,併爲每個標記項目生成一個Ti.UI.Label「類型」。但是,我不確定這個方法比使用TableView對象更有效率,因爲實際上每個創建的ListItem都將包含一個不同的模板。

要生成一個動態模板,它將類似於以下內容:請記住,您需要遍歷「標籤」並生成x Ti.UI.Label類型,其中x是「標籤」的長度。此外,點擊事件應該使用Titanium SDK 3.2.1。

var plainTemplate = { 
childTemplates: [ 
    { 
     type: 'Ti.UI.Label', 
     bindId: 'username' 
    }, 
    { 
     type: 'Ti.UI.ImageView', 
     bindId: 'pic'  

    },      
    { 
     type: 'Ti.UI.Label', 
     bindId: 'tags', 
     events: { click : handleTagClickEvent } // Binds a callback to click event 
    } 
]}; 


function handleTagClickEvent(e) { 
    Ti.API.info('You clicked a tag label: ' + e.type); 
} 


var listView = Ti.UI.createListView({ 
    templates: { 'plain': plainTemplate }, 
    defaultItemTemplate: 'plain'   
}); 

希望這可以幫助你以某種方式!

+0

謝謝Nando,但我不認爲這會工作,因爲你正在爲標籤聲明一個Ti.UI.Label。標籤是一串字符串,每個字符串都需要它自己的Ti.UI.Label。由於你必須在實例化ListView之前聲明子模板,我不相信你可以靈活地添加可變數量的Ti.UI.Labels,這取決於array.length – TheBigC

5

我想我知道你需要什麼,在這種情況下,因爲要動態生成每個項目(例如,一個場景,你打開你的窗口,你的ListView空第一和進行API調用來獲取遠程的數據,並填寫帶有所述數據的ListView),您將需要使用在其自己的控制器中聲明的ItemTemplates。

你剛纔創建像正常的,在視圖中的XML一個新的控制器,你把你的ItemTemplate:

<Alloy> 
    <ItemTemplate name="template" id="template"> 
     <View class="item-container">    
      <ImageView bindId="pic" class="pic"/> 
      <Label bindId="username" class="username"/> 
     </View> 
    </ItemTemplate> 
</Alloy> 

在您的TSS你把所有的在模板中提到的每個元素的樣式,因爲你沒」牛逼提供TSS的例子,我不能告訴你有什麼樣式屬性,但在TSS您需要定義模板的樣式,例如可以這樣說:

"#template": // this is the id of your template in your xml 
{ 
    width : Ti.UI.FILL, 
    height : '44dp', 
    backgroundColor : '#FFFFFF' 
} 

,以填補listItems中您的ListView動態地,你需要在你的系統中做這樣的事情從您的API回調:

function displayListItems(items) 
{ 
    var itemCollection = []; 
    for(var i=0; i < items.length; i++) 
    { 
     var tmp = { 
      pic : { 
       image : items[i].image 
      }, 
      username : { 
       text : items[i].text 
      }, 
      template : 'template' // here goes the name of the template in your xml, **do not confuse name with id, both are different and using one doesn't replace the other** 
     }; 
     itemCollection.push(tmp); 
    } 
    $.ListView.sections[0].items = itemCollection; 
} 

而且瞧,你得到你的ListView動態填充。現在你可以做一些額外的步驟。

在模板控制器,你可以將其留空,因爲ListView控件可以管理itemClick在事件,但如果你想用不同的操作發生時,在ListItem某個元素來觸發,你需要指定功能在您的控制器中爲每個元素調用。

例如可以讓你在你的模板,這樣通過一個名爲dataInfo您的ImageView和你的標籤屬性:

function displayListItems(items) 
{ 
    var itemCollection = []; 
    for(var i=0; i < items.length; i++) 
    { 
     var tmp = { 
      pic : { 
       image : items[i].image 
       dataInfo : items[i].fooA //lets pass to the ImageView the object fooA 
      }, 
      username : { 
       text : items[i].text, 
       dataInfo : items[i].fooB //lets pass to the Label the object fooB 
      }, 
      template : 'template' // here goes the name of the template in your xml, **do not confuse name with id, both are different and using one doesn't replace the other** 
     }; 
     itemCollection.push(tmp); 
    } 
    $.ListView.sections[0].items = itemCollection; 
} 

並且希望的ImageView和標籤調用不同的功能,你會需要改變你的XML是這樣的:

<Alloy> 
    <ItemTemplate name="template" id="template"> 
     <View class="item-container">    
      <ImageView bindId="pic" class="pic" onClick="imageFunction"/> <!-- added onClick event --> 
      <Label bindId="username" class="username" onClick="labelFunction"/> <!-- added onClick event --> 
     </View> 
    </ItemTemplate> 
</Alloy> 

在你的控制器,你將宣佈各功能:

function imageFunction(e) 
{ 
    var dataInfo; 
    if(Ti.Platform.osname === 'android') 
    { 
     var item = e.section.items[e.itemIndex]; 
     var bindObject = item[e.bindId]; 
     dataInfo = bindObject.fooA; 
    } 
    else 
    { 
     dataInfo = e.source.fooA; 
    } 

} 

function labelFunction(e) 
{ 
    var dataInfo; 
    if(Ti.Platform.osname === 'android') 
    { 
     var item = e.section.items[e.itemIndex]; 
     var bindObject = item[e.bindId]; 
     dataInfo = bindObject.fooB; 
    } 
    else 
    { 
     dataInfo = e.source.fooB; 
    } 
} 

現在你可能會問,爲什麼要檢查操作系統名稱,這是因爲即使你使用相同的功能,Android和iOS也會收到不同的對象。無論在什麼屬性,你傳遞給事件的來源可與e.source.propertyName直接訪問,而在Android中,你需要訪問到該項目e.section使用e.itemIndex中,在那之後你的iOS使用與其關聯的e.bindId檢索項目內部的視圖。

一對listItems中的更新列表項中的意見,要做到這一點,你需要更新你想直觀地更改併爲其分配一個不同的模板整個項目最大的限制,但它這樣做,你的速度將無法注意到任何滯後,認真ListView的表現是別的東西,不像ScrollView,我們不談論可怕和有問題的TableView。

從Titanium SDK 3.2.0.GA開始有一個警告,在ItemTemplates中存在一個錯誤,它會導致模板中的子視圖內的視圖在Android中更改其zIndex而無法控制它,但有兩個已知的實例這個: 如果你使用一個不要在一個子視圖中設置佈局:這可能會導致一個視圖應該顯示在另一個視圖之下來放置它。

如果在子視圖中使用垂直佈局:這可能會導致每個視圖的位置被擾亂,這是因爲zIndex會改變垂直佈局中的顯示順序。

這個錯誤是隨機觸發的,Appcelerator團隊沒有投入太多工作,查看這裏的JIRA票證TIMOB-16704

這可以,如果你使用模板固定安置的意見,並確保沒有視圖來在另一個之上,還記得沒有垂直佈局,未與水平測試這一點,但我個人儘量避免橫向避免佈局由於在scrollviews,正常的意見時,都與此相關的其他錯誤等

編輯

你可能想用這個做的另一件事是分配不同的外觀給你呈現的項目,你必須選擇:

  • 在聲明ListItem時應用樣式。
  • 根據一系列條件將不同的佈局應用於每個ListItem。

對於需要忽略或覆蓋在模板中某些屬性的聲明中的第一個選項:

例如,讓我們使用不同的背景顏色,其中財產fooA存在,另一種顏色,如果它不:

function displayListItems(items) 
{ 
    var itemCollection = []; 
    for(var i=0; i < items.length; i++) 
    { 
     var properties = {}; 
     if(typeof items[i].fooA !== 'undefined') 
     { 
      properties = { 
       backgroundColor : 'red' 
      }; 
     } 
     else 
     { 
      properties = { 
       backgroundColor : 'blue' 
      }; 
     } 
     var tmp = { 
      properties : properties, // properties for the template 
      pic : { 
       image : items[i].image 
       dataInfo : items[i].fooA //lets pass to the ImageView the object fooA 
      }, 
      username : { 
       text : items[i].text, 
       dataInfo : items[i].fooB //lets pass to the Label the object fooB 
      }, 
      template : 'template' // here goes the name of the template in your xml, **do not confuse name with id, both are different and using one doesn't replace the other** 
     }; 
     itemCollection.push(tmp); 
    } 
    $.ListView.sections[0].items = itemCollection; 
} 

您可以根據需要更改寬度,高度,backgroundColor,佈局等。

現在,如果您希望每個項目具有不同的外觀(意味着顯示不同內容的不同視圖)以及可能不同的行爲,則需要使用不同的模板。

這可能聽起來有點麻煩,但事實並非如此,一旦習慣了它們,不需要很長時間模板就可以快速創建,而另一個可能是如果你想要11種不同的外觀,這可能意味着你需要11模板,但這是一個極端的例子,如果你正在處理那麼多的模板,你可能想重新考慮你的UI。

雖然限制,項目模板提供了一個廣泛的選項供您使用,一點想象力是唯一必要的組成部分,以帶出所有的可能性。

EDIT 2

我終於明白了什麼是你的問題,如果你需要創建一個模板,其含量的變化,根據斧頭變量,那麼你應該嘗試聲明你的ListView控制器上的模板,但這應該在打開窗口之前完成了,你會被顯示的ListView自模板屬性只能在創建時設置,你應該喜歡添加一些東西:

function createTemplate(items) 
{ 
    var template = {}; 
    for(var i=0; i < items.length; i++) 
    { 

     template.childTemplates = []; 
     for(var j=0; items[i].tags.length; j++) 
     { 
      var childTemplate = { 
       type: 'Ti.UI.Label', 
       bindId: 'tag' + j, 
       properties : { 
        width : Ti.UI.SIZE, // Here you define how your style 
        height : Ti.UI.SIZE, 
        font : { 
         fontSize : '18dp' 
        }, 
        text : items[i].tags[j].text // you can pass the text here or if you want to on the later for 
       } 
      }; 
      template.childTemplates.push(childTemplate); 
     } 
    } 
    // After this you should end up with a template with as many childTemplates as tags each item have, so send the template to the controller with your ListView 
    Alloy.createController('ListViewWindow', {customTemplate: template}); 
} 

而在你的ListView控制器,你retriev E中的模板:

var args = arguments[0] || {}; 
var template = args.customTemplate; 

$.ListView.templates = {'customTemplate' : template}; // before any window open call, do this 

這應該模板添加到您的ListView,你還可以創建在您的控制器ListView控件,而不是在你的XML合金宣告它的,使用適合您的需求更多的人。

+0

我很欣賞詳細的答案,但我不'你以爲你回答了問題的主要部分。這個問題有一系列的帖子,每個帖子都有一個標籤數組。標籤數組的長度是動態的。擁有一個設置的模板不會考慮不同數量的標籤。 – TheBigC

+0

檢查我編輯的答案,你的模板高度可以設置爲Ti.UI.SIZE,無論你扔到他們的內容大小,它會自行調整。請記住,不是垂直佈局,並避免重疊視圖。 –

+0

我想我只是理解你的問題,你談論有一個ListItem可能包含一個或多個標籤,對嗎?檢查我編輯的答案 –