web-dev-qa-db-ja.com

findViewByIDはnullを返します

まず第一に、はい、このトピックに関する他のすべてのスレッドを読みました。そして、このサイトからのものだけでなく...(ほら、私は少しイライラしています)

それらのほとんどは、XMLファイルでidの代わりにAndroid:idを使用するようにアドバイスされています。やった。

他の人から、View.findViewByIdActivity.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も返しました。

次に、カスタムビューを変更してViewGroupViewの代わりに拡張し、location_layout.xmlを変更してTextViewをカスタムビューの直接の子にし、View.findViewByIdが想定どおりに動作するようにしました。驚き:それは何も解決しませんでした。

それで、私は一体何を間違っているのでしょうか?

コメントをお願いします。

233
Thomas

nullを返します

おそらく早すぎて呼び出しているからでしょう。 onFinishInflate()になるまで待ちます。 これはサンプルプロジェクトです カスタムViewがそのコンテンツにアクセスすることを示しています。

250
CommonsWare

おそらく、findViewByIdを呼び出す前にsetContentViewを呼び出していますか?その場合は、findViewByIdを呼び出してみてくださいの後のsetContentViewを呼び出します

138
Bayram Boyraz

異なる画面密度に対応したレイアウトの複数のバージョンがないことを確認してください。既存のレイアウトに新しいIDを追加するときに一度この問題に遭遇しましたが、hdpiバージョンを更新するのを忘れていました。レイアウトファイルのすべてのバージョンを更新するのを忘れると、一部の画面密度では機能しますが、他の画面密度では機能しません。

95
Joe

私の場合、プロジェクトにはmain.xmlmain2.xmlの2つのアクティビティがありました。最初から、main2mainのコピーであり、main2に新しいTextViewを追加するまではすべて正常に機能したため、R.id.textview1はアプリの残りの部分で使用可能になりました。次に、標準の呼び出しで取得しようとしました:

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

そして、それは常にヌルでした。 onCreateコンストラクターでmain2ではなく、他のインスタンス化を行っていたことが判明しました。私が持っていた:

setContentView(R.layout.main);

の代わりに

setContentView(R.layout.main2);

この場所に到着した後、私はこれに気づきました。

15
infografnet

他の場所で言及されている古典的な原因と一緒に:

  • setContentView()の前にfindViewById()を呼び出していることを確認してください
  • 必要なidsetContentView()に指定したビューまたはレイアウトにあることを確認してください
  • idが誤って異なるレイアウトで複製されないようにしてください

標準レイアウトのカスタムビューで見つけたものがありますが、これはドキュメントに反します。

理論的には、カスタムビューを作成してレイアウトに追加できます( こちらを参照 )。ただし、そのような状況では、カスタム変数以外のレイアウト内のすべてのビューで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);
    

    カスタムビューをフレームに配置します。

13
Neil Townsend

カスタムビューで間違ったスーパーコンストラクターを呼び出すと、FindViewByIdがnullになる可能性があります。 IDタグはattrsの一部であるため、attrsを無視すると、IDが削除されます。

これは間違っているだろう

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

これは正しいです

public CameraSurfaceView(Context context, AttributeSet attrs) {
        super(context,attrs);
}
13
repkap11
    @Override
protected void onStart() {
         // use findViewById() here instead of in onCreate()
    }
8
Jonathan

ExpandableListViewを使用し、タイトルに基づいてこの質問にぶつかった場合の回答

ExpandableListView実装の一部として、子ビューおよびグループビューでTextViewを操作しようとすると、このエラーが発生しました。

GetChildView()およびgetGroupView()メソッドの実装では、次のようなものを使用できます。

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

私はこれを見つけました ここ

6
Josh Metcalfe

私はAndroid/Eclipseにかなり慣れていないので、誤ってactivity_main.xmlではなくfragment_main.xmlにUIを追加しました。それを理解するのに数時間かかった...

5
lama12345

FWIW、私が必要とするのとまったく同じ方法でこれを解決した人は誰もいません。コンパイル時に不満はありませんが、実行時にnullビューを取得し、適切な順序で呼び出します。つまり、findViewById()after setContentView()です。問題は、私のビューがcontent_main.xmlで定義されていることでしたが、私のactivity_main.xmlでは、この1つのステートメントが欠けていました。

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

それをactivity_main.xmlに追加すると、NullPointerはなくなりました。

4
ferris

私の特定のケースでは、リストビューにフッターを追加しようとしました。 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);
3
Matt

私の場合は上記のようなものではなく、解決策はありませんでした。私の見解はレイアウト階層の奥深くにあると思います。私はそれを1レベル上に移動しましたが、もうヌルではありませんでした。

2

ここに私の特定のケースを投げたかっただけです。誰かが助けになるかもしれません。

次のように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を子ビューからincludeタグに移動すると、機能し始めました。

固定親:

<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">
2
John D.

私の場合、ExpandableListViewを使用していて、Android:transcriptMode="normal"を設定していました。これにより、展開可能なグループの子がほとんど表示されなくなり、リストをスクロールしたときにNULL例外が発生していました。

2
Jeevan

レイアウトリソースからアクティビティコンテンツを設定します。すなわち、setContentView(R.layout.basicXml);

2
Ajay Takur

私にとっては、同じアクティビティに対して2つのxmlレイアウトがありました。1つはポートレートモードで、もう1つは横長モードです。もちろん、landscape xmlのオブジェクトのidを変更しましたが、portraitバージョンで同じ変更を行うのを忘れていました。一方を変更した場合、もう一方のxmlに対しても同じことを行うか、実行またはデバッグして、変更していないIDが見つからない限り、エラーが発生しないことを確認してください。ああ、間抜けな間違い、なぜあなたは私をそう罰する必要がありますか?

2
ColossalChris

私も同じ問題を抱えていますが、皆さんと共有する価値があると思います。カスタムレイアウトでfindViewByIdを検索する必要がある場合、たとえば:

public class MiniPlayerControllBar extends LinearLayout {
    //code
}

コンストラクターでビューを取得することはできません。ビューが膨張した後、findViewByIdを呼び出す必要があります。それらはonFinishInflateをオーバーライドできるメソッドです

2
Shaw

同じ問題がありました。 GridViewのアダプターをオーバーライドし、各GridViewセルに独自のレイアウトを指定できるサードパーティライブラリを使用していました。

私は最終的に何が起こっているのかを理解しました。 Eclipseは、まだ示されていませんが、GridViewの各セルにライブラリのレイアウトxmlファイルを使用していました。私のカスタムアダプターでは、ランタイムではなくても、自分のプロジェクトのxmlリソースを使用していることが示されました。

したがって、私がしたことは、私のカスタムxmlレイアウトとIDがライブラリにまだ残っているものと異なることを確認し、プロジェクトをクリーンアップしてから、プロジェクトにあった正しいカスタムレイアウトの読み取りを開始することでした。

要するに、サードパーティのライブラリのアダプタをオーバーライドし、使用するアダプタの独自のレイアウトxmlを指定する場合は注意してください。プロジェクト内のレイアウトにライブラリ内のレイアウトと同じファイル名がある場合、本当に見つけにくいバグに遭遇する可能性があります!

2
JDJ

上記のソリューションに加えて、
tools:context=".TakeMultipleImages"はmainfest.xmlファイルの同じ値です:
Android:name=".TakeMultipleImages"同じアクティビティ要素。コピーアンドペーストを使用して新しいアクティビティを作成するときに発生します

2
user2982286

私の場合、レイアウトを拡大しましたが、子ビューは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 ...
1
Suragch

私の場合、親オブジェクトから親によってインスタンス化されたアダプターオブジェクトに呼び出しを移動すると、findViewByIdはnullを返しました。ここにリストされたトリックを成功せずに試行した後、findViewByIdを親オブジェクトに戻し、アダプターオブジェクトのインスタンス化中に結果をパラメーターとして渡しました。たとえば、親オブジェクトでこれを行いました:

 Spinner hdSpinner = (Spinner)view.findViewById(R.id.accountsSpinner);

次に、アダプターオブジェクトの作成中にhdSpinnerをパラメーターとして渡しました。

  mTransactionAdapter = new TransactionAdapter(getActivity(),
        R.layout.transactions_list_item, null, from, to, 0, hdSpinner);
0
Lexo

私の修正は、プロジェクトをきれいにすることでした。

0
Liangjun

上記のすべてを試してみましたが、何も機能しませんでした.. ImageView staticpublic static ImageView texture;を作成し、その後texture = (ImageView) findViewById(R.id.texture_back);を作成する必要がありましたが、これは良いアプローチではないと思いますが、これは本当に私の場合はうまくいきました:)

0
Tabish

フラグメント内にいる場合、findViewByIdはnullを返すこともできます。ここで説明されているとおり: フラグメント内のfindViewById

GetView()を呼び出して、フラグメント内のトップレベルビューを返す必要があります。次に、レイアウト項目(ボタン、テキストビューなど)を見つけることができます

0
technocrat

私の経験では、OnDestroyViewの後にコードが呼び出されたとき(フラグメントがバックスタックにあるとき)にもこれが発生する可能性があるようです。 。

0
Tad

レイアウトを膨らませる!! (IDを含む)

私の場合、要素が書き込まれたレイアウトが膨張していないため、findViewById()はnullを返しました...

例えば。 fragment_layout.xml

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

inflater.inflate(R.layout.fragment_layout、...、...);を実行していないため、findViewById(R.id.listview)はnullを返しました。その前に。

この答えがあなたの一部を助けることを願っています。

0
Akshayraj Kore

アクティビティIDのフィールドの1つが他のアクティビティのIDと一致していたため、クラッシュしました。一意のIDを指定して修正しました。

LoginActivity.xmlのパスワードフィールドidでは、「password」でした。私の登録アクティビティでは、id r_passwordを指定して修正しましたが、null以外のオブジェクトを返しました。

password = (EditText)findViewById(R.id.r_password);
0
Jageloo Yadav

ListViewのカスタムビューを作成しようとしたときに、同様の問題に直面していました。

私はこれを簡単に解決しました:

public View getView(int i, View view, ViewGroup viewGroup) {

    // Gets the inflater
    LayoutInflater inflater = LayoutInflater.from(this.contexto);

    // Inflates the layout
    ConstraintLayout cl2 = (ConstraintLayout) 
    inflater.inflate(R.layout.custom_list_view, viewGroup, false);

    //Insted of calling just findViewById, I call de cl2.findViewById method. cl2 is the layout I have just inflated. 
     TextView tv1 = (TextView)cl2.findViewById(cl2);
0
Rafael Costa