2012-03-13 53 views
5

我有一個包含自定義行的ListView。這個自定義行具有以下UI元素更改列表項選擇的視圖屬性

  1. ImageView的imageView1,imageView2
  2. TextView的textview1,textView2,textView3

要求是每當列表選擇行有將以下更改

imageView1背景,顏色發生變化

imageView1顏色發生變化

textview1顏色,大小和字體是改變

textview2顏色,大小改變

textview3顏色,大小改變

什麼將是這個設計的最佳方式?

AFAIK我們無法在選擇器中應用樣式。有沒有更好的方法來處理這個問題,而不是在java代碼中處理?

我們可以在這將對下列回調方法列表視圖設置setOnItemSelectedListener:

我)onItemSelected

II)onNothingSelected

但是沒有回調方法,它提供的細節項目失去了重點。這是一個更好的地方做出改變?

在此先感謝。

+0

」AFAIK我們不能在選擇器中應用樣式,有沒有更好的方法來處理這個問題而不是處理java代碼?如果你不能在選擇器中做到這一點,除Java之外還可以做什麼?也許你可以重寫默認選擇器引用的樣式屬性? – nmr 2012-03-15 03:21:56

+0

樣式可用於更改背景顏色/ drawable.It無助於更改字體大小。我也需要爲每個子視圖指定選擇器嗎?在java代碼中,在getView()中。 – 2012-03-16 03:22:50

回答

2

我想你想在這裏做的是創建一個Compound Control什麼。你可以找到在樣品// ApiDemos子目錄的SDK目錄中的一個例子(您可能需要下載Android source,如果你不具備這些目錄)。

我會做的是創建一個從您正在使用您的自定義行什麼樣的佈局繼承的類。假設這個例子是LinearLayout。在您的子類構造函數中,您可以從資源中擴充佈局,查找子視圖並將它們附加到實例變量,然後將LinearLayout返回給調用者。

在本小類中,您可以覆蓋setSelected和操縱在你想要的任何方式的子視圖。

下面是我根據您的文章我描述一個例子:

public class MyCustomLayout extends LinearLayout { 
    public ImageView imageView1; // These are public since you likely want 
    public ImageView imageView2; // to set them in your Adapter. 
    public TextView textView1; 
    public TextView textView2; 
    public TextView textView3; 

    public MyCustomLayout(Context ctxt) { 
     super(ctxt); 

     // The call below attaches the items in the mycustomlayout.xml file to this 
     // instance, which serves as the root element in the layout. 
     LayoutInflater.from(ctxt).inflate(R.layout.mycustomlayout, this, true); 

     imageView1 = (ImageView)findViewById(R.id.imageview1); 
     imageView2 = (ImageView)findViewById(R.id.imageview2); 
     textView1 = (TextView)findViewById(R.id.textview1); 
     textView2 = (TextView)findViewById(R.id.textview2); 
     textView3 = (TextView)findViewById(R.id.textview3); 
    } 

    @Override 
    public void setSelected(boolean selected) { 
     super.setChecked(selected); 
     if (selected) { 
      imageView1.setBackgroundColor(0xFFFF0000); // whatever color you want 
      // Do all the rest of the setting of your subviews here for 
      // the case when the row is selected. 
     } else { 
      imageView1.setBackgroundColor(0xFF000000); // whatever color you want 
      // Do all the rest of the setting of your subviews here for 
      // the case when the row is not selected 
     } 
    } 
} 

現在,在mycustomlayout。xml文件,你要使用的<merge>標籤,這樣你就不會產生不需要的佈局:

<merge xmlns:android="http://schemas.android.com/apk/res/android"> 
    <ImageView 
     android:id="@+id/imageview1" /> 
    <ImageView 
     android:id="@+id/imageview2" /> 
    <TextView 
     android:id="@+id/textview1" /> 
    <TextView 
     android:id="@+id/textview2" /> 
    <TextView 
     android:id="@+id/textview3" /> 
</merge> 

我省略掉的子視圖的所有配置上面,很明顯,但你應該得到有關如何的想法設置XML文件。如果你不想用XML和LayoutInflater混淆,你也可以在代碼中做到這一點。您可以在Android開發博客上查看this helpful blog post,其中討論了類似的情況。

然後,在你的適配器的getView你可以創建(或再循環)的MyCustomLayout的情況下,設置它們,並讓框架採取跟蹤,其中選擇行和沒被選的照顧。 「

0

我有一個粗糙的方式...但它是非常重的過程... 一旦一個項目被選中刷新你的列表視圖...只爲選定的項目,它應該顯示特定的字體等...和商店在填充適配器中的視圖時,某些變量中所選項目的ID與其匹配...

0

在活動級別取一個靜態整數變量selectedPos

在onItemSelected設置變量selectedPos = position和onNothingSelected其設置爲-1並調用notifyDataSetChanged()爲您的適配器對象。

現在在ListView的Adapter類中。作爲

if(position == selectedPos) 
{ 
    // set color and background to view 
} 

在getView 寫條件,不要忘了寫在適配器類這兩種方法,

@Override 
public int getItemViewType(int position) { 
return position; 
} 

@Override 
public int getViewTypeCount() { 
return _ArrayListObject.size(); 
} 
+0

謝謝soni。但是,這意味着要重新爲所選的每個項目重新繪製listView。這可以以任何方式避免嗎?當「底層數據已經被改變」時,notifyDataSetChanged()應該被調用,這在這裏不是這種情況。有沒有框架來支持這種情況下的支持? – 2012-03-17 20:39:25

+0

@khotmanish nope .. :) :(..我只是有這個想法在我的腦海裏,我認爲這將適用於你.. – MKJParekh 2012-03-19 05:26:04

0

Khotmanish,

我不知道你的意思通過最有效辦法。有很多方法非常快速,但它往往取決於你事先知道的事情和你不知道的事情。還必須瞭解的是,儘管流行的神話,動態視圖屬性被嚴重誤解,但高效。谷歌的人員在UI開發方面做得非常出色。

如果你知道它的時間提前,你可以簡單地創建一個StateListDrawable爲每個視圖,並將其應用到每個你通過你的適配器中運行。

要構建StateListDrawable,創建一個:

StateListDrawable _drawStates; 

然後,對於每個狀態,添加您需要的繪製:

_drawStates.add(new int[] {android.R.attr.state_pressed}, _newImage); 

這是你在getView以下行一樣簡單( )方法:

v.setBackgroundDrawable(_drawStates); 

或者,您可以動態更改背景根據選擇。這可以在OnListItemClick()中完成。你看,OnListItemClick()會給你點擊的確切視圖。一旦你有了這個,你會發現它的id孩子,並改變其性質和invalidate()它。我使用這個技巧很多。爲我節省了大量的內存,但我沒有做任何真正的處理器密集型任務。幾乎沒有任何處理,你可以在這裏改變幾乎所有的房產這裏有一個例子:

@Override protected void onListItemClick(final ListView inList, final View v, final int atPos, final long rowID) 
{//Get the Child, set the properties 
    ImageView _img = (ImageView)(v.findViewById(R.id.app_package)); 
    _img.setBackgroundColor(myClickedColor); 
    _img.invalidate(); // <---- BEST Option 
// ... OR ... 
    v.invalidate();  // <---- 2nd Best Option 
// ... OR ... 
    inList.invalidate(); // <---- Last resort or specialized implementation 
} 

重要的是要注意,這樣做動態有一些注意事項,當涉及到背景顏色是很重要的。你必須從點擊的視圖中獲取子...不是ListView。其次,當改變背景顏色時,你實際上正在改變背景Drawables。這意味着所有其他「有狀態」屬性都會消失,並且您必須手動將其更改回來(如果您希望以此開始)。現在

,更受歡迎,但少了幾分靈活的方法是建立你StateListDrawable XML格式。有許多資源可以學習如何在Android開發者網站上執行此操作。

希望這有助於 FuzzicalLogic

+0

感謝您的迴應模糊邏輯。然而StateListDrawable只會改變顏色/ drawables,它贏得'這對於改變字體大小有很大的幫助,另外我對onSelect狀態更感興趣,而不是onClicked狀態(我將使用軌跡球而不是onTouch),因此onListItemClick不會幫助我:(無論如何感謝您的簡要回答:) – 2012-03-21 04:45:09