findViewByIDはnullを返します


251

まず第一に、はい、このトピックに関する他のすべてのスレッドを読みました。そして、このサイトからのものだけではありません...

それらのほとんどは、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.findViewByIdとのView.findViewById違いによるものでしょう。そのため、カスタムビューコンストラクターに渡されたコンテキストをローカルに保存して試してみました。

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

これも帰ってきたnull

その後、私は拡張するために私のカスタムビューを変更するViewGroup代わりにView、変更location_layout.xmlできるようにするTextViewように、私のカスタムビューの直接の子であるView.findViewByIdはずのように動作するはずです。驚き:それは何も解決しませんでした。

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

コメントをいただければ幸いです。


6
これは、プロジェクトも破損している場合に発生することがあります。プロジェクトを
クリーンアップして修正

1
間違ったコンテキストビューに合格しました
izzy、2015

1
@Pacerierありがとうございます。それは私の問題を解決しました。XamarinでのAndroidプログラミングが嫌いになり始めました)
Artiom

@Pacerier「クリーンプロジェクト」は私の問題も解決しました。Dropboxがプロジェクトを破損したようです。
マキタニコーキ

回答:


271

nullを返す

多分あなたはそれを早すぎると言っているからです。まで待つonFinishInflate()以下は、Viewコンテンツにアクセスするカスタムを示すサンプルプロジェクトです。


67
ああ、神様!カントは、私がとても些細なことに何日も費やすと信じています。私は、setContentView()をfindViewById()呼び出しの上に移動しましたが、それはうまくいきませんでした。ありがとう!
agentcurry 2012年

2
@CommonsWareそれは正しいプロジェクトですか?私は中onFinishInflateどこにも表示されないgithub.com/commonsguy/cw-advandroid/tree/master/Animation/...
likejudo

1
@likejiujitsu:2010年のことかもしれませんonFinishInflate()。新しいプロジェクトへのリンクを更新しました。
CommonsWare、2015年

3
findViewByIdの前にsetContentViewを呼び出しましたが、まだnullです。私はEditTextを参照しています
Neon Warge

1
常に修正されたGitHubコミット(例:github.com/commonsguy/cw-omnibus/tree/…)にリンクし、リポジトリやリベースを削除しないでください;-)
Ciro Santilli郝海东冠状病六四事件法轮功

145

たぶん、あなたは呼び出すfindViewById前に呼び出していsetContentViewますか?その場合は、findViewById AFTERを呼び出してから呼び出してみてください。setContentView


1
そのような簡単な間違いは間違いですが、残念ながらこれは私がやったことです。デバッガーは、エラーが、私が呼び出していた実際の新しいアクティビティーではなく、私の新しいインテント行にあると言ったので、役に立ちません。ありがとう!
edude05

6
間違ったビューを指すsetContentViewを呼び出していたため、実際にこのエラーが発生しました...残念ながら、コンパイラーはこのタイプのエラーをキャッチしません。
HeatfanJohn 2013

はい、誤ってsetContentViewを削除しましたが、プログラムがクラッシュし始めた理由がわかりませんでした。
Ronen Festinger

100

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


8
ありがとう!それだけでした。(私の場合、異なるバージョンのAndroidに複数のバージョンがあります)。すべてのレイアウトファイルの上部と下部に巨大なコメントを付けましたが、いつも忘れてしまいました。これが起こった場合、コンパイラがエラーまたは大きな警告を出してくれるといいのですが。
tiktak 2013年

Ding ding ding、どうもありがとう!この
ザック

21

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

これは間違っているでしょう

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

これは正しいです

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

1
どうもありがとうございました!私は不注意なので、IDEに問題があるのではないかと疑いさえしました。あなたの答えに出会えてどれほど幸運か。
EffectiveMatrix

カスタムビューを作成したときにこの間違いをしました。ありがとう、repkap11。
Andrew F.

15

私の場合、私は私のプロジェクトでの2つのactivitesを持っていた、main.xmlmain2.xml。最初からmain2はのコピーでしたがmain、に新しいものTextViewが追加されるまで、すべてが正常に機能し、がアプリの残りの部分で使用できるmain2ようにR.id.textview1なりました。次に、標準の呼び出しでそれをフェッチしようとしました:

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

そしてそれは常にヌルでした。onCreate結局、コンストラクタではインスタンス化していなかったことがわかりましたmain2。私が持っていた:

setContentView(R.layout.main);

の代わりに

setContentView(R.layout.main2);

私はここに到着した後、サイトでこれに気づきました。


14

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

  • setContentView()以前に電話したことを確認してくださいfindViewById()
  • id目的のものが、指定したビューまたはレイアウトにあることを確認してくださいsetContentView()
  • 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);

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


これは私に役立ちました:「必要なIDが、setContentView()に指定したビューまたはレイアウトにあることを確認してください」。ただし、サブビューの場合はどうすればよいですか?親ビューを取得してからparentView.findById()を実行しようとしましたが、それでもnullが返されます
NaturalBornCamper

@naturalborncamperあなたがサンプルコードで別の質問を投稿するなら、私はそれを見るでしょう。
Neil Townsend

おかげでニール、私はすでに掲載し、私が別の戦略を使用していたので、それがあるべき正確にどのように働いていないが、誰かが、これを行うには良い方法を指摘:stackoverflow.com/questions/47955376/...
NaturalBornCamper


6

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);
        }

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


5

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


5

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

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

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


フラグメントをコピーして貼り付ける際の問題は、時々変更することを忘れてしまうことです...それらの1つを膨らませるのに適切なレイアウトであること ありがとう!
パブロケメ

3

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

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

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

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


3

私の特定のケースでは、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);

2

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


2

私にとっては、同じアクティビティ用に2つのxmlレイアウトがありました。1つは縦長モードで、もう1つは横長です。もちろん、横向きxmlのオブジェクトのIDを変更しましたが、縦向きバージョンで同じ変更を加えるのを忘れていました。1つを他のxmlと同じように変更するか、実行またはデバッグするまでエラーが発生せず、変更していないIDが見つからないことを確認してください。ばかげた間違い、なぜあなたは私を罰しなければならないのですか?


2

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


2

上記のソリューションに加え
tools:context=".TakeMultipleImages" て、レイアウト内のがmainfest.xmlファイル内の同じ値であることを確認してください:
android:name=".TakeMultipleImages"同じアクティビティ要素の場合。コピーと貼り付けを使用して新しいアクティビティを作成すると発生します


2

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

public class MiniPlayerControllBar extends LinearLayout {
    //code
}

コンストラクタでビューを取得することはできません。ビューが膨らんだ後、findViewByIdを呼び出す必要があります。彼らはあなたがオーバーライドできる方法ですonFinishInflate


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タグに移動すると、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">

2

私のケースは上記のようなものではなく、解決策は機能しませんでした。私の見解はレイアウト階層の深すぎると思います。私はそれを1レベル上に移動し、それはもうnullではありませんでした。


同じ問題があります。1つ上のレベルも見つかる可能性があります。これは非常に煩わしいです。メニューを思い通りに作成できないので、なぜそれが起こっているのか知りたいのですが
NaturalBornCamper

かなり深いレイアウト階層は反パターンであり、ほとんどの場合、より明確なソリューションがあります。ツールバーのオーバーフローメニュー、またはナビゲーションドロワーについて話していますか?
Deividas Strioga 2017

ナビゲーション引き出しは、私はすでにちょうどすべての項目の最後に追加し、グループ内のメニュー項目を追加すると動作していないことを除いて、実際には別の質問を投稿:stackoverflow.com/questions/47955376/...を
NaturalBornCamper

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 ...

0

私の経験では、OnDestroyViewの後にコードが呼び出された場合(フラグメントがバックスタックにある場合)にも発生する可能性があります。BroadCastReceiverからの入力でUIを更新する場合は、これが当てはまるかどうかを確認する必要があります。 。


0

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

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

例えば。fragment_layout.xml

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

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

この回答が一部のユーザーの役に立てば幸いです。



0

findViewByIdは、フラグメント内にいる場合もnullを返すことがあります。ここで説明するように:フラグメントのfindViewById

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


0

私は上記のすべてを試してみましたが、うまくいかなかったので、ImageViewを静的 にする必要がありました。それからpublic static ImageView texture;、それtexture = (ImageView) findViewById(R.id.texture_back);は良いアプローチだとは思いませんが、これは私のケースでは本当にうまくいきました:)


申し訳ありませんが、静的ビューは悪い考えだと思います
vuhung3990

0

私の場合、親オブジェクトから親によってインスタンス化されたアダプタオブジェクトに呼び出しを移動したときに、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

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

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

password = (EditText)findViewById(R.id.r_password);

0

のカスタムビューを作成しようとしたときに、同様の問題に直面していました。 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

問題をデバッグして見つける方法:

  • アクティビティ内のすべてのfindViewByIdをコメント化します。
  • onCreateとsetContentViewを除くすべてをコメント化する
  • プロジェクトを実行し、レイアウトが設定されているかどうかを確認します

私の場合、アプリモジュールとライブラリモジュールの両方でactivity_main.xmlを使用していました。したがって、上記の手順を実行すると、ライブラリで設計したレイアウトの代わりに、アプリモジュール内のレイアウトが膨らみました。

そこで、activity_main.xmlのファイル名をactivity_main_lib.xmlに変更しました。

したがって、プロジェクト全体でレイアウト名が重複していないことを確認してください

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.