2012-06-14 90 views
17

我做如下如何將視圖引用傳遞給android自定義視圖?

1)創建設置樣式

<declare-styleable name="Viewee"> 
    <attr name="linkedView" format="reference"/> 
</declare-styleable> 

2)定義的自定義視圖佈局

<LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     android:layout_width="fill_parent" 
     android:layout_height="wrap_content" 
     android:background="#ffc0"> 
    <TextView 
      android:id="@+id/custom_text" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:text="[text]" 
      /> 
</LinearLayout> 

3)創建所需的類

public class Viewee extends LinearLayout 
{ 
public Viewee(Context context, AttributeSet attributeSet) 
{ 
    super(context, attributeSet); 
    View.inflate(context, R.layout.viewee, this); 
    TextView textView = (TextView) findViewById(R.id.custom_text); 
    TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.Viewee); 
    int id = typedArray.getResourceId(R.styleable.Viewee_linkedView, 0); 
    if (id != 0) 
    { 
     View view = findViewById(id); 
     textView.setText(((TextView) view).getText().toString()); 
    } 

    typedArray.recycle(); 
} 
} 

,最後在像下面的活動

<LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android" 
     xmlns:app="http://schemas.android.com/apk/res/com.ns" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:orientation="vertical"> 
    <TextView 
      android:id="@+id/tvTest" 
      android:layout_width="fill_parent" 
      android:layout_height="wrap_content" 
      android:text="android"/> 
    <com.ns.Viewee 
      android:layout_width="fill_parent" 
      android:layout_height="fill_parent" 
      app:linkedView="@+id/tvTest" 
      /> 
</LinearLayout> 

現在雖然我收到的Viewee constractor非零idfindViewById(id) retuns空,NullPointerException occures。

我錯過了什麼?

I did it as described here

回答

17

我找到了答案!

問題出在findViewById(id)以及我稱之爲的地方。 findViewById只會查找子視圖,而不會在上層級別上存在視圖,因爲documentation說。所以我必須打電話給getRootView().findViewById(id),但這也會返回null因爲我稱之爲不正確。

Viewee約束條件Viewee本身尚未附加到其根目錄,因此致電NullPointerException

因此,如果我在調用之後的其他地方致電getRootView().findViewById(id),它可以正常工作,並且"@+id/tvTest""@id/tvTest"都是正確的。我測試過了!

的答案如下

public class Viewee extends LinearLayout 
{ 
    public Viewee(Context context, AttributeSet a) 
    { 
     super(context, attributeSet); 
     View.inflate(context, R.layout.main6, this); 
     TextView textView = (TextView) findViewById(R.id.custom_text); 
     TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee); 
     int id = t.getResourceId(R.styleable.Viewee_linkedView, 0); 
     if (id != 0) 
     { 
      _id = id; 
     } 

     t.recycle(); 
    } 

    private int _id; 

    public void Foo() 
    { 
     TextView textView = (TextView) findViewById(R.id.custom_text); 
     View view = getRootView().findViewById(_id); 
     textView.setText(((TextView) view).getText().toString()); 
    } 
} 

Foo當需要它來處理通過其參考ID其他地方的連接視圖中的作用等被調用。

信貸完全去那些貢獻在this post。在提交問題之前,我沒有看過那篇文章。

+0

不要把它放在'onDraw',而是放在'onAttachedToWindow'中,放在onDraw中會每秒調用X次,每秒可以達到60次@DanielWilson你可以刪除你的評論嗎? –

2

你的描述android:id設置爲app:linkedView="@+id/tvTest。但是,@+id/tvTest用於創建名稱爲「tvTest」的新ID。你想要做的是使用app:linkedView="@id/tvTest

+0

我通過'View view = findViewById(id);'來應用您的答案;'仍然返回null! – anonim

+0

你爲什麼使用'id'來保存視圖的ID?使用R.id.foo而不是創建另一個變量應該相當簡單。另外,我無法通過您的評論來判斷您是否將您的元素的'app:linkedView'屬性更改爲'「@ id/tvTest'。 –

+0

我必須持有id '因爲'Viewee'是一個自定義的視圖,指的是另一個視圖的一個共振,我不能像你說的那樣將鏈接的視圖稱爲R.id.foo'如果我在另一個佈局中使用'Viewee',那麼'R .id.foo'不存在嗎?我也照你的建議做了,並且把''@ + id/tvTest「'改爲'」@ id/tvTest「',但沒有成功 – anonim

8

我知道這是一個古老的問題,但我想我會添加另一種方法做到這一點,因爲我想將所有內容封裝到我的自定義視圖中。

而是從外面打電話的,層次結構中得到一個視圖上漲的另一種方式,我已經迷上到onAttachedToWindow()代替:

public class MyCustomView extends LinearLayout { 
    private int siblingResourceId; 
    private View siblingView; 

    public MyCustomView(Context context, AttributeSet a) { 
     super(context, attributeSet); 
     View.inflate(context, R.layout.main6, this); 
     TextView textView = (TextView) findViewById(R.id.custom_text); 
     TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee); 
     siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, 0); 
     t.recycle(); 
    } 

    @Override 
    public void onAttachedToWindow() { 
     super.onAttachedToWindow(); 
     if (siblingResourceId != 0) { 
      siblingView = getRootView().findViewById(siblingId); 
     } 
    } 
} 

onAttachedToWindow相當叫早,但顯然不夠遲到了整個視圖層次結構已經解決。它適用於我的需求至少是完美無缺的,並且有一點控制,並且不需要從外部進行互動;-)

相關問題