2013-05-02 82 views
2

我正在嘗試基於用戶實時指定的輸入爲我的Android應用程序實現動態按鈕充氣。點擊時,按鈕將其顏色從藍色更改爲紅色。更改顏色時充氣按鈕的奇怪行爲

負責這個代碼去如下:

LayoutInflater layoutsInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
LinearLayout linearLayout = (LinearLayout) findViewById(R.id.layout_for_buttons); 

// Let's say that now we need only 3 buttons: 
for (int i = 0; i < 3; i++) { 
    RelativeLayout buttonLayout = (RelativeLayout) layoutsInflater 
      .inflate(R.layout.button_layout, linearLayout, false); 
    Button button = (Button) buttonLayout.getChildAt(0); 
    button.setText("Button " + i); 

    button.setOnClickListener(new OnClickListener() { 
     @Override 
     public void onClick(View buttonView) { 
      Button button = (Button) buttonView; 
      GradientDrawable gradientDrawable = (GradientDrawable) button 
        .getBackground(); 
      gradientDrawable.setColor(Color.RED); 
      gradientDrawable.invalidateSelf(); 
     } 
    }); 

    linearLayout.addView(buttonLayout); 
    linearLayout.invalidate(); 
} 

佈局我追加按鈕是一個簡單的LinearLayout

<LinearLayout 
    android:id="@+id/layout_for_buttons" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent" 
    android:orientation="vertical" > 
</LinearLayout> 

充氣button_layoutRelativeLayoutButtonTextView的:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:layout_marginBottom="10sp" > 

    <Button 
     android:id="@+id/button_view" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:background="@drawable/button_bg" 
     android:gravity="left" 
     android:paddingBottom="7dip" 
     android:paddingLeft="50sp" 
     android:paddingTop="7dip" 
     android:textColor="#FFFFFF" 
     android:textSize="20sp" /> 

    <TextView 
     android:id="@+id/label_view" 
     android:layout_width="24dip" 
     android:layout_height="24dip" 
     android:layout_marginLeft="13dip" 
     android:layout_marginTop="8dip" 
     android:gravity="center" 
     android:text="Hi" 
     android:textColor="#FFFFFF" 
     android:textSize="20sp" 
     android:textStyle="bold" /> 

</RelativeLayout> 

@drawable/button_bg是藍顏色的shape

<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:padding="10dp" 
    android:shape="rectangle" > 
    <solid android:color="#0000ff" /> 
    <corners android:radius="10dp" /> 
</shape> 

現在,當我運行應用程序似乎一切都很好。被點擊後,第一個按鈕意料之中變爲紅色:

enter image description here

當我關閉並重新運行該應用程序的每一個按鈕是藍色的,那就是我的期望相匹配的行爲。問題是,當我重新運行第二次應用程序,每個按鈕變爲紅色(就好像它已被點擊):

enter image description here

因爲它是寫一個文檔中,inflate方法應膨脹一個新的視圖層次基於給定的XML,所以可能是負責任?我認爲每個充氣按鈕之間可能會共享相同的GradientDrawable,但調試器顯示每個按鈕都有自己的GradientDrawable實例。添加視圖後線性佈局

回答

8

看來,我已經解決了我的問題。這是一個GradientDrawable.mutate()方法,這不得不叫嚴防此類行爲發生:

Button button = (Button) buttonView; 
GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground(); 
gradientDrawable.mutate(); // needed line 
gradientDrawable.setColor(Color.RED); 
gradientDrawable.invalidateSelf(); 

它保證初始化的繪製對象不會與可繪製來自同一個XML充氣分享它的狀態,因爲它是在documentation指出:

使這個drawable變化。這個操作不能逆轉。一個可變的drawable保證不與其他drawable共享它的狀態。當你需要修改從資源加載的drawable的屬性時,這是特別有用的。默認情況下,從同一資源加載的所有可繪製實例共享一個公共狀態;如果修改一個實例的狀態,則所有其他實例都將收到相同的修改。在可變Drawable上調用此方法將不起作用。

+0

當我寫代碼類似於你我懷疑我會有像你這樣的問題),並感謝您的答案 – 2015-10-30 16:20:28

0

呼叫無效,

linearLayout.addView(buttonLayout); 
linearLayout.invalidate(); 
+0

我在'linearLayout'上添加了'invalidate'調用,但按鈕的奇怪行爲保持不變。 – falconepl 2013-05-02 19:26:11

+0

嘗試在您的活動父級佈局上調用invalidate。 – deepdroid 2013-05-02 19:57:28

+0

不幸的是,它也沒有幫助。 – falconepl 2013-05-02 20:23:05