2010-07-16 269 views
196

首先:是的,我閱讀了關於此主題的所有其他主題。而且不僅是從本網站......(你看,我有點沮喪)findViewByID返回null

他們大多與建議XML文件中使用android:id,而不只是id。我做到了。

從其他人那裏我瞭解到,View.findViewById的作品不同於Activity.findViewById。我也是這樣處理的。

在我location_layout.xml,我使用:

<FrameLayout .... > 
    <some.package.MyCustomView ... /> 

    <LinearLayout ... > 
     <TextView ... 
      android:id="@+id/txtLat" /> 
     ... 
    </LinearLayout> 
</FrameLayout> 

在我的活動我做的:

... 
setContentView(R.layout.location_layout); 

,在我的自定義視圖類:

... 
TextView tv = (TextView) findViewById(R.id.txtLat); 

返回null這樣做,我的活動正常工作。所以也許是因爲Activity.findViewByIdView.findViewById的差異。所以我存儲傳遞到海關來看待構造本地和嘗試:

... 
TextView tv = (TextView) ((Activity) context).findViewById(R.id.txtLat); 

也返回null

然後,我改變了我的自定義視圖擴展ViewGroup代替View,改變了location_layout.xmlTextView是我的自定義視圖的直接子,使View.findViewById應該工作的設想。驚喜:它沒有解決任何問題。

那麼,我做錯了什麼?

我會感謝您的任何意見。

+4

如果項目也被破壞,可能會發生這種情況。我通過清理項目來解決它 – Pacerier 2012-02-14 10:07:51

+1

通過錯誤的上下文視圖謝謝 – izzy 2015-04-13 09:59:59

+1

@Pacerier謝謝。這解決了我的問題。我開始討厭Xamarin中的android編程) – Artiom 2015-08-16 17:58:38

回答

226

其返回null

可能是因爲您太早調用它。等到onFinishInflate()Here is a sample project演示自定義View訪問其內容。

+51

OMG!不能相信我花了幾天的時間來處理這麼瑣碎的事情。我把setContentView()移到了findViewById()調用的上面,這並沒有把戲。謝謝! – agentcurry 2012-01-26 20:35:30

+0

@CommonsWare它是正確的項目?我沒有在https://github.com/commonsguy/cw-advandroid/tree/master/Animation/SlidingPanel/ – likejiujitsu 2015-10-12 16:43:19

+0

@likejiujitsu:它可能在2010年有這回。我已經更新了鏈接到一個更新的具有'onFinishInflate()'的項目。 – CommonsWare 2015-10-12 16:58:54

80

請確保您沒有針對不同屏幕密度的多個版本的佈局。在向現有佈局添加新的ID時,我遇到過這個問題,但忘記更新hdpi版本。如果您忘記更新佈局文件的所有版本,它將適用於某些屏幕密度,但不適用於其他屏幕密度。

+5

感謝!就是這樣。 (在我的情況下,我有不同的Android版本的多個版本)。儘管我在每個佈局文件的頂部和底部放了一個巨大的評論,但我一直都忘記它。如果發生這種情況,我希望編譯器會發出錯誤或很大的警告。 – tiktak 2013-01-20 12:28:53

+0

親愛的主謝謝你,我一直在看我的代碼5個小時,以爲我是一個白癡。真的幫了! – Squeazer 2014-03-13 13:50:59

116

在致電setContentView之前,您可能需要致電findViewById? 如果是這樣的情況下,嘗試調用findViewById調用setContentView

+1

這樣一個容易犯的錯誤讓不過,這是我所做的。調試器沒有用,因爲它表示錯誤出現在我的新意向行,而不是我正在調用的實際新行爲中。謝謝! – edude05 2012-04-13 01:23:41

+4

其實我有這個錯誤,因爲我正在調用setContentView指向錯誤的視圖...不幸的是,編譯器不會捕獲這種類型的錯誤。 – HeatfanJohn 2013-02-12 16:23:56

+0

是的,我錯誤地刪除了setContentView,並不明白爲什麼我的程序開始粉碎。 – 2016-07-15 18:23:02

5

一個答案對於那些使用ExpandableListView碰上基於它的標題這個問題。

我有這個錯誤嘗試在我的子視圖和組視圖中使用TextViews作爲ExpandableListView實現的一部分。

您可以使用類似在你的getChildView()和getGroupView的實現下列()方法。

 if (convertView == null) { 
      LayoutInflater inflater = (LayoutInflater) myContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
      convertView = inflater.inflate(R.layout.child_layout, null); 
     } 

我發現這個here

1

就我而言,我是用ExpandableListView和我設置android:transcriptMode="normal"。這導致可擴展組中的幾個孩子消失,並且在我使用滾動列表時,我曾經得到NULL異常。

11

就我而言,我有2個activites在我的項目,main.xmlmain2.xml。從一開始,main2是的main副本,一切運行良好,直到我增加了新的TextViewmain2,所以R.id.textview1對應用程序的其餘變得可用。然後我嘗試通過標準呼叫取回它:

TextView tv = (TextView) findViewById(R.id.textview1); 

它總是空。原來,在onCreate構造函數中,我實例化的不是main2,而是另一個。我:

setContentView(R.layout.main); 

,而不是

setContentView(R.layout.main2); 

我注意到這一點我來到這裏,在網站上後。

1

對我來說,我有相同的活動兩個XML佈局 - 一個在縱向模式下,一個在景觀。當然,我已經改變了景觀xml中的一個對象的id,但忘記了在肖像版本中做出同樣的改變。確保你是否改變了你對其他xml的相同,或者在你運行/調試它之前你不會得到一個錯誤,並且它找不到你沒有改變的id。哦,愚蠢的錯誤,爲什麼你要懲罰我呢?

0

以我的經驗看來,當你的代碼在OnDestroyView之後被調用時(當片段位於背面堆棧上時),也可能發生這種情況。如果你正在更新來自BroadCastReceiver輸入的UI,你應該檢查if情況就是如此。

4

我很新的Android/Eclipse,我錯誤地添加了UI的東西activity_main.xml而不是fragment_main.xml。花了我幾個小時才弄清楚...

7
@Override 
protected void onStart() { 
     // use findViewById() here instead of in onCreate() 
    } 
1

設置佈局資源的活動內容。 即,setContentView(R.layout.basicXml);

1

我有同樣的問題。我使用的第三方庫允許您覆蓋它們的GridView適配器併爲每個GridView單元指定您自己的佈局。

我終於意識到發生了什麼事。對於GridView中的每個單元格,Eclipse仍然使用該庫的layout xml文件,即使它沒有提供任何指示。在我的自定義適配器中,它表明它正在使用我自己的項目中的xml資源,即使在運行時,它也不是。

所以我所做的就是確保我的自定義xml佈局和ID與那些仍然坐在庫中的不同,清理該項目,然後開始閱讀我項目中正確的自定義佈局。

總之,如果您重寫第三方庫的適配器並指定您自己的佈局xml供適配器使用,請小心。如果您的項目中的佈局與庫中的文件名相同,則可能會遇到一個非常難以發現的錯誤!

11

除了傳統的原因,其它地方提到:

  • 確保你叫setContentView()之前findViewById()
  • 確保你想要的id是你給setContentView()
  • 視圖或佈局
  • 確保id不小心在不同的佈局複製

我在標準佈局中找到了一個自定義視圖,這與文檔不符:

理論上,您可以創建自定義視圖並將其添加到佈局(see here)。不過,我發現在這種情況下,id屬性有時適用於佈局中除自定義佈局外的所有視圖。我使用的解決方案是:

  1. 用具有相同佈局屬性的FrameLayout替換每個自定義視圖,您希望自定義視圖具有相同的佈局屬性。給它一個合適的id,比如frame_for_custom_view
  2. onCreate

    setContentView(R.layout.my_layout); 
    FrameView fv = findViewById(R.id.frame_for_custom_layout); 
    MyCustomView cv = new MyCustomView(context); 
    fv.addView(cv); 
    

    這使自定義視圖在框架中。

+0

這幫助了我:「確保你想要的id在你給setContentView()給出的視圖或佈局中」。當它是子視圖時要怎麼做?嘗試獲取父視圖,然後做parentView.findById(),但它仍然返回null – NaturalBornCamper 2017-12-23 18:26:08

+0

@naturalborncamper如果你用示例代碼發佈一個單獨的問題我會看看它。 – 2017-12-24 09:18:30

+0

謝謝尼爾,我已經發布了,有人指出了一個更好的方法來做到這一點,雖然它不能正確地工作,所以我不得不使用不同的策略:https:// stackoverflow。com/questions/47955376/get-subview-of-loaded-view-group-inside-a-drawer/47955507 – NaturalBornCamper 2017-12-25 20:25:26

1

在我的情況下,我膨脹了佈局,但子視圖返回null。本來我有這個:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_history); 

    footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false); 
    pbSpinner = (ProgressBar) findViewById(R.id.pbListviewFooter); 
    tvText = (TextView) findViewById(R.id.tvListviewFooter); 
    ... 
} 

然而,當我把它改成下面它的工作:

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_history); 

    footerView = ((LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.listview_footer, null, false); 
    pbSpinner = (ProgressBar) footerView.findViewById(R.id.pbListviewFooter); 
    tvText = (TextView) footerView.findViewById(R.id.tvListviewFooter); 
    ... 
} 

的關鍵是爲了得到孩子的意見具體提到的已經是膨脹的佈局。也就是說,增加footerView

  • footerView .findViewById ...
2

在我的具體情況,我試圖頁腳添加到ListView。 onCreate()中的以下調用返回null。

TextView footerView = (TextView) placesListView.findViewById(R.id.footer); 

更改此項以擴大頁腳視圖而不是通過ID查找它解決了此問題。

View footerView = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.footer_view, null, false); 
1

除了上述解決方案,你要確保在佈局中
tools:context=".TakeMultipleImages" 是在mainfest相同的值。xml文件:
android:name=".TakeMultipleImages"對於相同的活動元素。 使用複製和粘貼創建新活動時發生

8

如果您在自定義視圖中調用錯誤的超級構造函數,則FindViewById可爲null。 ID標籤是attrs的一部分,所以如果您忽略attrs,則會刪除該ID。

這將是錯誤的

public CameraSurfaceView(Context context, AttributeSet attrs) { 
     super(context); 
} 

這是正確的

public CameraSurfaceView(Context context, AttributeSet attrs) { 
     super(context,attrs); 
} 
+0

非常感謝您的先生!我很粗心,我甚至懷疑我的IDE有什麼問題。很高興遇到你的答案。 – EffectiveMatrix 2015-07-20 10:52:28

+0

我在創建自定義視圖時犯了這個錯誤。謝謝你,repkap11。 – 2016-08-09 17:47:27

+0

這應該值得更多upvotes。 – 2017-09-21 03:50:37

1

我有同樣的問題,但我認爲它值得分享與你們。 如果您有自定義佈局findViewById,例如:

public class MiniPlayerControllBar extends LinearLayout { 
    //code 
} 

你不能在構造函數中的視圖。 你應該在視圖充滿後調用findViewById。 他們是你可以覆蓋的方法onFinishInflate

0

INFLATE THE LAYOUT !! (其中包含ID)

在我的情況findViewById()返回null,因爲其中的元素被寫入佈局,不誇大...

EG。 fragment_layout.xml

<ListView 
android:id="@+id/listview"> 

findViewById(R.id.listview)返回null,因爲我沒有做 inflater.inflate(R.layout.fragment_layout,...,...);它之前有 。

希望這個答案有助於你們一些。

0

我的修復只是清理項目。

0

只是想在這裏拋出我的具體情況。可能幫助某人下線。

我所用的指令在我的Android UI XML這樣的:

父視圖:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:tag="home_phone" 
    android:background="@color/colorPrimary"> 

    ... 

    <include 
     layout="@layout/retry_button" 
     android:visibility="gone" /> 

子視圖(retry_button):

<com.foo.RetryButton 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@+id/retry" 
    android:layout_gravity="center" 
    android:orientation="vertical" 
    android:layout_width="100dp" 
    android:layout_height="140dp"> 

.findViewById(R.id .retry)總是返回null。但是,如果我將ID從子視圖移到包含標記中,它就開始工作。

固定父:

<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    android:tag="home_phone" 
    android:background="@color/colorPrimary"> 

    ... 

    <include 
     layout="@layout/retry_button" 
     android:id="@+id/retry" 
     android:visibility="gone" /> 

固定孩子:

<com.foo.RetryButton 
    xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_gravity="center" 
    android:orientation="vertical" 
    android:layout_width="100dp" 
    android:layout_height="140dp"> 
3

FWIW,我沒有看到任何人在以同樣的方式解決了這個,因爲我需要的。在編譯時沒有抱怨,但我在運行時得到了一個空視圖,並按正確的順序調用了一些東西。也就是 findViewById() setContentView()。 原來,這個問題,我的觀點是在content_main.xml定義,但在我activity_main.xml中,我缺少這一個聲明:

<include layout="@layout/content_main" /> 

當我補充說,activity_main.xml中,沒有更多的空指針。

+0

複製粘貼片段的問題是,您有時忘記改變一些東西......是正確的佈局來誇大其中之一。謝謝! – 2018-01-05 23:31:50

0

如果你在一個片段內,findViewById也可以返回null。如此處所述:findViewById in Fragment

您應該調用getView()以返回片段中的頂級視圖。然後,你可以找到

1

我已經嘗試了所有上面什麼也沒有工作佈局的項目(按鈕,textviews等)..所以我必須讓我的ImageView的靜態public static ImageView texture;然後texture = (ImageView) findViewById(R.id.texture_back);,我不知道認爲這是一個很好的做法,但這真的對我的情況:)

1

我的情況是沒有像上面,沒有解決方案的工作。我認爲我的觀點太深入佈局層次。我把它調高了一級,它不再是零。

+0

我有同樣的問題,也可以找到一個更高的級別..這很煩人,我想知道爲什麼它發生,因爲我不能讓我的菜單像我想要的那樣 – NaturalBornCamper 2017-12-23 17:17:24

+0

很好的深層佈局層次結構是反模式幾乎總是有一個更清潔的解決方案。你在談論工具欄或導航抽屜中的溢出菜單嗎? – 2017-12-25 12:03:34

+0

導航抽屜,實際上我已經發布了另一個問題,除了在組內添加菜單項不起作用,只是將其添加到所有項的末尾:https://stackoverflow.com/questions/47955376/get-subview -of加載 - 視圖 - 基團的內-A-抽屜/ 47955507#47955507 – NaturalBornCamper 2017-12-25 20:27:00