2011-09-02 106 views
4

我有一個自定義類(觸摸按鈕),用於擴展TextView類。我無法手動調整按鈕的大小。我可以讓按鈕僅適用於一種類型的佈局或容器,但不能同時適用。在大多數情況下,Touchbutton是在GridView的,所以我的方法來改變大小是這樣:更改佈局和容器的自定義按鈕大小

private void setLayout(buttonsize_t size) { 

    log("Setting Layout: "+buttonsize_t.getPxl(size)); 

    final float scale = getContext().getResources().getDisplayMetrics().density; 
    int dim = (int) (buttonsize_t.getPxl(size) * scale + 0.5f); 

    AbsListView.LayoutParams params = (AbsListView.LayoutParams) getLayoutParams(); 
    if (params != null) { 
     params.height = dim; 
     params.width = dim; 
    } 
    else { 
     params = new AbsListView.LayoutParams(dim,dim); 
    } 
    setLayoutParams(params); 
} 

然而,當TouchButton在LinearLayout中被調整(例如)我得到一個崩潰與logcat的:

09-01 19:18:35.630: ERROR/AndroidRuntime(20793): java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams 
09-01 19:18:35.630: ERROR/AndroidRuntime(20793):  at com.ians.aac3.TouchButton.setLayout(TouchButton.java:204) 

204行是指params的實例化。

我注意到GridViewLinearLayout共享父母ViewGroup,所以我嘗試使用ViewGroup.LayoutParams。然而,這會導致Gridviews的相同行爲(logcat引用相同的行)。

有誰知道我可以如何使這項工作的任何類型的佈局或部件?

UPDATE: 作爲建議我嘗試再次與視圖組:

import android.content.Context; 
import android.content.res.TypedArray; 
import android.util.AttributeSet; 
import android.util.Log; 
import android.view.ViewGroup; 
import android.view.ViewGroup.LayoutParams; 
import android.widget.TextView; 
..... 
ViewGroup.LayoutParams params = getLayoutParams(); 
     if (params != null) { 
      params.height = dim; 
      params.width = dim; 
     } 
     else { 
      params = new LayoutParams(dim,dim); 
     } 
     setLayoutParams(params); 

或沒有試圖回收當前的LayoutParams:

setLayoutParams(new ViewGroup.LayoutParams(dim, dim)); 

,我也得到相同類型的錯誤:

09-02 09:10:49.680: ERROR/AndroidRuntime(7069): java.lang.ClassCastException: android.view.ViewGroup$LayoutParams cannot be cast to android.widget.AbsListView$LayoutParams 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.widget.GridView.onMeasure(GridView.java:1028) 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.view.View.measure(View.java:10828) 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351) 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.widget.FrameLayout.onMeasure(FrameLayout.java:267) 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.view.View.measure(View.java:10828) 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.view.ViewGroup.measureChildWithMargins(ViewGroup.java:4351) 
09-02 09:10:49.680: ERROR/AndroidRuntime(7069):  at android.widget.LinearLayout.measureChildBeforeLayout(LinearLayout.java:1284) 

更新2: 看來,使用上面指定的ViewGroup.LayoutParams適用於LinearLayout。然而,如上所見,gridview並不喜歡它...

回答

19

要了解這裏發生了什麼,您需要查看Android源代碼。有一個在一個ViewGroup​​方法的Javadoc的狀態:

Returns a safe set of layout parameters based on the supplied layout params. When a ViewGroup is passed a View whose layout params do not pass the test of checkLayoutParams(android.view.ViewGroup.LayoutParams) , this method is invoked. This method should return a new set of layout params suitable for this ViewGroup, possibly by copying the appropriate attributes from the specified set of layout params.

如果你看的LinearLayout和AbsListView源(GridView控件的父),你會看到他們轉換他們的孩子分別佈局PARAMS到LinearsLayout.LayoutParamsAbsListView.LayoutParams。但是這種轉換隻發生在孩子被添加到佈局時。
因此,如果您將TouchButton添加到LinearLayout(programmaticaly或通過XML),它將會收到LinearsLayout.LayoutParams,如果您將它添加到GridView(通過適配器),它會收到AbsListView.LayoutParams
但是,如果您之後手動設置佈局參數,您將在父容器代碼的某處獲得ClassCastException(因爲它期望其子佈局參數具有某種特定類型)。

爲了您的問題的解決,我建議你如下:

private void setLayout(buttonsize_t size) { 

    log("Setting Layout: "+buttonsize_t.getPxl(size)); 

    final float scale = getContext().getResources().getDisplayMetrics().density; 
    int dim = (int) (buttonsize_t.getPxl(size) * scale + 0.5f); 

    ViewGroup.LayoutParams params = (ViewGroup.LayoutParams) getLayoutParams(); 
    if (params != null) { 
     params.height = dim; 
     params.width = dim; 
     setLayoutParams(params); 
    } else { 
     // the LayoutParams was not set yet, it must be the GridView 
     // which delays setting till child rendering 
     params = new AbsListView.LayoutParams(dim, dim); 
     setLayoutParams(params); 
    } 
} 
+2

出色地工作。感謝你的決議和一個很好的解釋。 – Ian

+0

感謝您的解釋(= – moskis

0

爲什麼要投影LayoutParams呢?

Button.getLayoutParams()應該返回ViewGroup.LayoutParams,您可以訪問高度和寬度 - 無需強制轉換。你確定當你嘗試ViewGroup.LayoutParams你沒有做類似的事情:

ViewGroup.LayoutParams params = (AbsListView.LayoutParams) getLayoutParams(); 

(這仍然會失敗)。

在任何情況下,使用此:

ViewGroup.LayoutParams params = getLayoutParams(); 

然後,如果你仍然得到一個異常,張貼一個 - 而不是一個與鑄件。

+0

想你的建議,並得到:09-01 22:16:35.740:ERROR/AndroidRuntime(27937):java.lang.ClassCastException: android.view.ViewGroup $ LayoutParams不能轉換爲android.widget.AbsListView $ LayoutParams – Ian

+0

在哪一行?你的代碼應該得到一個現有的LayoutParams的實現,改變它,然後再次設置它,我不知道爲什麼演員會失敗,除非它創建一個新的LayoutParams對象。 –

+0

這次跟蹤沒有給我一個行號。 – Ian