0

嗨,大家好,我想在Android中創建一個FieldSet組件。 (類似於html),所以類似that。所以我想讓我的自定義組件有孩子,並有一個董事會。主板部分已經完成,但是我在顯示組件時遇到了一些問題。我正在關注this的答案。我這裏還有我的份:Android自定義組件不會顯示其子代

FieldSet.java

public class FieldSet extends ViewGroup { 

    //... 3 constructors 

    @Override 
    protected void onFinishInflate() 
    int index = getChildCount(); 
    // Collect children declared in XML. 
    View[] children = new View[index]; 
    while(--index >= 0) { 
     children[index] = getChildAt(index); 
    } 
    // Pressumably, wipe out existing content (still holding reference to it). 
    this.detachAllViewsFromParent(); 
    // Inflate new "template". 
    final View template = LayoutInflater.from(getContext()).inflate(R.layout.field_set, this, true); 
    // Obtain reference to a new container within "template". 
    final ViewGroup vg = (ViewGroup)template.findViewById(R.id.field_set_content); 
    index = children.length; 
    // Push declared children into new container. 
    while(--index >= 0) { 
     vg.addView(children[index]); 
    } 
    } 

field_set.xml

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:duplicateParentState ="true" 
    android:layout_height="wrap_content"> 
    <RelativeLayout 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_margin="15dp" 
     android:id="@+id/field_set_content" 
     android:duplicateParentState ="true" 
     android:background="@drawable/field_set_frame" 
     android:orientation="vertical" 
     android:padding="20dp"> 
    </RelativeLayout> 
    <!-- This is the title label --> 
    <TextView 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_marginLeft="50dp" 
     android:paddingLeft="50dp" 
     android:paddingRight="50dp" 
     android:layout_marginRight="50dp" 
     android:layout_centerHorizontal="true" 
     android:text="Label" 
     android:background="@color/colorLoginBlue" 
     android:padding="5dp" 
     android:id="@+id/field_set_label" 
     android:textColor="@color/colorSmallTxt" /> 
</RelativeLayout> 

的Android工作室上面的佈局預覽(好像組件的佈局是完全沒問題):

enter image description here

以下是我添加它

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    xmlns:fs="http://schemas.android.com/apk/res-auto" 
    tools:context="my.package.DeleteThis"> 
    <my.package.FieldSet 
     android:layout_width="match_parent" 
     fs:label="Injected Label" 
     android:layout_height="wrap_content" 
     android:gravity="bottom"> 
     <TextView 
      android:layout_width="wrap_content" 
      android:layout_height="wrap_content" 
      android:textSize="50sp" 
      android:text="Inner text" /> 
    </my.package.FieldSet> 
<TextView 
    android:layout_width="match_parent" 
    android:text="BELOW" 
    android:layout_height="wrap_content" /> 
</RelativeLayout> 

的Android工作室預覽如下。 (所以佈局通吃的空間,孩子需要還要注意的是組件樹表示組件TextView被添加到佈局,因爲它應該是不過孩子有0高度和寬度:。

enter image description here

field_set_frame.xml

<?xml version="1.0" encoding="utf-8"?> 
<selector xmlns:android="http://schemas.android.com/apk/res/android"> 
    <item> 
     <shape android:shape="rectangle" > 
      <corners android:radius="7dp" /> 
      <padding android:bottom="2dp"/> 
      <padding android:right="2dp"/> 
      <padding android:left="2dp"/> 
      <padding android:top="2dp"/> 
      <stroke android:width="1dp" android:color="@color/colorFieldSetBorder" /> 
     </shape> 
    </item> 
</selector> 

結果: 就沒有什麼:(,無評論)

enter image description here

我也看了this答案,嘗試過,但addView沒有幫助 - 它會導致遞歸,當我使用addToRoot=True它是沒有必要的。我試過LinearLayout,而不是Relative - 沒有改變任何東西。我想我搞砸了LayoutInflater.from(getContext()) .inflate(R.layout.field_set, this, true);。同樣值得指出的是,孩子們佔有一席之地。所以基本上,如果我增加了放入FieldSet組件的內容的高度,它會佔用更多的高度,並推動下面的所有組件。我爲這個Visibility這個問題加油。或者有的圖層低於另一圖層,仍然高度和寬度都是零。有什麼建議麼?

任何形式的幫助,非常感謝。

最好的問候,

+0

您正在擴展'ViewGroup',因此您必須自己負責測量和佈置子View。或者,你可以擴展一個已經處理子項的'ViewGroup'子類,就像你想要的那樣;例如'FrameLayout','LinearLayout','RelativeLayout'等。 –

+0

感謝您的回覆@Mike。在發佈這個問題之前,我嘗試過擴展不同的類:View,ViewGroup,LinearLayout,RelativeLayout,FrameLayout。它沒有改變。我應該實施一些處理繪圖的更多方法嗎? (如果是的話,應該包含什麼) – deathangel908

+0

不是這一點,可能。測量和佈置孩子可能是一種痛苦。如果我是你,我會先在一個已經處理過這個問題的課程中工作。例如,至少沒有理由不延長'RelativeLayout',然後擺脫當前是膨脹佈局中父代的多餘元素,而是將'RelativeLayout'和'TextView'內部的代碼包裝在''標籤中。而且,在通貨膨脹之後,像這樣的「視圖」變得有點低效,而且並不是真正必要的。 –

回答

3

直接延伸ViewGroup時,您需要處理測量和佈局的孩子View s ^自己,或者他們從來沒有大小或位置正確。通常,擴展ViewGroup子類已經可以處理那些東西,這很簡單。在這種情況下,您最好延長RelativeLayout,因爲這實際上是持有內部View,而包裝ViewGroup是沒有必要的。

在內部佈局XML父RelativeLayout是那麼多餘的,可以與<merge>標籤,這將導致孩子View小號充氣時直接添加到您的RelativeLayout子類來代替。

<merge xmlns:android="http://schemas.android.com/apk/res/android"> 

    <RelativeLayout 
     android:id="@+id/field_set_content" 
     ... /> 

    <TextView 
     android:id="@+id/field_set_label" 
     ... /> 

</merge> 

我們可以進一步簡化通過設置內部結構,構造(S),並把孩子View S IN正確的地方,因爲它們可以補充,而不是在onFinishInflate()雜耍周圍所有的事情。例如:

public class FieldSet extends RelativeLayout { 

    final ViewGroup vg; 

    public FieldSet(Context context, AttributeSet attrs) { 
     super(context, attrs); 

     LayoutInflater.from(context).inflate(R.layout.field_set, this, true); 
     vg = (ViewGroup) findViewById(R.id.field_set_content); 
    } 

    @Override 
    public void addView(View child, int index, ViewGroup.LayoutParams params) { 
     final int id = child.getId(); 
     if (id == R.id.field_set_content || id == R.id.field_set_label) { 
      super.addView(child, index, params); 
     } 
     else { 
      vg.addView(child, index, params); 
     } 
    } 
}